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

Side by Side Diff: runtime/vm/intermediate_language_arm64.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_arm.cc ('k') | runtime/vm/intermediate_language_dbc.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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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_ARM64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
6 #if defined(TARGET_ARCH_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
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 17 matching lines...) Expand all
28 28
29 // Generic summary for call instructions that have all arguments pushed 29 // Generic summary for call instructions that have all arguments pushed
30 // on the stack and return the result in a fixed register R0. 30 // on the stack and return the result in a fixed register R0.
31 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { 31 LocationSummary* Instruction::MakeCallSummary(Zone* zone) {
32 LocationSummary* result = 32 LocationSummary* result =
33 new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); 33 new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall);
34 result->set_out(0, Location::RegisterLocation(R0)); 34 result->set_out(0, Location::RegisterLocation(R0));
35 return result; 35 return result;
36 } 36 }
37 37
38
39 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, 38 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone,
40 bool opt) const { 39 bool opt) const {
41 const intptr_t kNumInputs = 1; 40 const intptr_t kNumInputs = 1;
42 const intptr_t kNumTemps = 0; 41 const intptr_t kNumTemps = 0;
43 LocationSummary* locs = new (zone) 42 LocationSummary* locs = new (zone)
44 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 43 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
45 locs->set_in(0, Location::AnyOrConstant(value())); 44 locs->set_in(0, Location::AnyOrConstant(value()));
46 return locs; 45 return locs;
47 } 46 }
48 47
49
50 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 48 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
51 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode 49 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode
52 // where PushArgument is handled by BindInstr::EmitNativeCode. 50 // where PushArgument is handled by BindInstr::EmitNativeCode.
53 if (compiler->is_optimizing()) { 51 if (compiler->is_optimizing()) {
54 Location value = locs()->in(0); 52 Location value = locs()->in(0);
55 if (value.IsRegister()) { 53 if (value.IsRegister()) {
56 __ Push(value.reg()); 54 __ Push(value.reg());
57 } else if (value.IsConstant()) { 55 } else if (value.IsConstant()) {
58 __ PushObject(value.constant()); 56 __ PushObject(value.constant());
59 } else { 57 } else {
60 ASSERT(value.IsStackSlot()); 58 ASSERT(value.IsStackSlot());
61 const intptr_t value_offset = value.ToStackSlotOffset(); 59 const intptr_t value_offset = value.ToStackSlotOffset();
62 __ LoadFromOffset(TMP, value.base_reg(), value_offset); 60 __ LoadFromOffset(TMP, value.base_reg(), value_offset);
63 __ Push(TMP); 61 __ Push(TMP);
64 } 62 }
65 } 63 }
66 } 64 }
67 65
68
69 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { 66 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const {
70 const intptr_t kNumInputs = 1; 67 const intptr_t kNumInputs = 1;
71 const intptr_t kNumTemps = 0; 68 const intptr_t kNumTemps = 0;
72 LocationSummary* locs = new (zone) 69 LocationSummary* locs = new (zone)
73 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 70 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
74 locs->set_in(0, Location::RegisterLocation(R0)); 71 locs->set_in(0, Location::RegisterLocation(R0));
75 return locs; 72 return locs;
76 } 73 }
77 74
78
79 // Attempt optimized compilation at return instruction instead of at the entry. 75 // Attempt optimized compilation at return instruction instead of at the entry.
80 // The entry needs to be patchable, no inlined objects are allowed in the area 76 // The entry needs to be patchable, no inlined objects are allowed in the area
81 // that will be overwritten by the patch instructions: a branch macro sequence. 77 // that will be overwritten by the patch instructions: a branch macro sequence.
82 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 78 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
83 const Register result = locs()->in(0).reg(); 79 const Register result = locs()->in(0).reg();
84 ASSERT(result == R0); 80 ASSERT(result == R0);
85 81
86 if (compiler->intrinsic_mode()) { 82 if (compiler->intrinsic_mode()) {
87 // Intrinsics don't have a frame. 83 // Intrinsics don't have a frame.
88 __ ret(); 84 __ ret();
(...skipping 13 matching lines...) Expand all
102 __ Bind(&stack_ok); 98 __ Bind(&stack_ok);
103 #endif 99 #endif
104 ASSERT(__ constant_pool_allowed()); 100 ASSERT(__ constant_pool_allowed());
105 __ LeaveDartFrame(); // Disallows constant pool use. 101 __ LeaveDartFrame(); // Disallows constant pool use.
106 __ ret(); 102 __ ret();
107 // This ReturnInstr may be emitted out of order by the optimizer. The next 103 // This ReturnInstr may be emitted out of order by the optimizer. The next
108 // block may be a target expecting a properly set constant pool pointer. 104 // block may be a target expecting a properly set constant pool pointer.
109 __ set_constant_pool_allowed(true); 105 __ set_constant_pool_allowed(true);
110 } 106 }
111 107
112
113 static Condition NegateCondition(Condition condition) { 108 static Condition NegateCondition(Condition condition) {
114 switch (condition) { 109 switch (condition) {
115 case EQ: 110 case EQ:
116 return NE; 111 return NE;
117 case NE: 112 case NE:
118 return EQ; 113 return EQ;
119 case LT: 114 case LT:
120 return GE; 115 return GE;
121 case LE: 116 case LE:
122 return GT; 117 return GT;
(...skipping 12 matching lines...) Expand all
135 case VS: 130 case VS:
136 return VC; 131 return VC;
137 case VC: 132 case VC:
138 return VS; 133 return VS;
139 default: 134 default:
140 UNREACHABLE(); 135 UNREACHABLE();
141 return EQ; 136 return EQ;
142 } 137 }
143 } 138 }
144 139
145
146 // Detect pattern when one value is zero and another is a power of 2. 140 // Detect pattern when one value is zero and another is a power of 2.
147 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { 141 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
148 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || 142 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
149 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); 143 (Utils::IsPowerOfTwo(v2) && (v1 == 0));
150 } 144 }
151 145
152
153 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, 146 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone,
154 bool opt) const { 147 bool opt) const {
155 comparison()->InitializeLocationSummary(zone, opt); 148 comparison()->InitializeLocationSummary(zone, opt);
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 const Register result = locs()->out(0).reg(); 153 const Register result = locs()->out(0).reg();
162 154
163 Location left = locs()->in(0); 155 Location left = locs()->in(0);
164 Location right = locs()->in(1); 156 Location right = locs()->in(1);
165 ASSERT(!left.IsConstant() || !right.IsConstant()); 157 ASSERT(!left.IsConstant() || !right.IsConstant());
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 __ sub(result, result, Operand(1)); 194 __ sub(result, result, Operand(1));
203 const int64_t val = Smi::RawValue(true_value) - Smi::RawValue(false_value); 195 const int64_t val = Smi::RawValue(true_value) - Smi::RawValue(false_value);
204 __ AndImmediate(result, result, val); 196 __ AndImmediate(result, result, val);
205 if (false_value != 0) { 197 if (false_value != 0) {
206 __ AddImmediate(result, Smi::RawValue(false_value)); 198 __ AddImmediate(result, Smi::RawValue(false_value));
207 } 199 }
208 } 200 }
209 } 201 }
210 202
211
212 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, 203 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone,
213 bool opt) const { 204 bool opt) const {
214 const intptr_t kNumInputs = 1; 205 const intptr_t kNumInputs = 1;
215 const intptr_t kNumTemps = 0; 206 const intptr_t kNumTemps = 0;
216 LocationSummary* summary = new (zone) 207 LocationSummary* summary = new (zone)
217 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); 208 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
218 summary->set_in(0, Location::RegisterLocation(R0)); // Function. 209 summary->set_in(0, Location::RegisterLocation(R0)); // Function.
219 summary->set_out(0, Location::RegisterLocation(R0)); 210 summary->set_out(0, Location::RegisterLocation(R0));
220 return summary; 211 return summary;
221 } 212 }
222 213
223
224 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 214 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
225 // Load arguments descriptor in R4. 215 // Load arguments descriptor in R4.
226 const intptr_t argument_count = ArgumentCount(); // Includes type args. 216 const intptr_t argument_count = ArgumentCount(); // Includes type args.
227 const Array& arguments_descriptor = 217 const Array& arguments_descriptor =
228 Array::ZoneHandle(Z, GetArgumentsDescriptor()); 218 Array::ZoneHandle(Z, GetArgumentsDescriptor());
229 __ LoadObject(R4, arguments_descriptor); 219 __ LoadObject(R4, arguments_descriptor);
230 220
231 // R4: Arguments descriptor. 221 // R4: Arguments descriptor.
232 // R0: Function. 222 // R0: Function.
233 ASSERT(locs()->in(0).reg() == R0); 223 ASSERT(locs()->in(0).reg() == R0);
(...skipping 14 matching lines...) Expand all
248 compiler->AddDeoptIndexAtCall(deopt_id_after); 238 compiler->AddDeoptIndexAtCall(deopt_id_after);
249 } 239 }
250 // Add deoptimization continuation point after the call and before the 240 // Add deoptimization continuation point after the call and before the
251 // arguments are removed. 241 // arguments are removed.
252 // In optimized code this descriptor is needed for exception handling. 242 // In optimized code this descriptor is needed for exception handling.
253 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, 243 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after,
254 token_pos()); 244 token_pos());
255 __ Drop(argument_count); 245 __ Drop(argument_count);
256 } 246 }
257 247
258
259 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, 248 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone,
260 bool opt) const { 249 bool opt) const {
261 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), 250 return LocationSummary::Make(zone, 0, Location::RequiresRegister(),
262 LocationSummary::kNoCall); 251 LocationSummary::kNoCall);
263 } 252 }
264 253
265
266 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 254 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
267 const Register result = locs()->out(0).reg(); 255 const Register result = locs()->out(0).reg();
268 __ LoadFromOffset(result, FP, local().index() * kWordSize); 256 __ LoadFromOffset(result, FP, local().index() * kWordSize);
269 } 257 }
270 258
271
272 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, 259 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone,
273 bool opt) const { 260 bool opt) const {
274 return LocationSummary::Make(zone, 1, Location::SameAsFirstInput(), 261 return LocationSummary::Make(zone, 1, Location::SameAsFirstInput(),
275 LocationSummary::kNoCall); 262 LocationSummary::kNoCall);
276 } 263 }
277 264
278
279 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 265 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
280 const Register value = locs()->in(0).reg(); 266 const Register value = locs()->in(0).reg();
281 const Register result = locs()->out(0).reg(); 267 const Register result = locs()->out(0).reg();
282 ASSERT(result == value); // Assert that register assignment is correct. 268 ASSERT(result == value); // Assert that register assignment is correct.
283 __ StoreToOffset(value, FP, local().index() * kWordSize); 269 __ StoreToOffset(value, FP, local().index() * kWordSize);
284 } 270 }
285 271
286
287 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, 272 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone,
288 bool opt) const { 273 bool opt) const {
289 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), 274 return LocationSummary::Make(zone, 0, Location::RequiresRegister(),
290 LocationSummary::kNoCall); 275 LocationSummary::kNoCall);
291 } 276 }
292 277
293
294 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 278 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
295 // The register allocator drops constant definitions that have no uses. 279 // The register allocator drops constant definitions that have no uses.
296 if (!locs()->out(0).IsInvalid()) { 280 if (!locs()->out(0).IsInvalid()) {
297 const Register result = locs()->out(0).reg(); 281 const Register result = locs()->out(0).reg();
298 __ LoadObject(result, value()); 282 __ LoadObject(result, value());
299 } 283 }
300 } 284 }
301 285
302
303 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, 286 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone,
304 bool opt) const { 287 bool opt) const {
305 const intptr_t kNumInputs = 0; 288 const intptr_t kNumInputs = 0;
306 const Location out = (representation_ == kUnboxedInt32) 289 const Location out = (representation_ == kUnboxedInt32)
307 ? Location::RequiresRegister() 290 ? Location::RequiresRegister()
308 : Location::RequiresFpuRegister(); 291 : Location::RequiresFpuRegister();
309 return LocationSummary::Make(zone, kNumInputs, out, LocationSummary::kNoCall); 292 return LocationSummary::Make(zone, kNumInputs, out, LocationSummary::kNoCall);
310 } 293 }
311 294
312
313 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 295 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
314 if (!locs()->out(0).IsInvalid()) { 296 if (!locs()->out(0).IsInvalid()) {
315 switch (representation_) { 297 switch (representation_) {
316 case kUnboxedDouble: 298 case kUnboxedDouble:
317 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { 299 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) {
318 const VRegister dst = locs()->out(0).fpu_reg(); 300 const VRegister dst = locs()->out(0).fpu_reg();
319 __ veor(dst, dst, dst); 301 __ veor(dst, dst, dst);
320 } else { 302 } else {
321 const VRegister dst = locs()->out(0).fpu_reg(); 303 const VRegister dst = locs()->out(0).fpu_reg();
322 __ LoadDImmediate(dst, Double::Cast(value()).value()); 304 __ LoadDImmediate(dst, Double::Cast(value()).value());
323 } 305 }
324 break; 306 break;
325 case kUnboxedInt32: 307 case kUnboxedInt32:
326 __ LoadImmediate(locs()->out(0).reg(), 308 __ LoadImmediate(locs()->out(0).reg(),
327 static_cast<int32_t>(Smi::Cast(value()).Value())); 309 static_cast<int32_t>(Smi::Cast(value()).Value()));
328 break; 310 break;
329 default: 311 default:
330 UNREACHABLE(); 312 UNREACHABLE();
331 break; 313 break;
332 } 314 }
333 } 315 }
334 } 316 }
335 317
336
337 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, 318 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
338 bool opt) const { 319 bool opt) const {
339 const intptr_t kNumInputs = 3; 320 const intptr_t kNumInputs = 3;
340 const intptr_t kNumTemps = 0; 321 const intptr_t kNumTemps = 0;
341 LocationSummary* summary = new (zone) 322 LocationSummary* summary = new (zone)
342 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); 323 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
343 summary->set_in(0, Location::RegisterLocation(R0)); // Value. 324 summary->set_in(0, Location::RegisterLocation(R0)); // Value.
344 summary->set_in(1, Location::RegisterLocation(R1)); // Instant. type args. 325 summary->set_in(1, Location::RegisterLocation(R1)); // Instant. type args.
345 summary->set_in(2, Location::RegisterLocation(R2)); // Function type args. 326 summary->set_in(2, Location::RegisterLocation(R2)); // Function type args.
346 summary->set_out(0, Location::RegisterLocation(R0)); 327 summary->set_out(0, Location::RegisterLocation(R0));
347 return summary; 328 return summary;
348 } 329 }
349 330
350
351 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, 331 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone,
352 bool opt) const { 332 bool opt) const {
353 const intptr_t kNumInputs = 1; 333 const intptr_t kNumInputs = 1;
354 const intptr_t kNumTemps = 0; 334 const intptr_t kNumTemps = 0;
355 LocationSummary* locs = new (zone) 335 LocationSummary* locs = new (zone)
356 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); 336 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
357 locs->set_in(0, Location::RegisterLocation(R0)); 337 locs->set_in(0, Location::RegisterLocation(R0));
358 locs->set_out(0, Location::RegisterLocation(R0)); 338 locs->set_out(0, Location::RegisterLocation(R0));
359 return locs; 339 return locs;
360 } 340 }
361 341
362
363 static void EmitAssertBoolean(Register reg, 342 static void EmitAssertBoolean(Register reg,
364 TokenPosition token_pos, 343 TokenPosition token_pos,
365 intptr_t deopt_id, 344 intptr_t deopt_id,
366 LocationSummary* locs, 345 LocationSummary* locs,
367 FlowGraphCompiler* compiler) { 346 FlowGraphCompiler* compiler) {
368 // Check that the type of the value is allowed in conditional context. 347 // Check that the type of the value is allowed in conditional context.
369 // Call the runtime if the object is not bool::true or bool::false. 348 // Call the runtime if the object is not bool::true or bool::false.
370 ASSERT(locs->always_calls()); 349 ASSERT(locs->always_calls());
371 Label done; 350 Label done;
372 351
373 if (Isolate::Current()->type_checks()) { 352 if (Isolate::Current()->type_checks()) {
374 __ CompareObject(reg, Bool::True()); 353 __ CompareObject(reg, Bool::True());
375 __ b(&done, EQ); 354 __ b(&done, EQ);
376 __ CompareObject(reg, Bool::False()); 355 __ CompareObject(reg, Bool::False());
377 __ b(&done, EQ); 356 __ b(&done, EQ);
378 } else { 357 } else {
379 ASSERT(Isolate::Current()->asserts()); 358 ASSERT(Isolate::Current()->asserts());
380 __ CompareObject(reg, Object::null_instance()); 359 __ CompareObject(reg, Object::null_instance());
381 __ b(&done, NE); 360 __ b(&done, NE);
382 } 361 }
383 362
384 __ Push(reg); // Push the source object. 363 __ Push(reg); // Push the source object.
385 compiler->GenerateRuntimeCall(token_pos, deopt_id, 364 compiler->GenerateRuntimeCall(token_pos, deopt_id,
386 kNonBoolTypeErrorRuntimeEntry, 1, locs); 365 kNonBoolTypeErrorRuntimeEntry, 1, locs);
387 // We should never return here. 366 // We should never return here.
388 __ brk(0); 367 __ brk(0);
389 __ Bind(&done); 368 __ Bind(&done);
390 } 369 }
391 370
392
393 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 371 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
394 const Register obj = locs()->in(0).reg(); 372 const Register obj = locs()->in(0).reg();
395 const Register result = locs()->out(0).reg(); 373 const Register result = locs()->out(0).reg();
396 374
397 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); 375 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler);
398 ASSERT(obj == result); 376 ASSERT(obj == result);
399 } 377 }
400 378
401
402 static Condition TokenKindToSmiCondition(Token::Kind kind) { 379 static Condition TokenKindToSmiCondition(Token::Kind kind) {
403 switch (kind) { 380 switch (kind) {
404 case Token::kEQ: 381 case Token::kEQ:
405 return EQ; 382 return EQ;
406 case Token::kNE: 383 case Token::kNE:
407 return NE; 384 return NE;
408 case Token::kLT: 385 case Token::kLT:
409 return LT; 386 return LT;
410 case Token::kGT: 387 case Token::kGT:
411 return GT; 388 return GT;
412 case Token::kLTE: 389 case Token::kLTE:
413 return LE; 390 return LE;
414 case Token::kGTE: 391 case Token::kGTE:
415 return GE; 392 return GE;
416 default: 393 default:
417 UNREACHABLE(); 394 UNREACHABLE();
418 return VS; 395 return VS;
419 } 396 }
420 } 397 }
421 398
422
423 static Condition FlipCondition(Condition condition) { 399 static Condition FlipCondition(Condition condition) {
424 switch (condition) { 400 switch (condition) {
425 case EQ: 401 case EQ:
426 return EQ; 402 return EQ;
427 case NE: 403 case NE:
428 return NE; 404 return NE;
429 case LT: 405 case LT:
430 return GT; 406 return GT;
431 case LE: 407 case LE:
432 return GE; 408 return GE;
433 case GT: 409 case GT:
434 return LT; 410 return LT;
435 case GE: 411 case GE:
436 return LE; 412 return LE;
437 case CC: 413 case CC:
438 return HI; 414 return HI;
439 case LS: 415 case LS:
440 return CS; 416 return CS;
441 case HI: 417 case HI:
442 return CC; 418 return CC;
443 case CS: 419 case CS:
444 return LS; 420 return LS;
445 default: 421 default:
446 UNREACHABLE(); 422 UNREACHABLE();
447 return EQ; 423 return EQ;
448 } 424 }
449 } 425 }
450 426
451
452 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, 427 static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
453 Condition true_condition, 428 Condition true_condition,
454 BranchLabels labels) { 429 BranchLabels labels) {
455 if (labels.fall_through == labels.false_label) { 430 if (labels.fall_through == labels.false_label) {
456 // If the next block is the false successor we will fall through to it. 431 // If the next block is the false successor we will fall through to it.
457 __ b(labels.true_label, true_condition); 432 __ b(labels.true_label, true_condition);
458 } else { 433 } else {
459 // If the next block is not the false successor we will branch to it. 434 // If the next block is not the false successor we will branch to it.
460 Condition false_condition = NegateCondition(true_condition); 435 Condition false_condition = NegateCondition(true_condition);
461 __ b(labels.false_label, false_condition); 436 __ b(labels.false_label, false_condition);
462 437
463 // Fall through or jump to the true successor. 438 // Fall through or jump to the true successor.
464 if (labels.fall_through != labels.true_label) { 439 if (labels.fall_through != labels.true_label) {
465 __ b(labels.true_label); 440 __ b(labels.true_label);
466 } 441 }
467 } 442 }
468 } 443 }
469 444
470
471 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, 445 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
472 LocationSummary* locs, 446 LocationSummary* locs,
473 Token::Kind kind) { 447 Token::Kind kind) {
474 Location left = locs->in(0); 448 Location left = locs->in(0);
475 Location right = locs->in(1); 449 Location right = locs->in(1);
476 ASSERT(!left.IsConstant() || !right.IsConstant()); 450 ASSERT(!left.IsConstant() || !right.IsConstant());
477 451
478 Condition true_condition = TokenKindToSmiCondition(kind); 452 Condition true_condition = TokenKindToSmiCondition(kind);
479 453
480 if (left.IsConstant()) { 454 if (left.IsConstant()) {
481 __ CompareObject(right.reg(), left.constant()); 455 __ CompareObject(right.reg(), left.constant());
482 true_condition = FlipCondition(true_condition); 456 true_condition = FlipCondition(true_condition);
483 } else if (right.IsConstant()) { 457 } else if (right.IsConstant()) {
484 __ CompareObject(left.reg(), right.constant()); 458 __ CompareObject(left.reg(), right.constant());
485 } else { 459 } else {
486 __ CompareRegisters(left.reg(), right.reg()); 460 __ CompareRegisters(left.reg(), right.reg());
487 } 461 }
488 return true_condition; 462 return true_condition;
489 } 463 }
490 464
491
492 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, 465 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone,
493 bool opt) const { 466 bool opt) const {
494 const intptr_t kNumInputs = 2; 467 const intptr_t kNumInputs = 2;
495 if (operation_cid() == kDoubleCid) { 468 if (operation_cid() == kDoubleCid) {
496 const intptr_t kNumTemps = 0; 469 const intptr_t kNumTemps = 0;
497 LocationSummary* locs = new (zone) 470 LocationSummary* locs = new (zone)
498 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 471 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
499 locs->set_in(0, Location::RequiresFpuRegister()); 472 locs->set_in(0, Location::RequiresFpuRegister());
500 locs->set_in(1, Location::RequiresFpuRegister()); 473 locs->set_in(1, Location::RequiresFpuRegister());
501 locs->set_out(0, Location::RequiresRegister()); 474 locs->set_out(0, Location::RequiresRegister());
(...skipping 10 matching lines...) Expand all
512 locs->set_in(1, locs->in(0).IsConstant() 485 locs->set_in(1, locs->in(0).IsConstant()
513 ? Location::RequiresRegister() 486 ? Location::RequiresRegister()
514 : Location::RegisterOrConstant(right())); 487 : Location::RegisterOrConstant(right()));
515 locs->set_out(0, Location::RequiresRegister()); 488 locs->set_out(0, Location::RequiresRegister());
516 return locs; 489 return locs;
517 } 490 }
518 UNREACHABLE(); 491 UNREACHABLE();
519 return NULL; 492 return NULL;
520 } 493 }
521 494
522
523 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 495 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
524 switch (kind) { 496 switch (kind) {
525 case Token::kEQ: 497 case Token::kEQ:
526 return EQ; 498 return EQ;
527 case Token::kNE: 499 case Token::kNE:
528 return NE; 500 return NE;
529 case Token::kLT: 501 case Token::kLT:
530 return LT; 502 return LT;
531 case Token::kGT: 503 case Token::kGT:
532 return GT; 504 return GT;
533 case Token::kLTE: 505 case Token::kLTE:
534 return LE; 506 return LE;
535 case Token::kGTE: 507 case Token::kGTE:
536 return GE; 508 return GE;
537 default: 509 default:
538 UNREACHABLE(); 510 UNREACHABLE();
539 return VS; 511 return VS;
540 } 512 }
541 } 513 }
542 514
543
544 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 515 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
545 LocationSummary* locs, 516 LocationSummary* locs,
546 BranchLabels labels, 517 BranchLabels labels,
547 Token::Kind kind) { 518 Token::Kind kind) {
548 const VRegister left = locs->in(0).fpu_reg(); 519 const VRegister left = locs->in(0).fpu_reg();
549 const VRegister right = locs->in(1).fpu_reg(); 520 const VRegister right = locs->in(1).fpu_reg();
550 __ fcmpd(left, right); 521 __ fcmpd(left, right);
551 Condition true_condition = TokenKindToDoubleCondition(kind); 522 Condition true_condition = TokenKindToDoubleCondition(kind);
552 if (true_condition != NE) { 523 if (true_condition != NE) {
553 // Special case for NaN comparison. Result is always false unless 524 // Special case for NaN comparison. Result is always false unless
554 // relational operator is !=. 525 // relational operator is !=.
555 __ b(labels.false_label, VS); 526 __ b(labels.false_label, VS);
556 } 527 }
557 return true_condition; 528 return true_condition;
558 } 529 }
559 530
560
561 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 531 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
562 BranchLabels labels) { 532 BranchLabels labels) {
563 if (operation_cid() == kSmiCid) { 533 if (operation_cid() == kSmiCid) {
564 return EmitSmiComparisonOp(compiler, locs(), kind()); 534 return EmitSmiComparisonOp(compiler, locs(), kind());
565 } else { 535 } else {
566 ASSERT(operation_cid() == kDoubleCid); 536 ASSERT(operation_cid() == kDoubleCid);
567 return EmitDoubleComparisonOp(compiler, locs(), labels, kind()); 537 return EmitDoubleComparisonOp(compiler, locs(), labels, kind());
568 } 538 }
569 } 539 }
570 540
571
572 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { 541 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const {
573 const intptr_t kNumInputs = 2; 542 const intptr_t kNumInputs = 2;
574 const intptr_t kNumTemps = 0; 543 const intptr_t kNumTemps = 0;
575 LocationSummary* locs = new (zone) 544 LocationSummary* locs = new (zone)
576 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 545 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
577 locs->set_in(0, Location::RequiresRegister()); 546 locs->set_in(0, Location::RequiresRegister());
578 // Only one input can be a constant operand. The case of two constant 547 // Only one input can be a constant operand. The case of two constant
579 // operands should be handled by constant propagation. 548 // operands should be handled by constant propagation.
580 locs->set_in(1, Location::RegisterOrConstant(right())); 549 locs->set_in(1, Location::RegisterOrConstant(right()));
581 return locs; 550 return locs;
582 } 551 }
583 552
584
585 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 553 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
586 BranchLabels labels) { 554 BranchLabels labels) {
587 const Register left = locs()->in(0).reg(); 555 const Register left = locs()->in(0).reg();
588 Location right = locs()->in(1); 556 Location right = locs()->in(1);
589 if (right.IsConstant()) { 557 if (right.IsConstant()) {
590 ASSERT(right.constant().IsSmi()); 558 ASSERT(right.constant().IsSmi());
591 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); 559 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw());
592 __ TestImmediate(left, imm); 560 __ TestImmediate(left, imm);
593 } else { 561 } else {
594 __ tst(left, Operand(right.reg())); 562 __ tst(left, Operand(right.reg()));
595 } 563 }
596 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; 564 Condition true_condition = (kind() == Token::kNE) ? NE : EQ;
597 return true_condition; 565 return true_condition;
598 } 566 }
599 567
600
601 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, 568 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone,
602 bool opt) const { 569 bool opt) const {
603 const intptr_t kNumInputs = 1; 570 const intptr_t kNumInputs = 1;
604 const intptr_t kNumTemps = 1; 571 const intptr_t kNumTemps = 1;
605 LocationSummary* locs = new (zone) 572 LocationSummary* locs = new (zone)
606 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 573 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
607 locs->set_in(0, Location::RequiresRegister()); 574 locs->set_in(0, Location::RequiresRegister());
608 locs->set_temp(0, Location::RequiresRegister()); 575 locs->set_temp(0, Location::RequiresRegister());
609 locs->set_out(0, Location::RequiresRegister()); 576 locs->set_out(0, Location::RequiresRegister());
610 return locs; 577 return locs;
611 } 578 }
612 579
613
614 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 580 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
615 BranchLabels labels) { 581 BranchLabels labels) {
616 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); 582 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT));
617 const Register val_reg = locs()->in(0).reg(); 583 const Register val_reg = locs()->in(0).reg();
618 const Register cid_reg = locs()->temp(0).reg(); 584 const Register cid_reg = locs()->temp(0).reg();
619 585
620 Label* deopt = 586 Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub(
621 CanDeoptimize() 587 deopt_id(), ICData::kDeoptTestCids,
622 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, 588 licm_hoisted_ ? ICData::kHoisted : 0)
623 licm_hoisted_ ? ICData::kHoisted : 0) 589 : NULL;
624 : NULL;
625 590
626 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; 591 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
627 const ZoneGrowableArray<intptr_t>& data = cid_results(); 592 const ZoneGrowableArray<intptr_t>& data = cid_results();
628 ASSERT(data[0] == kSmiCid); 593 ASSERT(data[0] == kSmiCid);
629 bool result = data[1] == true_result; 594 bool result = data[1] == true_result;
630 __ tsti(val_reg, Immediate(kSmiTagMask)); 595 __ tsti(val_reg, Immediate(kSmiTagMask));
631 __ b(result ? labels.true_label : labels.false_label, EQ); 596 __ b(result ? labels.true_label : labels.false_label, EQ);
632 __ LoadClassId(cid_reg, val_reg); 597 __ LoadClassId(cid_reg, val_reg);
633 598
634 for (intptr_t i = 2; i < data.length(); i += 2) { 599 for (intptr_t i = 2; i < data.length(); i += 2) {
(...skipping 13 matching lines...) Expand all
648 __ b(target); 613 __ b(target);
649 } 614 }
650 } else { 615 } else {
651 __ b(deopt); 616 __ b(deopt);
652 } 617 }
653 // Dummy result as this method already did the jump, there's no need 618 // Dummy result as this method already did the jump, there's no need
654 // for the caller to branch on a condition. 619 // for the caller to branch on a condition.
655 return kInvalidCondition; 620 return kInvalidCondition;
656 } 621 }
657 622
658
659 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, 623 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone,
660 bool opt) const { 624 bool opt) const {
661 const intptr_t kNumInputs = 2; 625 const intptr_t kNumInputs = 2;
662 const intptr_t kNumTemps = 0; 626 const intptr_t kNumTemps = 0;
663 if (operation_cid() == kDoubleCid) { 627 if (operation_cid() == kDoubleCid) {
664 LocationSummary* summary = new (zone) 628 LocationSummary* summary = new (zone)
665 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 629 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
666 summary->set_in(0, Location::RequiresFpuRegister()); 630 summary->set_in(0, Location::RequiresFpuRegister());
667 summary->set_in(1, Location::RequiresFpuRegister()); 631 summary->set_in(1, Location::RequiresFpuRegister());
668 summary->set_out(0, Location::RequiresRegister()); 632 summary->set_out(0, Location::RequiresRegister());
669 return summary; 633 return summary;
670 } 634 }
671 ASSERT(operation_cid() == kSmiCid); 635 ASSERT(operation_cid() == kSmiCid);
672 LocationSummary* summary = new (zone) 636 LocationSummary* summary = new (zone)
673 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 637 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
674 summary->set_in(0, Location::RegisterOrConstant(left())); 638 summary->set_in(0, Location::RegisterOrConstant(left()));
675 // Only one input can be a constant operand. The case of two constant 639 // Only one input can be a constant operand. The case of two constant
676 // operands should be handled by constant propagation. 640 // operands should be handled by constant propagation.
677 summary->set_in(1, summary->in(0).IsConstant() 641 summary->set_in(1, summary->in(0).IsConstant()
678 ? Location::RequiresRegister() 642 ? Location::RequiresRegister()
679 : Location::RegisterOrConstant(right())); 643 : Location::RegisterOrConstant(right()));
680 summary->set_out(0, Location::RequiresRegister()); 644 summary->set_out(0, Location::RequiresRegister());
681 return summary; 645 return summary;
682 } 646 }
683 647
684
685 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 648 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
686 BranchLabels labels) { 649 BranchLabels labels) {
687 if (operation_cid() == kSmiCid) { 650 if (operation_cid() == kSmiCid) {
688 return EmitSmiComparisonOp(compiler, locs(), kind()); 651 return EmitSmiComparisonOp(compiler, locs(), kind());
689 } else { 652 } else {
690 ASSERT(operation_cid() == kDoubleCid); 653 ASSERT(operation_cid() == kDoubleCid);
691 return EmitDoubleComparisonOp(compiler, locs(), labels, kind()); 654 return EmitDoubleComparisonOp(compiler, locs(), labels, kind());
692 } 655 }
693 } 656 }
694 657
695
696 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, 658 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
697 bool opt) const { 659 bool opt) const {
698 return MakeCallSummary(zone); 660 return MakeCallSummary(zone);
699 } 661 }
700 662
701
702 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 663 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
703 SetupNative(); 664 SetupNative();
704 const Register result = locs()->out(0).reg(); 665 const Register result = locs()->out(0).reg();
705 666
706 // Push the result place holder initialized to NULL. 667 // Push the result place holder initialized to NULL.
707 __ PushObject(Object::null_object()); 668 __ PushObject(Object::null_object());
708 // Pass a pointer to the first argument in R2. 669 // Pass a pointer to the first argument in R2.
709 if (!function().HasOptionalParameters()) { 670 if (!function().HasOptionalParameters()) {
710 __ AddImmediate( 671 __ AddImmediate(
711 R2, FP, (kParamEndSlotFromFp + function().NumParameters()) * kWordSize); 672 R2, FP, (kParamEndSlotFromFp + function().NumParameters()) * kWordSize);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 if (link_lazily()) { 708 if (link_lazily()) {
748 compiler->GeneratePatchableCall(token_pos(), *stub_entry, 709 compiler->GeneratePatchableCall(token_pos(), *stub_entry,
749 RawPcDescriptors::kOther, locs()); 710 RawPcDescriptors::kOther, locs());
750 } else { 711 } else {
751 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, 712 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
752 locs()); 713 locs());
753 } 714 }
754 __ Pop(result); 715 __ Pop(result);
755 } 716 }
756 717
757
758 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( 718 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
759 Zone* zone, 719 Zone* zone,
760 bool opt) const { 720 bool opt) const {
761 const intptr_t kNumInputs = 1; 721 const intptr_t kNumInputs = 1;
762 // TODO(fschneider): Allow immediate operands for the char code. 722 // TODO(fschneider): Allow immediate operands for the char code.
763 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), 723 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(),
764 LocationSummary::kNoCall); 724 LocationSummary::kNoCall);
765 } 725 }
766 726
767
768 void OneByteStringFromCharCodeInstr::EmitNativeCode( 727 void OneByteStringFromCharCodeInstr::EmitNativeCode(
769 FlowGraphCompiler* compiler) { 728 FlowGraphCompiler* compiler) {
770 ASSERT(compiler->is_optimizing()); 729 ASSERT(compiler->is_optimizing());
771 const Register char_code = locs()->in(0).reg(); 730 const Register char_code = locs()->in(0).reg();
772 const Register result = locs()->out(0).reg(); 731 const Register result = locs()->out(0).reg();
773 732
774 __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset())); 733 __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset()));
775 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); 734 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize);
776 __ SmiUntag(TMP, char_code); // Untag to use scaled address mode. 735 __ SmiUntag(TMP, char_code); // Untag to use scaled address mode.
777 __ ldr(result, Address(result, TMP, UXTX, Address::Scaled)); 736 __ ldr(result, Address(result, TMP, UXTX, Address::Scaled));
778 } 737 }
779 738
780
781 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, 739 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone,
782 bool opt) const { 740 bool opt) const {
783 const intptr_t kNumInputs = 1; 741 const intptr_t kNumInputs = 1;
784 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), 742 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(),
785 LocationSummary::kNoCall); 743 LocationSummary::kNoCall);
786 } 744 }
787 745
788
789 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 746 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
790 ASSERT(cid_ == kOneByteStringCid); 747 ASSERT(cid_ == kOneByteStringCid);
791 const Register str = locs()->in(0).reg(); 748 const Register str = locs()->in(0).reg();
792 const Register result = locs()->out(0).reg(); 749 const Register result = locs()->out(0).reg();
793 __ LoadFieldFromOffset(result, str, String::length_offset()); 750 __ LoadFieldFromOffset(result, str, String::length_offset());
794 __ ldr(TMP, FieldAddress(str, OneByteString::data_offset()), kUnsignedByte); 751 __ ldr(TMP, FieldAddress(str, OneByteString::data_offset()), kUnsignedByte);
795 __ CompareImmediate(result, Smi::RawValue(1)); 752 __ CompareImmediate(result, Smi::RawValue(1));
796 __ LoadImmediate(result, -1); 753 __ LoadImmediate(result, -1);
797 __ csel(result, TMP, result, EQ); 754 __ csel(result, TMP, result, EQ);
798 __ SmiTag(result); 755 __ SmiTag(result);
799 } 756 }
800 757
801
802 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, 758 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone,
803 bool opt) const { 759 bool opt) const {
804 const intptr_t kNumInputs = 1; 760 const intptr_t kNumInputs = 1;
805 const intptr_t kNumTemps = 0; 761 const intptr_t kNumTemps = 0;
806 LocationSummary* summary = new (zone) 762 LocationSummary* summary = new (zone)
807 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); 763 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
808 summary->set_in(0, Location::RegisterLocation(R0)); 764 summary->set_in(0, Location::RegisterLocation(R0));
809 summary->set_out(0, Location::RegisterLocation(R0)); 765 summary->set_out(0, Location::RegisterLocation(R0));
810 return summary; 766 return summary;
811 } 767 }
812 768
813
814 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 769 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
815 const Register array = locs()->in(0).reg(); 770 const Register array = locs()->in(0).reg();
816 __ Push(array); 771 __ Push(array);
817 const int kTypeArgsLen = 0; 772 const int kTypeArgsLen = 0;
818 const int kNumberOfArguments = 1; 773 const int kNumberOfArguments = 1;
819 const Array& kNoArgumentNames = Object::null_array(); 774 const Array& kNoArgumentNames = Object::null_array();
820 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); 775 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
821 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), 776 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
822 args_info, locs(), ICData::Handle()); 777 args_info, locs(), ICData::Handle());
823 ASSERT(locs()->out(0).reg() == R0); 778 ASSERT(locs()->out(0).reg() == R0);
824 } 779 }
825 780
826
827 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, 781 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone,
828 bool opt) const { 782 bool opt) const {
829 const intptr_t kNumInputs = 1; 783 const intptr_t kNumInputs = 1;
830 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), 784 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(),
831 LocationSummary::kNoCall); 785 LocationSummary::kNoCall);
832 } 786 }
833 787
834
835 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 788 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
836 const Register obj = locs()->in(0).reg(); 789 const Register obj = locs()->in(0).reg();
837 const Register result = locs()->out(0).reg(); 790 const Register result = locs()->out(0).reg();
838 if (object()->definition()->representation() == kUntagged) { 791 if (object()->definition()->representation() == kUntagged) {
839 __ LoadFromOffset(result, obj, offset()); 792 __ LoadFromOffset(result, obj, offset());
840 } else { 793 } else {
841 ASSERT(object()->definition()->representation() == kTagged); 794 ASSERT(object()->definition()->representation() == kTagged);
842 __ LoadFieldFromOffset(result, obj, offset()); 795 __ LoadFieldFromOffset(result, obj, offset());
843 } 796 }
844 } 797 }
845 798
846
847 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, 799 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone,
848 bool opt) const { 800 bool opt) const {
849 const intptr_t kNumInputs = 1; 801 const intptr_t kNumInputs = 1;
850 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), 802 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(),
851 LocationSummary::kNoCall); 803 LocationSummary::kNoCall);
852 } 804 }
853 805
854
855 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 806 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
856 const Register object = locs()->in(0).reg(); 807 const Register object = locs()->in(0).reg();
857 const Register result = locs()->out(0).reg(); 808 const Register result = locs()->out(0).reg();
858 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); 809 const AbstractType& value_type = *this->object()->Type()->ToAbstractType();
859 if (CompileType::Smi().IsAssignableTo(value_type) || 810 if (CompileType::Smi().IsAssignableTo(value_type) ||
860 value_type.IsTypeParameter()) { 811 value_type.IsTypeParameter()) {
861 __ LoadTaggedClassIdMayBeSmi(result, object); 812 __ LoadTaggedClassIdMayBeSmi(result, object);
862 } else { 813 } else {
863 __ LoadClassId(result, object); 814 __ LoadClassId(result, object);
864 __ SmiTag(result); 815 __ SmiTag(result);
865 } 816 }
866 } 817 }
867 818
868
869 CompileType LoadIndexedInstr::ComputeType() const { 819 CompileType LoadIndexedInstr::ComputeType() const {
870 switch (class_id_) { 820 switch (class_id_) {
871 case kArrayCid: 821 case kArrayCid:
872 case kImmutableArrayCid: 822 case kImmutableArrayCid:
873 return CompileType::Dynamic(); 823 return CompileType::Dynamic();
874 824
875 case kTypedDataFloat32ArrayCid: 825 case kTypedDataFloat32ArrayCid:
876 case kTypedDataFloat64ArrayCid: 826 case kTypedDataFloat64ArrayCid:
877 return CompileType::FromCid(kDoubleCid); 827 return CompileType::FromCid(kDoubleCid);
878 case kTypedDataFloat32x4ArrayCid: 828 case kTypedDataFloat32x4ArrayCid:
(...skipping 17 matching lines...) Expand all
896 case kTypedDataInt32ArrayCid: 846 case kTypedDataInt32ArrayCid:
897 case kTypedDataUint32ArrayCid: 847 case kTypedDataUint32ArrayCid:
898 return CompileType::FromCid(kSmiCid); 848 return CompileType::FromCid(kSmiCid);
899 849
900 default: 850 default:
901 UNIMPLEMENTED(); 851 UNIMPLEMENTED();
902 return CompileType::Dynamic(); 852 return CompileType::Dynamic();
903 } 853 }
904 } 854 }
905 855
906
907 Representation LoadIndexedInstr::representation() const { 856 Representation LoadIndexedInstr::representation() const {
908 switch (class_id_) { 857 switch (class_id_) {
909 case kArrayCid: 858 case kArrayCid:
910 case kImmutableArrayCid: 859 case kImmutableArrayCid:
911 case kTypedDataInt8ArrayCid: 860 case kTypedDataInt8ArrayCid:
912 case kTypedDataUint8ArrayCid: 861 case kTypedDataUint8ArrayCid:
913 case kTypedDataUint8ClampedArrayCid: 862 case kTypedDataUint8ClampedArrayCid:
914 case kExternalTypedDataUint8ArrayCid: 863 case kExternalTypedDataUint8ArrayCid:
915 case kExternalTypedDataUint8ClampedArrayCid: 864 case kExternalTypedDataUint8ClampedArrayCid:
916 case kTypedDataInt16ArrayCid: 865 case kTypedDataInt16ArrayCid:
(...skipping 15 matching lines...) Expand all
932 case kTypedDataFloat32x4ArrayCid: 881 case kTypedDataFloat32x4ArrayCid:
933 return kUnboxedFloat32x4; 882 return kUnboxedFloat32x4;
934 case kTypedDataFloat64x2ArrayCid: 883 case kTypedDataFloat64x2ArrayCid:
935 return kUnboxedFloat64x2; 884 return kUnboxedFloat64x2;
936 default: 885 default:
937 UNIMPLEMENTED(); 886 UNIMPLEMENTED();
938 return kTagged; 887 return kTagged;
939 } 888 }
940 } 889 }
941 890
942
943 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) { 891 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) {
944 ConstantInstr* constant = value->definition()->AsConstant(); 892 ConstantInstr* constant = value->definition()->AsConstant();
945 if ((constant == NULL) || !constant->value().IsSmi()) { 893 if ((constant == NULL) || !constant->value().IsSmi()) {
946 return false; 894 return false;
947 } 895 }
948 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); 896 const int64_t index = Smi::Cast(constant->value()).AsInt64Value();
949 const intptr_t scale = Instance::ElementSizeFor(cid); 897 const intptr_t scale = Instance::ElementSizeFor(cid);
950 const int64_t offset = 898 const int64_t offset =
951 index * scale + 899 index * scale +
952 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); 900 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
953 if (!Utils::IsInt(32, offset)) { 901 if (!Utils::IsInt(32, offset)) {
954 return false; 902 return false;
955 } 903 }
956 return Address::CanHoldOffset(static_cast<int32_t>(offset), Address::Offset, 904 return Address::CanHoldOffset(static_cast<int32_t>(offset), Address::Offset,
957 Address::OperandSizeFor(cid)); 905 Address::OperandSizeFor(cid));
958 } 906 }
959 907
960
961 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, 908 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone,
962 bool opt) const { 909 bool opt) const {
963 const intptr_t kNumInputs = 2; 910 const intptr_t kNumInputs = 2;
964 const intptr_t kNumTemps = aligned() ? 0 : 1; 911 const intptr_t kNumTemps = aligned() ? 0 : 1;
965 LocationSummary* locs = new (zone) 912 LocationSummary* locs = new (zone)
966 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 913 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
967 locs->set_in(0, Location::RequiresRegister()); 914 locs->set_in(0, Location::RequiresRegister());
968 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { 915 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) {
969 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); 916 locs->set_in(1, Location::Constant(index()->definition()->AsConstant()));
970 } else { 917 } else {
971 locs->set_in(1, Location::RequiresRegister()); 918 locs->set_in(1, Location::RequiresRegister());
972 } 919 }
973 if ((representation() == kUnboxedDouble) || 920 if ((representation() == kUnboxedDouble) ||
974 (representation() == kUnboxedFloat32x4) || 921 (representation() == kUnboxedFloat32x4) ||
975 (representation() == kUnboxedInt32x4) || 922 (representation() == kUnboxedInt32x4) ||
976 (representation() == kUnboxedFloat64x2)) { 923 (representation() == kUnboxedFloat64x2)) {
977 locs->set_out(0, Location::RequiresFpuRegister()); 924 locs->set_out(0, Location::RequiresFpuRegister());
978 } else { 925 } else {
979 locs->set_out(0, Location::RequiresRegister()); 926 locs->set_out(0, Location::RequiresRegister());
980 } 927 }
981 if (!aligned()) { 928 if (!aligned()) {
982 locs->set_temp(0, Location::RequiresRegister()); 929 locs->set_temp(0, Location::RequiresRegister());
983 } 930 }
984 return locs; 931 return locs;
985 } 932 }
986 933
987
988 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 934 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
989 // The array register points to the backing store for external arrays. 935 // The array register points to the backing store for external arrays.
990 const Register array = locs()->in(0).reg(); 936 const Register array = locs()->in(0).reg();
991 const Location index = locs()->in(1); 937 const Location index = locs()->in(1);
992 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); 938 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg();
993 939
994 Address element_address(TMP); // Bad address. 940 Address element_address(TMP); // Bad address.
995 if (aligned()) { 941 if (aligned()) {
996 element_address = 942 element_address =
997 index.IsRegister() 943 index.IsRegister()
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 __ SmiTag(result); 1061 __ SmiTag(result);
1116 break; 1062 break;
1117 default: 1063 default:
1118 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); 1064 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
1119 ASSERT(aligned()); 1065 ASSERT(aligned());
1120 __ ldr(result, element_address); 1066 __ ldr(result, element_address);
1121 break; 1067 break;
1122 } 1068 }
1123 } 1069 }
1124 1070
1125
1126 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, 1071 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone,
1127 bool opt) const { 1072 bool opt) const {
1128 const intptr_t kNumInputs = 2; 1073 const intptr_t kNumInputs = 2;
1129 const intptr_t kNumTemps = 0; 1074 const intptr_t kNumTemps = 0;
1130 LocationSummary* summary = new (zone) 1075 LocationSummary* summary = new (zone)
1131 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 1076 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
1132 summary->set_in(0, Location::RequiresRegister()); 1077 summary->set_in(0, Location::RequiresRegister());
1133 summary->set_in(1, Location::RequiresRegister()); 1078 summary->set_in(1, Location::RequiresRegister());
1134 summary->set_out(0, Location::RequiresRegister()); 1079 summary->set_out(0, Location::RequiresRegister());
1135 return summary; 1080 return summary;
1136 } 1081 }
1137 1082
1138
1139 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1083 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1140 // The string register points to the backing store for external strings. 1084 // The string register points to the backing store for external strings.
1141 const Register str = locs()->in(0).reg(); 1085 const Register str = locs()->in(0).reg();
1142 const Location index = locs()->in(1); 1086 const Location index = locs()->in(1);
1143 1087
1144 Address element_address = __ ElementAddressForRegIndex( 1088 Address element_address = __ ElementAddressForRegIndex(
1145 true, IsExternal(), class_id(), index_scale(), str, index.reg()); 1089 true, IsExternal(), class_id(), index_scale(), str, index.reg());
1146 // Warning: element_address may use register TMP as base. 1090 // Warning: element_address may use register TMP as base.
1147 1091
1148 Register result = locs()->out(0).reg(); 1092 Register result = locs()->out(0).reg();
(...skipping 28 matching lines...) Expand all
1177 UNREACHABLE(); 1121 UNREACHABLE();
1178 } 1122 }
1179 __ SmiTag(result); 1123 __ SmiTag(result);
1180 break; 1124 break;
1181 default: 1125 default:
1182 UNREACHABLE(); 1126 UNREACHABLE();
1183 break; 1127 break;
1184 } 1128 }
1185 } 1129 }
1186 1130
1187
1188 Representation StoreIndexedInstr::RequiredInputRepresentation( 1131 Representation StoreIndexedInstr::RequiredInputRepresentation(
1189 intptr_t idx) const { 1132 intptr_t idx) const {
1190 // Array can be a Dart object or a pointer to external data. 1133 // Array can be a Dart object or a pointer to external data.
1191 if (idx == 0) return kNoRepresentation; // Flexible input representation. 1134 if (idx == 0) return kNoRepresentation; // Flexible input representation.
1192 if (idx == 1) return kTagged; // Index is a smi. 1135 if (idx == 1) return kTagged; // Index is a smi.
1193 ASSERT(idx == 2); 1136 ASSERT(idx == 2);
1194 switch (class_id_) { 1137 switch (class_id_) {
1195 case kArrayCid: 1138 case kArrayCid:
1196 case kOneByteStringCid: 1139 case kOneByteStringCid:
1197 case kTypedDataInt8ArrayCid: 1140 case kTypedDataInt8ArrayCid:
(...skipping 16 matching lines...) Expand all
1214 case kTypedDataInt32x4ArrayCid: 1157 case kTypedDataInt32x4ArrayCid:
1215 return kUnboxedInt32x4; 1158 return kUnboxedInt32x4;
1216 case kTypedDataFloat64x2ArrayCid: 1159 case kTypedDataFloat64x2ArrayCid:
1217 return kUnboxedFloat64x2; 1160 return kUnboxedFloat64x2;
1218 default: 1161 default:
1219 UNREACHABLE(); 1162 UNREACHABLE();
1220 return kTagged; 1163 return kTagged;
1221 } 1164 }
1222 } 1165 }
1223 1166
1224
1225 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, 1167 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
1226 bool opt) const { 1168 bool opt) const {
1227 const intptr_t kNumInputs = 3; 1169 const intptr_t kNumInputs = 3;
1228 const intptr_t kNumTemps = aligned() ? 0 : 2; 1170 const intptr_t kNumTemps = aligned() ? 0 : 2;
1229 LocationSummary* locs = new (zone) 1171 LocationSummary* locs = new (zone)
1230 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 1172 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
1231 locs->set_in(0, Location::RequiresRegister()); 1173 locs->set_in(0, Location::RequiresRegister());
1232 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { 1174 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) {
1233 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); 1175 locs->set_in(1, Location::Constant(index()->definition()->AsConstant()));
1234 } else { 1176 } else {
(...skipping 30 matching lines...) Expand all
1265 UNREACHABLE(); 1207 UNREACHABLE();
1266 return NULL; 1208 return NULL;
1267 } 1209 }
1268 if (!aligned()) { 1210 if (!aligned()) {
1269 locs->set_temp(0, Location::RequiresRegister()); 1211 locs->set_temp(0, Location::RequiresRegister());
1270 locs->set_temp(1, Location::RequiresRegister()); 1212 locs->set_temp(1, Location::RequiresRegister());
1271 } 1213 }
1272 return locs; 1214 return locs;
1273 } 1215 }
1274 1216
1275
1276 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1217 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1277 // The array register points to the backing store for external arrays. 1218 // The array register points to the backing store for external arrays.
1278 const Register array = locs()->in(0).reg(); 1219 const Register array = locs()->in(0).reg();
1279 const Location index = locs()->in(1); 1220 const Location index = locs()->in(1);
1280 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); 1221 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg();
1281 const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg(); 1222 const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg();
1282 1223
1283 Address element_address(TMP); // Bad address. 1224 Address element_address(TMP); // Bad address.
1284 if (aligned()) { 1225 if (aligned()) {
1285 element_address = 1226 element_address =
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1405 ASSERT(aligned()); 1346 ASSERT(aligned());
1406 const VRegister value_reg = locs()->in(2).fpu_reg(); 1347 const VRegister value_reg = locs()->in(2).fpu_reg();
1407 __ fstrq(value_reg, element_address); 1348 __ fstrq(value_reg, element_address);
1408 break; 1349 break;
1409 } 1350 }
1410 default: 1351 default:
1411 UNREACHABLE(); 1352 UNREACHABLE();
1412 } 1353 }
1413 } 1354 }
1414 1355
1415
1416 static void LoadValueCid(FlowGraphCompiler* compiler, 1356 static void LoadValueCid(FlowGraphCompiler* compiler,
1417 Register value_cid_reg, 1357 Register value_cid_reg,
1418 Register value_reg, 1358 Register value_reg,
1419 Label* value_is_smi = NULL) { 1359 Label* value_is_smi = NULL) {
1420 Label done; 1360 Label done;
1421 if (value_is_smi == NULL) { 1361 if (value_is_smi == NULL) {
1422 __ LoadImmediate(value_cid_reg, kSmiCid); 1362 __ LoadImmediate(value_cid_reg, kSmiCid);
1423 } 1363 }
1424 __ tsti(value_reg, Immediate(kSmiTagMask)); 1364 __ tsti(value_reg, Immediate(kSmiTagMask));
1425 if (value_is_smi == NULL) { 1365 if (value_is_smi == NULL) {
1426 __ b(&done, EQ); 1366 __ b(&done, EQ);
1427 } else { 1367 } else {
1428 __ b(value_is_smi, EQ); 1368 __ b(value_is_smi, EQ);
1429 } 1369 }
1430 __ LoadClassId(value_cid_reg, value_reg); 1370 __ LoadClassId(value_cid_reg, value_reg);
1431 __ Bind(&done); 1371 __ Bind(&done);
1432 } 1372 }
1433 1373
1434
1435 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, 1374 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone,
1436 bool opt) const { 1375 bool opt) const {
1437 const intptr_t kNumInputs = 1; 1376 const intptr_t kNumInputs = 1;
1438 1377
1439 const intptr_t value_cid = value()->Type()->ToCid(); 1378 const intptr_t value_cid = value()->Type()->ToCid();
1440 const intptr_t field_cid = field().guarded_cid(); 1379 const intptr_t field_cid = field().guarded_cid();
1441 1380
1442 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); 1381 const bool emit_full_guard = !opt || (field_cid == kIllegalCid);
1443 1382
1444 const bool needs_value_cid_temp_reg = 1383 const bool needs_value_cid_temp_reg =
(...skipping 13 matching lines...) Expand all
1458 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); 1397 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall);
1459 summary->set_in(0, Location::RequiresRegister()); 1398 summary->set_in(0, Location::RequiresRegister());
1460 1399
1461 for (intptr_t i = 0; i < num_temps; i++) { 1400 for (intptr_t i = 0; i < num_temps; i++) {
1462 summary->set_temp(i, Location::RequiresRegister()); 1401 summary->set_temp(i, Location::RequiresRegister());
1463 } 1402 }
1464 1403
1465 return summary; 1404 return summary;
1466 } 1405 }
1467 1406
1468
1469 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1407 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1470 ASSERT(sizeof(classid_t) == kInt16Size); 1408 ASSERT(sizeof(classid_t) == kInt16Size);
1471 const intptr_t value_cid = value()->Type()->ToCid(); 1409 const intptr_t value_cid = value()->Type()->ToCid();
1472 const intptr_t field_cid = field().guarded_cid(); 1410 const intptr_t field_cid = field().guarded_cid();
1473 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; 1411 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
1474 1412
1475 if (field_cid == kDynamicCid) { 1413 if (field_cid == kDynamicCid) {
1476 if (Compiler::IsBackgroundCompilation()) { 1414 if (Compiler::IsBackgroundCompilation()) {
1477 // Field state changed while compiling. 1415 // Field state changed while compiling.
1478 Compiler::AbortBackgroundCompilation( 1416 Compiler::AbortBackgroundCompilation(
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1600 __ b(fail, NE); 1538 __ b(fail, NE);
1601 } else { 1539 } else {
1602 // Both value's and field's class id is known. 1540 // Both value's and field's class id is known.
1603 ASSERT((value_cid != field_cid) && (value_cid != nullability)); 1541 ASSERT((value_cid != field_cid) && (value_cid != nullability));
1604 __ b(fail); 1542 __ b(fail);
1605 } 1543 }
1606 } 1544 }
1607 __ Bind(&ok); 1545 __ Bind(&ok);
1608 } 1546 }
1609 1547
1610
1611 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, 1548 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone,
1612 bool opt) const { 1549 bool opt) const {
1613 const intptr_t kNumInputs = 1; 1550 const intptr_t kNumInputs = 1;
1614 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { 1551 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) {
1615 const intptr_t kNumTemps = 3; 1552 const intptr_t kNumTemps = 3;
1616 LocationSummary* summary = new (zone) 1553 LocationSummary* summary = new (zone)
1617 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 1554 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
1618 summary->set_in(0, Location::RequiresRegister()); 1555 summary->set_in(0, Location::RequiresRegister());
1619 // We need temporaries for field object, length offset and expected length. 1556 // We need temporaries for field object, length offset and expected length.
1620 summary->set_temp(0, Location::RequiresRegister()); 1557 summary->set_temp(0, Location::RequiresRegister());
1621 summary->set_temp(1, Location::RequiresRegister()); 1558 summary->set_temp(1, Location::RequiresRegister());
1622 summary->set_temp(2, Location::RequiresRegister()); 1559 summary->set_temp(2, Location::RequiresRegister());
1623 return summary; 1560 return summary;
1624 } else { 1561 } else {
1625 LocationSummary* summary = new (zone) 1562 LocationSummary* summary = new (zone)
1626 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); 1563 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall);
1627 summary->set_in(0, Location::RequiresRegister()); 1564 summary->set_in(0, Location::RequiresRegister());
1628 return summary; 1565 return summary;
1629 } 1566 }
1630 UNREACHABLE(); 1567 UNREACHABLE();
1631 } 1568 }
1632 1569
1633
1634 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1570 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1635 if (field().guarded_list_length() == Field::kNoFixedLength) { 1571 if (field().guarded_list_length() == Field::kNoFixedLength) {
1636 if (Compiler::IsBackgroundCompilation()) { 1572 if (Compiler::IsBackgroundCompilation()) {
1637 // Field state changed while compiling. 1573 // Field state changed while compiling.
1638 Compiler::AbortBackgroundCompilation( 1574 Compiler::AbortBackgroundCompilation(
1639 deopt_id(), 1575 deopt_id(),
1640 "GuardFieldLengthInstr: field state changed while compiling"); 1576 "GuardFieldLengthInstr: field state changed while compiling");
1641 } 1577 }
1642 ASSERT(!compiler->is_optimizing()); 1578 ASSERT(!compiler->is_optimizing());
1643 return; // Nothing to emit. 1579 return; // Nothing to emit.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1695 ASSERT(field().guarded_list_length_in_object_offset() != 1631 ASSERT(field().guarded_list_length_in_object_offset() !=
1696 Field::kUnknownLengthOffset); 1632 Field::kUnknownLengthOffset);
1697 1633
1698 __ ldr(TMP, FieldAddress(value_reg, 1634 __ ldr(TMP, FieldAddress(value_reg,
1699 field().guarded_list_length_in_object_offset())); 1635 field().guarded_list_length_in_object_offset()));
1700 __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length())); 1636 __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length()));
1701 __ b(deopt, NE); 1637 __ b(deopt, NE);
1702 } 1638 }
1703 } 1639 }
1704 1640
1705
1706 class BoxAllocationSlowPath : public SlowPathCode { 1641 class BoxAllocationSlowPath : public SlowPathCode {
1707 public: 1642 public:
1708 BoxAllocationSlowPath(Instruction* instruction, 1643 BoxAllocationSlowPath(Instruction* instruction,
1709 const Class& cls, 1644 const Class& cls,
1710 Register result) 1645 Register result)
1711 : instruction_(instruction), cls_(cls), result_(result) {} 1646 : instruction_(instruction), cls_(cls), result_(result) {}
1712 1647
1713 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 1648 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
1714 if (Assembler::EmittingComments()) { 1649 if (Assembler::EmittingComments()) {
1715 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), 1650 __ Comment("%s slow path allocation of %s", instruction_->DebugName(),
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1749 __ Bind(slow_path->exit_label()); 1684 __ Bind(slow_path->exit_label());
1750 } 1685 }
1751 } 1686 }
1752 1687
1753 private: 1688 private:
1754 Instruction* instruction_; 1689 Instruction* instruction_;
1755 const Class& cls_; 1690 const Class& cls_;
1756 const Register result_; 1691 const Register result_;
1757 }; 1692 };
1758 1693
1759
1760 static void EnsureMutableBox(FlowGraphCompiler* compiler, 1694 static void EnsureMutableBox(FlowGraphCompiler* compiler,
1761 StoreInstanceFieldInstr* instruction, 1695 StoreInstanceFieldInstr* instruction,
1762 Register box_reg, 1696 Register box_reg,
1763 const Class& cls, 1697 const Class& cls,
1764 Register instance_reg, 1698 Register instance_reg,
1765 intptr_t offset, 1699 intptr_t offset,
1766 Register temp) { 1700 Register temp) {
1767 Label done; 1701 Label done;
1768 __ LoadFieldFromOffset(box_reg, instance_reg, offset); 1702 __ LoadFieldFromOffset(box_reg, instance_reg, offset);
1769 __ CompareObject(box_reg, Object::null_object()); 1703 __ CompareObject(box_reg, Object::null_object());
1770 __ b(&done, NE); 1704 __ b(&done, NE);
1771 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); 1705 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp);
1772 __ mov(temp, box_reg); 1706 __ mov(temp, box_reg);
1773 __ StoreIntoObjectOffset(instance_reg, offset, temp); 1707 __ StoreIntoObjectOffset(instance_reg, offset, temp);
1774 __ Bind(&done); 1708 __ Bind(&done);
1775 } 1709 }
1776 1710
1777
1778 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, 1711 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone,
1779 bool opt) const { 1712 bool opt) const {
1780 const intptr_t kNumInputs = 2; 1713 const intptr_t kNumInputs = 2;
1781 const intptr_t kNumTemps = 1714 const intptr_t kNumTemps =
1782 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 2 : 0); 1715 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 2 : 0);
1783 LocationSummary* summary = new (zone) 1716 LocationSummary* summary = new (zone)
1784 LocationSummary(zone, kNumInputs, kNumTemps, 1717 LocationSummary(zone, kNumInputs, kNumTemps,
1785 ((IsUnboxedStore() && opt && is_initialization()) || 1718 ((IsUnboxedStore() && opt && is_initialization()) ||
1786 IsPotentialUnboxedStore()) 1719 IsPotentialUnboxedStore())
1787 ? LocationSummary::kCallOnSlowPath 1720 ? LocationSummary::kCallOnSlowPath
(...skipping 10 matching lines...) Expand all
1798 summary->set_temp(0, Location::RequiresRegister()); 1731 summary->set_temp(0, Location::RequiresRegister());
1799 summary->set_temp(1, Location::RequiresRegister()); 1732 summary->set_temp(1, Location::RequiresRegister());
1800 } else { 1733 } else {
1801 summary->set_in(1, ShouldEmitStoreBarrier() 1734 summary->set_in(1, ShouldEmitStoreBarrier()
1802 ? Location::WritableRegister() 1735 ? Location::WritableRegister()
1803 : Location::RegisterOrConstant(value())); 1736 : Location::RegisterOrConstant(value()));
1804 } 1737 }
1805 return summary; 1738 return summary;
1806 } 1739 }
1807 1740
1808
1809 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1741 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1810 ASSERT(sizeof(classid_t) == kInt16Size); 1742 ASSERT(sizeof(classid_t) == kInt16Size);
1811 Label skip_store; 1743 Label skip_store;
1812 1744
1813 const Register instance_reg = locs()->in(0).reg(); 1745 const Register instance_reg = locs()->in(0).reg();
1814 1746
1815 if (IsUnboxedStore() && compiler->is_optimizing()) { 1747 if (IsUnboxedStore() && compiler->is_optimizing()) {
1816 const VRegister value = locs()->in(1).fpu_reg(); 1748 const VRegister value = locs()->in(1).fpu_reg();
1817 const Register temp = locs()->temp(0).reg(); 1749 const Register temp = locs()->temp(0).reg();
1818 const Register temp2 = locs()->temp(1).reg(); 1750 const Register temp2 = locs()->temp(1).reg();
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1951 locs()->in(1).constant()); 1883 locs()->in(1).constant());
1952 } else { 1884 } else {
1953 const Register value_reg = locs()->in(1).reg(); 1885 const Register value_reg = locs()->in(1).reg();
1954 __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes_, 1886 __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes_,
1955 value_reg); 1887 value_reg);
1956 } 1888 }
1957 } 1889 }
1958 __ Bind(&skip_store); 1890 __ Bind(&skip_store);
1959 } 1891 }
1960 1892
1961
1962 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, 1893 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone,
1963 bool opt) const { 1894 bool opt) const {
1964 const intptr_t kNumInputs = 1; 1895 const intptr_t kNumInputs = 1;
1965 const intptr_t kNumTemps = 0; 1896 const intptr_t kNumTemps = 0;
1966 LocationSummary* summary = new (zone) 1897 LocationSummary* summary = new (zone)
1967 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 1898 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
1968 summary->set_in(0, Location::RequiresRegister()); 1899 summary->set_in(0, Location::RequiresRegister());
1969 summary->set_out(0, Location::RequiresRegister()); 1900 summary->set_out(0, Location::RequiresRegister());
1970 return summary; 1901 return summary;
1971 } 1902 }
1972 1903
1973
1974 // When the parser is building an implicit static getter for optimization, 1904 // When the parser is building an implicit static getter for optimization,
1975 // it can generate a function body where deoptimization ids do not line up 1905 // it can generate a function body where deoptimization ids do not line up
1976 // with the unoptimized code. 1906 // with the unoptimized code.
1977 // 1907 //
1978 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. 1908 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize.
1979 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1909 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1980 const Register field = locs()->in(0).reg(); 1910 const Register field = locs()->in(0).reg();
1981 const Register result = locs()->out(0).reg(); 1911 const Register result = locs()->out(0).reg();
1982 __ LoadFieldFromOffset(result, field, Field::static_value_offset()); 1912 __ LoadFieldFromOffset(result, field, Field::static_value_offset());
1983 } 1913 }
1984 1914
1985
1986 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, 1915 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone,
1987 bool opt) const { 1916 bool opt) const {
1988 LocationSummary* locs = 1917 LocationSummary* locs =
1989 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); 1918 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall);
1990 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() 1919 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister()
1991 : Location::RequiresRegister()); 1920 : Location::RequiresRegister());
1992 locs->set_temp(0, Location::RequiresRegister()); 1921 locs->set_temp(0, Location::RequiresRegister());
1993 return locs; 1922 return locs;
1994 } 1923 }
1995 1924
1996
1997 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1925 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1998 const Register value = locs()->in(0).reg(); 1926 const Register value = locs()->in(0).reg();
1999 const Register temp = locs()->temp(0).reg(); 1927 const Register temp = locs()->temp(0).reg();
2000 1928
2001 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); 1929 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original()));
2002 if (this->value()->NeedsStoreBuffer()) { 1930 if (this->value()->NeedsStoreBuffer()) {
2003 __ StoreIntoObjectOffset(temp, Field::static_value_offset(), value, 1931 __ StoreIntoObjectOffset(temp, Field::static_value_offset(), value,
2004 CanValueBeSmi()); 1932 CanValueBeSmi());
2005 } else { 1933 } else {
2006 __ StoreIntoObjectOffsetNoBarrier(temp, Field::static_value_offset(), 1934 __ StoreIntoObjectOffsetNoBarrier(temp, Field::static_value_offset(),
2007 value); 1935 value);
2008 } 1936 }
2009 } 1937 }
2010 1938
2011
2012 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, 1939 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
2013 bool opt) const { 1940 bool opt) const {
2014 const intptr_t kNumInputs = 3; 1941 const intptr_t kNumInputs = 3;
2015 const intptr_t kNumTemps = 0; 1942 const intptr_t kNumTemps = 0;
2016 LocationSummary* summary = new (zone) 1943 LocationSummary* summary = new (zone)
2017 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); 1944 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2018 summary->set_in(0, Location::RegisterLocation(R0)); // Instance. 1945 summary->set_in(0, Location::RegisterLocation(R0)); // Instance.
2019 summary->set_in(1, Location::RegisterLocation(R1)); // Instant. type args. 1946 summary->set_in(1, Location::RegisterLocation(R1)); // Instant. type args.
2020 summary->set_in(2, Location::RegisterLocation(R2)); // Function type args. 1947 summary->set_in(2, Location::RegisterLocation(R2)); // Function type args.
2021 summary->set_out(0, Location::RegisterLocation(R0)); 1948 summary->set_out(0, Location::RegisterLocation(R0));
2022 return summary; 1949 return summary;
2023 } 1950 }
2024 1951
2025
2026 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1952 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2027 ASSERT(locs()->in(0).reg() == R0); // Value. 1953 ASSERT(locs()->in(0).reg() == R0); // Value.
2028 ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments. 1954 ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments.
2029 ASSERT(locs()->in(2).reg() == R2); // Function type arguments. 1955 ASSERT(locs()->in(2).reg() == R2); // Function type arguments.
2030 1956
2031 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs()); 1957 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
2032 ASSERT(locs()->out(0).reg() == R0); 1958 ASSERT(locs()->out(0).reg() == R0);
2033 } 1959 }
2034 1960
2035
2036 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, 1961 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone,
2037 bool opt) const { 1962 bool opt) const {
2038 const intptr_t kNumInputs = 2; 1963 const intptr_t kNumInputs = 2;
2039 const intptr_t kNumTemps = 0; 1964 const intptr_t kNumTemps = 0;
2040 LocationSummary* locs = new (zone) 1965 LocationSummary* locs = new (zone)
2041 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); 1966 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2042 locs->set_in(kElementTypePos, Location::RegisterLocation(R1)); 1967 locs->set_in(kElementTypePos, Location::RegisterLocation(R1));
2043 locs->set_in(kLengthPos, Location::RegisterLocation(R2)); 1968 locs->set_in(kLengthPos, Location::RegisterLocation(R2));
2044 locs->set_out(0, Location::RegisterLocation(R0)); 1969 locs->set_out(0, Location::RegisterLocation(R0));
2045 return locs; 1970 return locs;
2046 } 1971 }
2047 1972
2048
2049 // Inlines array allocation for known constant values. 1973 // Inlines array allocation for known constant values.
2050 static void InlineArrayAllocation(FlowGraphCompiler* compiler, 1974 static void InlineArrayAllocation(FlowGraphCompiler* compiler,
2051 intptr_t num_elements, 1975 intptr_t num_elements,
2052 Label* slow_path, 1976 Label* slow_path,
2053 Label* done) { 1977 Label* done) {
2054 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. 1978 const int kInlineArraySize = 12; // Same as kInlineInstanceSize.
2055 const Register kLengthReg = R2; 1979 const Register kLengthReg = R2;
2056 const Register kElemTypeReg = R1; 1980 const Register kElemTypeReg = R1;
2057 const intptr_t instance_size = Array::InstanceSize(num_elements); 1981 const intptr_t instance_size = Array::InstanceSize(num_elements);
2058 1982
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2095 __ b(&end_loop, CS); 2019 __ b(&end_loop, CS);
2096 __ str(R6, Address(R8)); 2020 __ str(R6, Address(R8));
2097 __ AddImmediate(R8, kWordSize); 2021 __ AddImmediate(R8, kWordSize);
2098 __ b(&init_loop); 2022 __ b(&init_loop);
2099 __ Bind(&end_loop); 2023 __ Bind(&end_loop);
2100 } 2024 }
2101 } 2025 }
2102 __ b(done); 2026 __ b(done);
2103 } 2027 }
2104 2028
2105
2106 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2029 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2107 const Register kLengthReg = R2; 2030 const Register kLengthReg = R2;
2108 const Register kElemTypeReg = R1; 2031 const Register kElemTypeReg = R1;
2109 const Register kResultReg = R0; 2032 const Register kResultReg = R0;
2110 2033
2111 ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg); 2034 ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg);
2112 ASSERT(locs()->in(kLengthPos).reg() == kLengthReg); 2035 ASSERT(locs()->in(kLengthPos).reg() == kLengthReg);
2113 2036
2114 if (compiler->is_optimizing() && !FLAG_precompiled_mode && 2037 if (compiler->is_optimizing() && !FLAG_precompiled_mode &&
2115 num_elements()->BindsToConstant() && 2038 num_elements()->BindsToConstant() &&
(...skipping 16 matching lines...) Expand all
2132 } 2055 }
2133 const Code& stub = Code::ZoneHandle(compiler->zone(), 2056 const Code& stub = Code::ZoneHandle(compiler->zone(),
2134 StubCode::AllocateArray_entry()->code()); 2057 StubCode::AllocateArray_entry()->code());
2135 compiler->AddStubCallTarget(stub); 2058 compiler->AddStubCallTarget(stub);
2136 compiler->GenerateCallWithDeopt(token_pos(), deopt_id(), 2059 compiler->GenerateCallWithDeopt(token_pos(), deopt_id(),
2137 *StubCode::AllocateArray_entry(), 2060 *StubCode::AllocateArray_entry(),
2138 RawPcDescriptors::kOther, locs()); 2061 RawPcDescriptors::kOther, locs());
2139 ASSERT(locs()->out(0).reg() == kResultReg); 2062 ASSERT(locs()->out(0).reg() == kResultReg);
2140 } 2063 }
2141 2064
2142
2143 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, 2065 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone,
2144 bool opt) const { 2066 bool opt) const {
2145 const intptr_t kNumInputs = 1; 2067 const intptr_t kNumInputs = 1;
2146 const intptr_t kNumTemps = 2068 const intptr_t kNumTemps =
2147 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 1 : 0); 2069 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 1 : 0);
2148 LocationSummary* locs = new (zone) LocationSummary( 2070 LocationSummary* locs = new (zone) LocationSummary(
2149 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) 2071 zone, kNumInputs, kNumTemps,
2150 ? LocationSummary::kNoCall 2072 (opt && !IsPotentialUnboxedLoad()) ? LocationSummary::kNoCall
2151 : LocationSummary::kCallOnSlowPath); 2073 : LocationSummary::kCallOnSlowPath);
2152 2074
2153 locs->set_in(0, Location::RequiresRegister()); 2075 locs->set_in(0, Location::RequiresRegister());
2154 2076
2155 if (IsUnboxedLoad() && opt) { 2077 if (IsUnboxedLoad() && opt) {
2156 locs->set_temp(0, Location::RequiresRegister()); 2078 locs->set_temp(0, Location::RequiresRegister());
2157 } else if (IsPotentialUnboxedLoad()) { 2079 } else if (IsPotentialUnboxedLoad()) {
2158 locs->set_temp(0, Location::RequiresRegister()); 2080 locs->set_temp(0, Location::RequiresRegister());
2159 } 2081 }
2160 locs->set_out(0, Location::RequiresRegister()); 2082 locs->set_out(0, Location::RequiresRegister());
2161 return locs; 2083 return locs;
2162 } 2084 }
2163 2085
2164
2165 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2086 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2166 ASSERT(sizeof(classid_t) == kInt16Size); 2087 ASSERT(sizeof(classid_t) == kInt16Size);
2167 const Register instance_reg = locs()->in(0).reg(); 2088 const Register instance_reg = locs()->in(0).reg();
2168 if (IsUnboxedLoad() && compiler->is_optimizing()) { 2089 if (IsUnboxedLoad() && compiler->is_optimizing()) {
2169 const VRegister result = locs()->out(0).fpu_reg(); 2090 const VRegister result = locs()->out(0).fpu_reg();
2170 const Register temp = locs()->temp(0).reg(); 2091 const Register temp = locs()->temp(0).reg();
2171 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); 2092 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes());
2172 const intptr_t cid = field()->UnboxedFieldCid(); 2093 const intptr_t cid = field()->UnboxedFieldCid();
2173 switch (cid) { 2094 switch (cid) {
2174 case kDoubleCid: 2095 case kDoubleCid:
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
2256 __ StoreQFieldToOffset(VTMP, result_reg, Float64x2::value_offset()); 2177 __ StoreQFieldToOffset(VTMP, result_reg, Float64x2::value_offset());
2257 __ b(&done); 2178 __ b(&done);
2258 } 2179 }
2259 2180
2260 __ Bind(&load_pointer); 2181 __ Bind(&load_pointer);
2261 } 2182 }
2262 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); 2183 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes());
2263 __ Bind(&done); 2184 __ Bind(&done);
2264 } 2185 }
2265 2186
2266
2267 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, 2187 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
2268 bool opt) const { 2188 bool opt) const {
2269 const intptr_t kNumInputs = 2; 2189 const intptr_t kNumInputs = 2;
2270 const intptr_t kNumTemps = 0; 2190 const intptr_t kNumTemps = 0;
2271 LocationSummary* locs = new (zone) 2191 LocationSummary* locs = new (zone)
2272 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); 2192 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2273 locs->set_in(0, Location::RegisterLocation(R0)); // Instant. type args. 2193 locs->set_in(0, Location::RegisterLocation(R0)); // Instant. type args.
2274 locs->set_in(1, Location::RegisterLocation(R1)); // Function type args. 2194 locs->set_in(1, Location::RegisterLocation(R1)); // Function type args.
2275 locs->set_out(0, Location::RegisterLocation(R0)); 2195 locs->set_out(0, Location::RegisterLocation(R0));
2276 return locs; 2196 return locs;
2277 } 2197 }
2278 2198
2279
2280 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2199 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2281 const Register instantiator_type_args_reg = locs()->in(0).reg(); 2200 const Register instantiator_type_args_reg = locs()->in(0).reg();
2282 const Register function_type_args_reg = locs()->in(1).reg(); 2201 const Register function_type_args_reg = locs()->in(1).reg();
2283 const Register result_reg = locs()->out(0).reg(); 2202 const Register result_reg = locs()->out(0).reg();
2284 2203
2285 // 'instantiator_type_args_reg' is a TypeArguments object (or null). 2204 // 'instantiator_type_args_reg' is a TypeArguments object (or null).
2286 // 'function_type_args_reg' is a TypeArguments object (or null). 2205 // 'function_type_args_reg' is a TypeArguments object (or null).
2287 // A runtime call to instantiate the type is required. 2206 // A runtime call to instantiate the type is required.
2288 __ PushObject(Object::null_object()); // Make room for the result. 2207 __ PushObject(Object::null_object()); // Make room for the result.
2289 __ PushObject(type()); 2208 __ PushObject(type());
2290 __ PushPair(function_type_args_reg, instantiator_type_args_reg); 2209 __ PushPair(function_type_args_reg, instantiator_type_args_reg);
2291 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), 2210 compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
2292 kInstantiateTypeRuntimeEntry, 3, locs()); 2211 kInstantiateTypeRuntimeEntry, 3, locs());
2293 __ Drop(3); // Drop 2 type argument vectors and uninstantiated type. 2212 __ Drop(3); // Drop 2 type argument vectors and uninstantiated type.
2294 __ Pop(result_reg); // Pop instantiated type. 2213 __ Pop(result_reg); // Pop instantiated type.
2295 ASSERT(instantiator_type_args_reg == result_reg); 2214 ASSERT(instantiator_type_args_reg == result_reg);
2296 } 2215 }
2297 2216
2298
2299 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( 2217 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
2300 Zone* zone, 2218 Zone* zone,
2301 bool opt) const { 2219 bool opt) const {
2302 const intptr_t kNumInputs = 2; 2220 const intptr_t kNumInputs = 2;
2303 const intptr_t kNumTemps = 0; 2221 const intptr_t kNumTemps = 0;
2304 LocationSummary* locs = new (zone) 2222 LocationSummary* locs = new (zone)
2305 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); 2223 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2306 locs->set_in(0, Location::RegisterLocation(R0)); // Instant. type args. 2224 locs->set_in(0, Location::RegisterLocation(R0)); // Instant. type args.
2307 locs->set_in(1, Location::RegisterLocation(R1)); // Function type args. 2225 locs->set_in(1, Location::RegisterLocation(R1)); // Function type args.
2308 locs->set_out(0, Location::RegisterLocation(R0)); 2226 locs->set_out(0, Location::RegisterLocation(R0));
2309 return locs; 2227 return locs;
2310 } 2228 }
2311 2229
2312
2313 void InstantiateTypeArgumentsInstr::EmitNativeCode( 2230 void InstantiateTypeArgumentsInstr::EmitNativeCode(
2314 FlowGraphCompiler* compiler) { 2231 FlowGraphCompiler* compiler) {
2315 const Register instantiator_type_args_reg = locs()->in(0).reg(); 2232 const Register instantiator_type_args_reg = locs()->in(0).reg();
2316 const Register function_type_args_reg = locs()->in(1).reg(); 2233 const Register function_type_args_reg = locs()->in(1).reg();
2317 const Register result_reg = locs()->out(0).reg(); 2234 const Register result_reg = locs()->out(0).reg();
2318 ASSERT(instantiator_type_args_reg == R0); 2235 ASSERT(instantiator_type_args_reg == R0);
2319 ASSERT(instantiator_type_args_reg == result_reg); 2236 ASSERT(instantiator_type_args_reg == result_reg);
2320 2237
2321 // 'instantiator_type_args_reg' is a TypeArguments object (or null). 2238 // 'instantiator_type_args_reg' is a TypeArguments object (or null).
2322 // 'function_type_args_reg' is a TypeArguments object (or null). 2239 // 'function_type_args_reg' is a TypeArguments object (or null).
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2369 __ PushObject(type_arguments()); 2286 __ PushObject(type_arguments());
2370 __ PushPair(function_type_args_reg, instantiator_type_args_reg); 2287 __ PushPair(function_type_args_reg, instantiator_type_args_reg);
2371 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), 2288 compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
2372 kInstantiateTypeArgumentsRuntimeEntry, 3, 2289 kInstantiateTypeArgumentsRuntimeEntry, 3,
2373 locs()); 2290 locs());
2374 __ Drop(3); // Drop 2 type argument vectors and uninstantiated args. 2291 __ Drop(3); // Drop 2 type argument vectors and uninstantiated args.
2375 __ Pop(result_reg); // Pop instantiated type arguments. 2292 __ Pop(result_reg); // Pop instantiated type arguments.
2376 __ Bind(&type_arguments_instantiated); 2293 __ Bind(&type_arguments_instantiated);
2377 } 2294 }
2378 2295
2379
2380 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( 2296 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary(
2381 Zone* zone, 2297 Zone* zone,
2382 bool opt) const { 2298 bool opt) const {
2383 ASSERT(opt); 2299 ASSERT(opt);
2384 const intptr_t kNumInputs = 0; 2300 const intptr_t kNumInputs = 0;
2385 const intptr_t kNumTemps = 3; 2301 const intptr_t kNumTemps = 3;
2386 LocationSummary* locs = new (zone) LocationSummary( 2302 LocationSummary* locs = new (zone) LocationSummary(
2387 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); 2303 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
2388 locs->set_temp(0, Location::RegisterLocation(R1)); 2304 locs->set_temp(0, Location::RegisterLocation(R1));
2389 locs->set_temp(1, Location::RegisterLocation(R2)); 2305 locs->set_temp(1, Location::RegisterLocation(R2));
2390 locs->set_temp(2, Location::RegisterLocation(R3)); 2306 locs->set_temp(2, Location::RegisterLocation(R3));
2391 locs->set_out(0, Location::RegisterLocation(R0)); 2307 locs->set_out(0, Location::RegisterLocation(R0));
2392 return locs; 2308 return locs;
2393 } 2309 }
2394 2310
2395
2396 class AllocateContextSlowPath : public SlowPathCode { 2311 class AllocateContextSlowPath : public SlowPathCode {
2397 public: 2312 public:
2398 explicit AllocateContextSlowPath( 2313 explicit AllocateContextSlowPath(
2399 AllocateUninitializedContextInstr* instruction) 2314 AllocateUninitializedContextInstr* instruction)
2400 : instruction_(instruction) {} 2315 : instruction_(instruction) {}
2401 2316
2402 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 2317 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
2403 __ Comment("AllocateContextSlowPath"); 2318 __ Comment("AllocateContextSlowPath");
2404 __ Bind(entry_label()); 2319 __ Bind(entry_label());
2405 2320
(...skipping 11 matching lines...) Expand all
2417 RawPcDescriptors::kOther, locs); 2332 RawPcDescriptors::kOther, locs);
2418 ASSERT(instruction_->locs()->out(0).reg() == R0); 2333 ASSERT(instruction_->locs()->out(0).reg() == R0);
2419 compiler->RestoreLiveRegisters(instruction_->locs()); 2334 compiler->RestoreLiveRegisters(instruction_->locs());
2420 __ b(exit_label()); 2335 __ b(exit_label());
2421 } 2336 }
2422 2337
2423 private: 2338 private:
2424 AllocateUninitializedContextInstr* instruction_; 2339 AllocateUninitializedContextInstr* instruction_;
2425 }; 2340 };
2426 2341
2427
2428 void AllocateUninitializedContextInstr::EmitNativeCode( 2342 void AllocateUninitializedContextInstr::EmitNativeCode(
2429 FlowGraphCompiler* compiler) { 2343 FlowGraphCompiler* compiler) {
2430 Register temp0 = locs()->temp(0).reg(); 2344 Register temp0 = locs()->temp(0).reg();
2431 Register temp1 = locs()->temp(1).reg(); 2345 Register temp1 = locs()->temp(1).reg();
2432 Register temp2 = locs()->temp(2).reg(); 2346 Register temp2 = locs()->temp(2).reg();
2433 Register result = locs()->out(0).reg(); 2347 Register result = locs()->out(0).reg();
2434 // Try allocate the object. 2348 // Try allocate the object.
2435 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); 2349 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this);
2436 compiler->AddSlowPathCode(slow_path); 2350 compiler->AddSlowPathCode(slow_path);
2437 intptr_t instance_size = Context::InstanceSize(num_context_variables()); 2351 intptr_t instance_size = Context::InstanceSize(num_context_variables());
2438 2352
2439 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), 2353 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(),
2440 result, // instance 2354 result, // instance
2441 temp0, temp1, temp2); 2355 temp0, temp1, temp2);
2442 2356
2443 // Setup up number of context variables field. 2357 // Setup up number of context variables field.
2444 __ LoadImmediate(temp0, num_context_variables()); 2358 __ LoadImmediate(temp0, num_context_variables());
2445 __ str(temp0, FieldAddress(result, Context::num_variables_offset())); 2359 __ str(temp0, FieldAddress(result, Context::num_variables_offset()));
2446 2360
2447 __ Bind(slow_path->exit_label()); 2361 __ Bind(slow_path->exit_label());
2448 } 2362 }
2449 2363
2450
2451 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, 2364 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone,
2452 bool opt) const { 2365 bool opt) const {
2453 const intptr_t kNumInputs = 0; 2366 const intptr_t kNumInputs = 0;
2454 const intptr_t kNumTemps = 1; 2367 const intptr_t kNumTemps = 1;
2455 LocationSummary* locs = new (zone) 2368 LocationSummary* locs = new (zone)
2456 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); 2369 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2457 locs->set_temp(0, Location::RegisterLocation(R1)); 2370 locs->set_temp(0, Location::RegisterLocation(R1));
2458 locs->set_out(0, Location::RegisterLocation(R0)); 2371 locs->set_out(0, Location::RegisterLocation(R0));
2459 return locs; 2372 return locs;
2460 } 2373 }
2461 2374
2462
2463 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2375 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2464 ASSERT(locs()->temp(0).reg() == R1); 2376 ASSERT(locs()->temp(0).reg() == R1);
2465 ASSERT(locs()->out(0).reg() == R0); 2377 ASSERT(locs()->out(0).reg() == R0);
2466 2378
2467 __ LoadImmediate(R1, num_context_variables()); 2379 __ LoadImmediate(R1, num_context_variables());
2468 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), 2380 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(),
2469 RawPcDescriptors::kOther, locs()); 2381 RawPcDescriptors::kOther, locs());
2470 } 2382 }
2471 2383
2472 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, 2384 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone,
2473 bool opt) const { 2385 bool opt) const {
2474 const intptr_t kNumInputs = 1; 2386 const intptr_t kNumInputs = 1;
2475 const intptr_t kNumTemps = 1; 2387 const intptr_t kNumTemps = 1;
2476 LocationSummary* locs = new (zone) 2388 LocationSummary* locs = new (zone)
2477 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); 2389 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2478 locs->set_in(0, Location::RegisterLocation(R0)); 2390 locs->set_in(0, Location::RegisterLocation(R0));
2479 locs->set_temp(0, Location::RegisterLocation(R1)); 2391 locs->set_temp(0, Location::RegisterLocation(R1));
2480 return locs; 2392 return locs;
2481 } 2393 }
2482 2394
2483
2484 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2395 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2485 Register field = locs()->in(0).reg(); 2396 Register field = locs()->in(0).reg();
2486 Register temp = locs()->temp(0).reg(); 2397 Register temp = locs()->temp(0).reg();
2487 Label call_runtime, no_call; 2398 Label call_runtime, no_call;
2488 2399
2489 __ ldr(temp, FieldAddress(field, Field::static_value_offset())); 2400 __ ldr(temp, FieldAddress(field, Field::static_value_offset()));
2490 __ CompareObject(temp, Object::sentinel()); 2401 __ CompareObject(temp, Object::sentinel());
2491 __ b(&call_runtime, EQ); 2402 __ b(&call_runtime, EQ);
2492 2403
2493 __ CompareObject(temp, Object::transition_sentinel()); 2404 __ CompareObject(temp, Object::transition_sentinel());
2494 __ b(&no_call, NE); 2405 __ b(&no_call, NE);
2495 2406
2496 __ Bind(&call_runtime); 2407 __ Bind(&call_runtime);
2497 __ PushObject(Object::null_object()); // Make room for (unused) result. 2408 __ PushObject(Object::null_object()); // Make room for (unused) result.
2498 __ Push(field); 2409 __ Push(field);
2499 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), 2410 compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
2500 kInitStaticFieldRuntimeEntry, 1, locs()); 2411 kInitStaticFieldRuntimeEntry, 1, locs());
2501 __ Drop(2); // Remove argument and result placeholder. 2412 __ Drop(2); // Remove argument and result placeholder.
2502 __ Bind(&no_call); 2413 __ Bind(&no_call);
2503 } 2414 }
2504 2415
2505
2506 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, 2416 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone,
2507 bool opt) const { 2417 bool opt) const {
2508 const intptr_t kNumInputs = 1; 2418 const intptr_t kNumInputs = 1;
2509 const intptr_t kNumTemps = 0; 2419 const intptr_t kNumTemps = 0;
2510 LocationSummary* locs = new (zone) 2420 LocationSummary* locs = new (zone)
2511 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); 2421 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2512 locs->set_in(0, Location::RegisterLocation(R0)); 2422 locs->set_in(0, Location::RegisterLocation(R0));
2513 locs->set_out(0, Location::RegisterLocation(R0)); 2423 locs->set_out(0, Location::RegisterLocation(R0));
2514 return locs; 2424 return locs;
2515 } 2425 }
2516 2426
2517
2518 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2427 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2519 const Register context_value = locs()->in(0).reg(); 2428 const Register context_value = locs()->in(0).reg();
2520 const Register result = locs()->out(0).reg(); 2429 const Register result = locs()->out(0).reg();
2521 2430
2522 __ PushObject(Object::null_object()); // Make room for the result. 2431 __ PushObject(Object::null_object()); // Make room for the result.
2523 __ Push(context_value); 2432 __ Push(context_value);
2524 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), 2433 compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
2525 kCloneContextRuntimeEntry, 1, locs()); 2434 kCloneContextRuntimeEntry, 1, locs());
2526 __ Drop(1); // Remove argument. 2435 __ Drop(1); // Remove argument.
2527 __ Pop(result); // Get result (cloned context). 2436 __ Pop(result); // Get result (cloned context).
2528 } 2437 }
2529 2438
2530
2531 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, 2439 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone,
2532 bool opt) const { 2440 bool opt) const {
2533 UNREACHABLE(); 2441 UNREACHABLE();
2534 return NULL; 2442 return NULL;
2535 } 2443 }
2536 2444
2537
2538 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2445 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2539 __ Bind(compiler->GetJumpLabel(this)); 2446 __ Bind(compiler->GetJumpLabel(this));
2540 compiler->AddExceptionHandler(catch_try_index(), try_index(), 2447 compiler->AddExceptionHandler(catch_try_index(), try_index(),
2541 compiler->assembler()->CodeSize(), 2448 compiler->assembler()->CodeSize(),
2542 handler_token_pos(), is_generated(), 2449 handler_token_pos(), is_generated(),
2543 catch_handler_types_, needs_stacktrace()); 2450 catch_handler_types_, needs_stacktrace());
2544 // On lazy deoptimization we patch the optimized code here to enter the 2451 // On lazy deoptimization we patch the optimized code here to enter the
2545 // deoptimization stub. 2452 // deoptimization stub.
2546 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); 2453 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId());
2547 if (compiler->is_optimizing()) { 2454 if (compiler->is_optimizing()) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2591 } else { 2498 } else {
2592 // Restore stack and initialize the two exception variables: 2499 // Restore stack and initialize the two exception variables:
2593 // exception and stack trace variables. 2500 // exception and stack trace variables.
2594 __ StoreToOffset(kExceptionObjectReg, FP, 2501 __ StoreToOffset(kExceptionObjectReg, FP,
2595 exception_var().index() * kWordSize); 2502 exception_var().index() * kWordSize);
2596 __ StoreToOffset(kStackTraceObjectReg, FP, 2503 __ StoreToOffset(kStackTraceObjectReg, FP,
2597 stacktrace_var().index() * kWordSize); 2504 stacktrace_var().index() * kWordSize);
2598 } 2505 }
2599 } 2506 }
2600 2507
2601
2602 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, 2508 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone,
2603 bool opt) const { 2509 bool opt) const {
2604 const intptr_t kNumInputs = 0; 2510 const intptr_t kNumInputs = 0;
2605 const intptr_t kNumTemps = 1; 2511 const intptr_t kNumTemps = 1;
2606 LocationSummary* summary = new (zone) LocationSummary( 2512 LocationSummary* summary = new (zone) LocationSummary(
2607 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); 2513 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
2608 summary->set_temp(0, Location::RequiresRegister()); 2514 summary->set_temp(0, Location::RequiresRegister());
2609 return summary; 2515 return summary;
2610 } 2516 }
2611 2517
2612
2613 class CheckStackOverflowSlowPath : public SlowPathCode { 2518 class CheckStackOverflowSlowPath : public SlowPathCode {
2614 public: 2519 public:
2615 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) 2520 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction)
2616 : instruction_(instruction) {} 2521 : instruction_(instruction) {}
2617 2522
2618 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 2523 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
2619 if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) { 2524 if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) {
2620 const Register value = instruction_->locs()->temp(0).reg(); 2525 const Register value = instruction_->locs()->temp(0).reg();
2621 __ Comment("CheckStackOverflowSlowPathOsr"); 2526 __ Comment("CheckStackOverflowSlowPathOsr");
2622 __ Bind(osr_entry_label()); 2527 __ Bind(osr_entry_label());
(...skipping 27 matching lines...) Expand all
2650 Label* osr_entry_label() { 2555 Label* osr_entry_label() {
2651 ASSERT(Isolate::Current()->use_osr()); 2556 ASSERT(Isolate::Current()->use_osr());
2652 return &osr_entry_label_; 2557 return &osr_entry_label_;
2653 } 2558 }
2654 2559
2655 private: 2560 private:
2656 CheckStackOverflowInstr* instruction_; 2561 CheckStackOverflowInstr* instruction_;
2657 Label osr_entry_label_; 2562 Label osr_entry_label_;
2658 }; 2563 };
2659 2564
2660
2661 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2565 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2662 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); 2566 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
2663 compiler->AddSlowPathCode(slow_path); 2567 compiler->AddSlowPathCode(slow_path);
2664 2568
2665 __ ldr(TMP, Address(THR, Thread::stack_limit_offset())); 2569 __ ldr(TMP, Address(THR, Thread::stack_limit_offset()));
2666 // Compare to CSP not SP because CSP is closer to the stack limit. See 2570 // Compare to CSP not SP because CSP is closer to the stack limit. See
2667 // Assembler::EnterFrame. 2571 // Assembler::EnterFrame.
2668 __ CompareRegisters(CSP, TMP); 2572 __ CompareRegisters(CSP, TMP);
2669 __ b(slow_path->entry_label(), LS); 2573 __ b(slow_path->entry_label(), LS);
2670 if (compiler->CanOSRFunction() && in_loop()) { 2574 if (compiler->CanOSRFunction() && in_loop()) {
2671 const Register temp = locs()->temp(0).reg(); 2575 const Register temp = locs()->temp(0).reg();
2672 // In unoptimized code check the usage counter to trigger OSR at loop 2576 // In unoptimized code check the usage counter to trigger OSR at loop
2673 // stack checks. Use progressively higher thresholds for more deeply 2577 // stack checks. Use progressively higher thresholds for more deeply
2674 // nested loops to attempt to hit outer loops with OSR when possible. 2578 // nested loops to attempt to hit outer loops with OSR when possible.
2675 __ LoadObject(temp, compiler->parsed_function().function()); 2579 __ LoadObject(temp, compiler->parsed_function().function());
2676 intptr_t threshold = 2580 intptr_t threshold =
2677 FLAG_optimization_counter_threshold * (loop_depth() + 1); 2581 FLAG_optimization_counter_threshold * (loop_depth() + 1);
2678 __ LoadFieldFromOffset(temp, temp, Function::usage_counter_offset(), kWord); 2582 __ LoadFieldFromOffset(temp, temp, Function::usage_counter_offset(), kWord);
2679 __ CompareImmediate(temp, threshold); 2583 __ CompareImmediate(temp, threshold);
2680 __ b(slow_path->osr_entry_label(), GE); 2584 __ b(slow_path->osr_entry_label(), GE);
2681 } 2585 }
2682 if (compiler->ForceSlowPathForStackOverflow()) { 2586 if (compiler->ForceSlowPathForStackOverflow()) {
2683 __ b(slow_path->entry_label()); 2587 __ b(slow_path->entry_label());
2684 } 2588 }
2685 __ Bind(slow_path->exit_label()); 2589 __ Bind(slow_path->exit_label());
2686 } 2590 }
2687 2591
2688
2689 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, 2592 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
2690 BinarySmiOpInstr* shift_left) { 2593 BinarySmiOpInstr* shift_left) {
2691 const LocationSummary& locs = *shift_left->locs(); 2594 const LocationSummary& locs = *shift_left->locs();
2692 const Register left = locs.in(0).reg(); 2595 const Register left = locs.in(0).reg();
2693 const Register result = locs.out(0).reg(); 2596 const Register result = locs.out(0).reg();
2694 Label* deopt = shift_left->CanDeoptimize() 2597 Label* deopt = shift_left->CanDeoptimize()
2695 ? compiler->AddDeoptStub(shift_left->deopt_id(), 2598 ? compiler->AddDeoptStub(shift_left->deopt_id(),
2696 ICData::kDeoptBinarySmiOp) 2599 ICData::kDeoptBinarySmiOp)
2697 : NULL; 2600 : NULL;
2698 if (locs.in(1).IsConstant()) { 2601 if (locs.in(1).IsConstant()) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
2776 const Register temp = locs.temp(0).reg(); 2679 const Register temp = locs.temp(0).reg();
2777 __ lslv(temp, left, TMP); 2680 __ lslv(temp, left, TMP);
2778 __ asrv(TMP2, temp, TMP); 2681 __ asrv(TMP2, temp, TMP);
2779 __ CompareRegisters(left, TMP2); 2682 __ CompareRegisters(left, TMP2);
2780 __ b(deopt, NE); // Overflow. 2683 __ b(deopt, NE); // Overflow.
2781 // Shift for result now we know there is no overflow. 2684 // Shift for result now we know there is no overflow.
2782 __ lslv(result, left, TMP); 2685 __ lslv(result, left, TMP);
2783 } 2686 }
2784 } 2687 }
2785 2688
2786
2787 class CheckedSmiSlowPath : public SlowPathCode { 2689 class CheckedSmiSlowPath : public SlowPathCode {
2788 public: 2690 public:
2789 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) 2691 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index)
2790 : instruction_(instruction), try_index_(try_index) {} 2692 : instruction_(instruction), try_index_(try_index) {}
2791 2693
2792 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 2694 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
2793 if (Assembler::EmittingComments()) { 2695 if (Assembler::EmittingComments()) {
2794 __ Comment("slow path smi operation"); 2696 __ Comment("slow path smi operation");
2795 } 2697 }
2796 __ Bind(entry_label()); 2698 __ Bind(entry_label());
(...skipping 21 matching lines...) Expand all
2818 compiler->RestoreLiveRegisters(locs); 2720 compiler->RestoreLiveRegisters(locs);
2819 __ b(exit_label()); 2721 __ b(exit_label());
2820 compiler->pending_deoptimization_env_ = NULL; 2722 compiler->pending_deoptimization_env_ = NULL;
2821 } 2723 }
2822 2724
2823 private: 2725 private:
2824 CheckedSmiOpInstr* instruction_; 2726 CheckedSmiOpInstr* instruction_;
2825 intptr_t try_index_; 2727 intptr_t try_index_;
2826 }; 2728 };
2827 2729
2828
2829 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, 2730 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone,
2830 bool opt) const { 2731 bool opt) const {
2831 const intptr_t kNumInputs = 2; 2732 const intptr_t kNumInputs = 2;
2832 const intptr_t kNumTemps = 0; 2733 const intptr_t kNumTemps = 0;
2833 LocationSummary* summary = new (zone) LocationSummary( 2734 LocationSummary* summary = new (zone) LocationSummary(
2834 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); 2735 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
2835 summary->set_in(0, Location::RequiresRegister()); 2736 summary->set_in(0, Location::RequiresRegister());
2836 summary->set_in(1, Location::RequiresRegister()); 2737 summary->set_in(1, Location::RequiresRegister());
2837 summary->set_out(0, Location::RequiresRegister()); 2738 summary->set_out(0, Location::RequiresRegister());
2838 return summary; 2739 return summary;
2839 } 2740 }
2840 2741
2841
2842 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2742 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2843 CheckedSmiSlowPath* slow_path = 2743 CheckedSmiSlowPath* slow_path =
2844 new CheckedSmiSlowPath(this, compiler->CurrentTryIndex()); 2744 new CheckedSmiSlowPath(this, compiler->CurrentTryIndex());
2845 compiler->AddSlowPathCode(slow_path); 2745 compiler->AddSlowPathCode(slow_path);
2846 // Test operands if necessary. 2746 // Test operands if necessary.
2847 Register left = locs()->in(0).reg(); 2747 Register left = locs()->in(0).reg();
2848 Register right = locs()->in(1).reg(); 2748 Register right = locs()->in(1).reg();
2849 Register result = locs()->out(0).reg(); 2749 Register result = locs()->out(0).reg();
2850 intptr_t left_cid = this->left()->Type()->ToCid(); 2750 intptr_t left_cid = this->left()->Type()->ToCid();
2851 intptr_t right_cid = this->right()->Type()->ToCid(); 2751 intptr_t right_cid = this->right()->Type()->ToCid();
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2916 __ SmiUntag(TMP, left); 2816 __ SmiUntag(TMP, left);
2917 __ asrv(result, TMP, result); 2817 __ asrv(result, TMP, result);
2918 __ SmiTag(result); 2818 __ SmiTag(result);
2919 break; 2819 break;
2920 default: 2820 default:
2921 UNIMPLEMENTED(); 2821 UNIMPLEMENTED();
2922 } 2822 }
2923 __ Bind(slow_path->exit_label()); 2823 __ Bind(slow_path->exit_label());
2924 } 2824 }
2925 2825
2926
2927 class CheckedSmiComparisonSlowPath : public SlowPathCode { 2826 class CheckedSmiComparisonSlowPath : public SlowPathCode {
2928 public: 2827 public:
2929 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, 2828 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction,
2930 intptr_t try_index, 2829 intptr_t try_index,
2931 BranchLabels labels, 2830 BranchLabels labels,
2932 bool merged) 2831 bool merged)
2933 : instruction_(instruction), 2832 : instruction_(instruction),
2934 try_index_(try_index), 2833 try_index_(try_index),
2935 labels_(labels), 2834 labels_(labels),
2936 merged_(merged) {} 2835 merged_(merged) {}
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2975 } 2874 }
2976 } 2875 }
2977 2876
2978 private: 2877 private:
2979 CheckedSmiComparisonInstr* instruction_; 2878 CheckedSmiComparisonInstr* instruction_;
2980 intptr_t try_index_; 2879 intptr_t try_index_;
2981 BranchLabels labels_; 2880 BranchLabels labels_;
2982 bool merged_; 2881 bool merged_;
2983 }; 2882 };
2984 2883
2985
2986 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( 2884 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary(
2987 Zone* zone, 2885 Zone* zone,
2988 bool opt) const { 2886 bool opt) const {
2989 const intptr_t kNumInputs = 2; 2887 const intptr_t kNumInputs = 2;
2990 const intptr_t kNumTemps = 1; 2888 const intptr_t kNumTemps = 1;
2991 LocationSummary* summary = new (zone) LocationSummary( 2889 LocationSummary* summary = new (zone) LocationSummary(
2992 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); 2890 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
2993 summary->set_in(0, Location::RequiresRegister()); 2891 summary->set_in(0, Location::RequiresRegister());
2994 summary->set_in(1, Location::RequiresRegister()); 2892 summary->set_in(1, Location::RequiresRegister());
2995 summary->set_temp(0, Location::RequiresRegister()); 2893 summary->set_temp(0, Location::RequiresRegister());
2996 summary->set_out(0, Location::RequiresRegister()); 2894 summary->set_out(0, Location::RequiresRegister());
2997 return summary; 2895 return summary;
2998 } 2896 }
2999 2897
3000
3001 Condition CheckedSmiComparisonInstr::EmitComparisonCode( 2898 Condition CheckedSmiComparisonInstr::EmitComparisonCode(
3002 FlowGraphCompiler* compiler, 2899 FlowGraphCompiler* compiler,
3003 BranchLabels labels) { 2900 BranchLabels labels) {
3004 return EmitSmiComparisonOp(compiler, locs(), kind()); 2901 return EmitSmiComparisonOp(compiler, locs(), kind());
3005 } 2902 }
3006 2903
3007
3008 #define EMIT_SMI_CHECK \ 2904 #define EMIT_SMI_CHECK \
3009 Register left = locs()->in(0).reg(); \ 2905 Register left = locs()->in(0).reg(); \
3010 Register right = locs()->in(1).reg(); \ 2906 Register right = locs()->in(1).reg(); \
3011 Register temp = locs()->temp(0).reg(); \ 2907 Register temp = locs()->temp(0).reg(); \
3012 intptr_t left_cid = this->left()->Type()->ToCid(); \ 2908 intptr_t left_cid = this->left()->Type()->ToCid(); \
3013 intptr_t right_cid = this->right()->Type()->ToCid(); \ 2909 intptr_t right_cid = this->right()->Type()->ToCid(); \
3014 if (this->left()->definition() == this->right()->definition()) { \ 2910 if (this->left()->definition() == this->right()->definition()) { \
3015 __ tsti(left, Immediate(kSmiTagMask)); \ 2911 __ tsti(left, Immediate(kSmiTagMask)); \
3016 } else if (left_cid == kSmiCid) { \ 2912 } else if (left_cid == kSmiCid) { \
3017 __ tsti(right, Immediate(kSmiTagMask)); \ 2913 __ tsti(right, Immediate(kSmiTagMask)); \
3018 } else if (right_cid == kSmiCid) { \ 2914 } else if (right_cid == kSmiCid) { \
3019 __ tsti(left, Immediate(kSmiTagMask)); \ 2915 __ tsti(left, Immediate(kSmiTagMask)); \
3020 } else { \ 2916 } else { \
3021 __ orr(temp, left, Operand(right)); \ 2917 __ orr(temp, left, Operand(right)); \
3022 __ tsti(temp, Immediate(kSmiTagMask)); \ 2918 __ tsti(temp, Immediate(kSmiTagMask)); \
3023 } \ 2919 } \
3024 __ b(slow_path->entry_label(), NE) 2920 __ b(slow_path->entry_label(), NE)
3025 2921
3026
3027 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, 2922 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
3028 BranchInstr* branch) { 2923 BranchInstr* branch) {
3029 BranchLabels labels = compiler->CreateBranchLabels(branch); 2924 BranchLabels labels = compiler->CreateBranchLabels(branch);
3030 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( 2925 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath(
3031 this, compiler->CurrentTryIndex(), labels, 2926 this, compiler->CurrentTryIndex(), labels,
3032 /* merged = */ true); 2927 /* merged = */ true);
3033 compiler->AddSlowPathCode(slow_path); 2928 compiler->AddSlowPathCode(slow_path);
3034 EMIT_SMI_CHECK; 2929 EMIT_SMI_CHECK;
3035 Condition true_condition = EmitComparisonCode(compiler, labels); 2930 Condition true_condition = EmitComparisonCode(compiler, labels);
3036 ASSERT(true_condition != kInvalidCondition); 2931 ASSERT(true_condition != kInvalidCondition);
3037 EmitBranchOnCondition(compiler, true_condition, labels); 2932 EmitBranchOnCondition(compiler, true_condition, labels);
3038 __ Bind(slow_path->exit_label()); 2933 __ Bind(slow_path->exit_label());
3039 } 2934 }
3040 2935
3041
3042 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2936 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3043 Label true_label, false_label, done; 2937 Label true_label, false_label, done;
3044 BranchLabels labels = {&true_label, &false_label, &false_label}; 2938 BranchLabels labels = {&true_label, &false_label, &false_label};
3045 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( 2939 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath(
3046 this, compiler->CurrentTryIndex(), labels, 2940 this, compiler->CurrentTryIndex(), labels,
3047 /* merged = */ false); 2941 /* merged = */ false);
3048 compiler->AddSlowPathCode(slow_path); 2942 compiler->AddSlowPathCode(slow_path);
3049 EMIT_SMI_CHECK; 2943 EMIT_SMI_CHECK;
3050 Condition true_condition = EmitComparisonCode(compiler, labels); 2944 Condition true_condition = EmitComparisonCode(compiler, labels);
3051 ASSERT(true_condition != kInvalidCondition); 2945 ASSERT(true_condition != kInvalidCondition);
3052 EmitBranchOnCondition(compiler, true_condition, labels); 2946 EmitBranchOnCondition(compiler, true_condition, labels);
3053 Register result = locs()->out(0).reg(); 2947 Register result = locs()->out(0).reg();
3054 __ Bind(&false_label); 2948 __ Bind(&false_label);
3055 __ LoadObject(result, Bool::False()); 2949 __ LoadObject(result, Bool::False());
3056 __ b(&done); 2950 __ b(&done);
3057 __ Bind(&true_label); 2951 __ Bind(&true_label);
3058 __ LoadObject(result, Bool::True()); 2952 __ LoadObject(result, Bool::True());
3059 __ Bind(&done); 2953 __ Bind(&done);
3060 __ Bind(slow_path->exit_label()); 2954 __ Bind(slow_path->exit_label());
3061 } 2955 }
3062 2956
3063
3064 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, 2957 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone,
3065 bool opt) const { 2958 bool opt) const {
3066 const intptr_t kNumInputs = 2; 2959 const intptr_t kNumInputs = 2;
3067 const intptr_t kNumTemps = (((op_kind() == Token::kSHL) && can_overflow()) || 2960 const intptr_t kNumTemps = (((op_kind() == Token::kSHL) && can_overflow()) ||
3068 (op_kind() == Token::kSHR)) 2961 (op_kind() == Token::kSHR))
3069 ? 1 2962 ? 1
3070 : 0; 2963 : 0;
3071 LocationSummary* summary = new (zone) 2964 LocationSummary* summary = new (zone)
3072 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 2965 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3073 if (op_kind() == Token::kTRUNCDIV) { 2966 if (op_kind() == Token::kTRUNCDIV) {
(...skipping 18 matching lines...) Expand all
3092 if (((op_kind() == Token::kSHL) && can_overflow()) || 2985 if (((op_kind() == Token::kSHL) && can_overflow()) ||
3093 (op_kind() == Token::kSHR)) { 2986 (op_kind() == Token::kSHR)) {
3094 summary->set_temp(0, Location::RequiresRegister()); 2987 summary->set_temp(0, Location::RequiresRegister());
3095 } 2988 }
3096 // We make use of 3-operand instructions by not requiring result register 2989 // We make use of 3-operand instructions by not requiring result register
3097 // to be identical to first input register as on Intel. 2990 // to be identical to first input register as on Intel.
3098 summary->set_out(0, Location::RequiresRegister()); 2991 summary->set_out(0, Location::RequiresRegister());
3099 return summary; 2992 return summary;
3100 } 2993 }
3101 2994
3102
3103 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2995 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3104 if (op_kind() == Token::kSHL) { 2996 if (op_kind() == Token::kSHL) {
3105 EmitSmiShiftLeft(compiler, this); 2997 EmitSmiShiftLeft(compiler, this);
3106 return; 2998 return;
3107 } 2999 }
3108 3000
3109 const Register left = locs()->in(0).reg(); 3001 const Register left = locs()->in(0).reg();
3110 const Register result = locs()->out(0).reg(); 3002 const Register result = locs()->out(0).reg();
3111 Label* deopt = NULL; 3003 Label* deopt = NULL;
3112 if (CanDeoptimize()) { 3004 if (CanDeoptimize()) {
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
3329 // behavior (short-circuit evaluation). 3221 // behavior (short-circuit evaluation).
3330 UNREACHABLE(); 3222 UNREACHABLE();
3331 break; 3223 break;
3332 } 3224 }
3333 default: 3225 default:
3334 UNREACHABLE(); 3226 UNREACHABLE();
3335 break; 3227 break;
3336 } 3228 }
3337 } 3229 }
3338 3230
3339
3340 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, 3231 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone,
3341 bool opt) const { 3232 bool opt) const {
3342 intptr_t left_cid = left()->Type()->ToCid(); 3233 intptr_t left_cid = left()->Type()->ToCid();
3343 intptr_t right_cid = right()->Type()->ToCid(); 3234 intptr_t right_cid = right()->Type()->ToCid();
3344 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); 3235 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
3345 const intptr_t kNumInputs = 2; 3236 const intptr_t kNumInputs = 2;
3346 const intptr_t kNumTemps = 0; 3237 const intptr_t kNumTemps = 0;
3347 LocationSummary* summary = new (zone) 3238 LocationSummary* summary = new (zone)
3348 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3239 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3349 summary->set_in(0, Location::RequiresRegister()); 3240 summary->set_in(0, Location::RequiresRegister());
3350 summary->set_in(1, Location::RequiresRegister()); 3241 summary->set_in(1, Location::RequiresRegister());
3351 return summary; 3242 return summary;
3352 } 3243 }
3353 3244
3354
3355 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3245 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3356 Label* deopt = 3246 Label* deopt =
3357 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, 3247 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp,
3358 licm_hoisted_ ? ICData::kHoisted : 0); 3248 licm_hoisted_ ? ICData::kHoisted : 0);
3359 intptr_t left_cid = left()->Type()->ToCid(); 3249 intptr_t left_cid = left()->Type()->ToCid();
3360 intptr_t right_cid = right()->Type()->ToCid(); 3250 intptr_t right_cid = right()->Type()->ToCid();
3361 const Register left = locs()->in(0).reg(); 3251 const Register left = locs()->in(0).reg();
3362 const Register right = locs()->in(1).reg(); 3252 const Register right = locs()->in(1).reg();
3363 if (this->left()->definition() == this->right()->definition()) { 3253 if (this->left()->definition() == this->right()->definition()) {
3364 __ tsti(left, Immediate(kSmiTagMask)); 3254 __ tsti(left, Immediate(kSmiTagMask));
3365 } else if (left_cid == kSmiCid) { 3255 } else if (left_cid == kSmiCid) {
3366 __ tsti(right, Immediate(kSmiTagMask)); 3256 __ tsti(right, Immediate(kSmiTagMask));
3367 } else if (right_cid == kSmiCid) { 3257 } else if (right_cid == kSmiCid) {
3368 __ tsti(left, Immediate(kSmiTagMask)); 3258 __ tsti(left, Immediate(kSmiTagMask));
3369 } else { 3259 } else {
3370 __ orr(TMP, left, Operand(right)); 3260 __ orr(TMP, left, Operand(right));
3371 __ tsti(TMP, Immediate(kSmiTagMask)); 3261 __ tsti(TMP, Immediate(kSmiTagMask));
3372 } 3262 }
3373 __ b(deopt, EQ); 3263 __ b(deopt, EQ);
3374 } 3264 }
3375 3265
3376
3377 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { 3266 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const {
3378 const intptr_t kNumInputs = 1; 3267 const intptr_t kNumInputs = 1;
3379 const intptr_t kNumTemps = 1; 3268 const intptr_t kNumTemps = 1;
3380 LocationSummary* summary = new (zone) LocationSummary( 3269 LocationSummary* summary = new (zone) LocationSummary(
3381 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); 3270 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
3382 summary->set_in(0, Location::RequiresFpuRegister()); 3271 summary->set_in(0, Location::RequiresFpuRegister());
3383 summary->set_temp(0, Location::RequiresRegister()); 3272 summary->set_temp(0, Location::RequiresRegister());
3384 summary->set_out(0, Location::RequiresRegister()); 3273 summary->set_out(0, Location::RequiresRegister());
3385 return summary; 3274 return summary;
3386 } 3275 }
3387 3276
3388
3389 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3277 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3390 const Register out_reg = locs()->out(0).reg(); 3278 const Register out_reg = locs()->out(0).reg();
3391 const Register temp_reg = locs()->temp(0).reg(); 3279 const Register temp_reg = locs()->temp(0).reg();
3392 const VRegister value = locs()->in(0).fpu_reg(); 3280 const VRegister value = locs()->in(0).fpu_reg();
3393 3281
3394 BoxAllocationSlowPath::Allocate(compiler, this, 3282 BoxAllocationSlowPath::Allocate(compiler, this,
3395 compiler->BoxClassFor(from_representation()), 3283 compiler->BoxClassFor(from_representation()),
3396 out_reg, temp_reg); 3284 out_reg, temp_reg);
3397 3285
3398 switch (from_representation()) { 3286 switch (from_representation()) {
3399 case kUnboxedDouble: 3287 case kUnboxedDouble:
3400 __ StoreDFieldToOffset(value, out_reg, ValueOffset()); 3288 __ StoreDFieldToOffset(value, out_reg, ValueOffset());
3401 break; 3289 break;
3402 case kUnboxedFloat32x4: 3290 case kUnboxedFloat32x4:
3403 case kUnboxedFloat64x2: 3291 case kUnboxedFloat64x2:
3404 case kUnboxedInt32x4: 3292 case kUnboxedInt32x4:
3405 __ StoreQFieldToOffset(value, out_reg, ValueOffset()); 3293 __ StoreQFieldToOffset(value, out_reg, ValueOffset());
3406 break; 3294 break;
3407 default: 3295 default:
3408 UNREACHABLE(); 3296 UNREACHABLE();
3409 break; 3297 break;
3410 } 3298 }
3411 } 3299 }
3412 3300
3413
3414 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { 3301 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const {
3415 const intptr_t kNumInputs = 1; 3302 const intptr_t kNumInputs = 1;
3416 const intptr_t kNumTemps = 0; 3303 const intptr_t kNumTemps = 0;
3417 LocationSummary* summary = new (zone) 3304 LocationSummary* summary = new (zone)
3418 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3305 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3419 summary->set_in(0, Location::RequiresRegister()); 3306 summary->set_in(0, Location::RequiresRegister());
3420 summary->set_out(0, Location::RequiresFpuRegister()); 3307 summary->set_out(0, Location::RequiresFpuRegister());
3421 return summary; 3308 return summary;
3422 } 3309 }
3423 3310
3424
3425 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { 3311 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) {
3426 const Register box = locs()->in(0).reg(); 3312 const Register box = locs()->in(0).reg();
3427 3313
3428 switch (representation()) { 3314 switch (representation()) {
3429 case kUnboxedMint: { 3315 case kUnboxedMint: {
3430 UNIMPLEMENTED(); 3316 UNIMPLEMENTED();
3431 break; 3317 break;
3432 } 3318 }
3433 3319
3434 case kUnboxedDouble: { 3320 case kUnboxedDouble: {
3435 const VRegister result = locs()->out(0).fpu_reg(); 3321 const VRegister result = locs()->out(0).fpu_reg();
3436 __ LoadDFieldFromOffset(result, box, ValueOffset()); 3322 __ LoadDFieldFromOffset(result, box, ValueOffset());
3437 break; 3323 break;
3438 } 3324 }
3439 3325
3440 case kUnboxedFloat32x4: 3326 case kUnboxedFloat32x4:
3441 case kUnboxedFloat64x2: 3327 case kUnboxedFloat64x2:
3442 case kUnboxedInt32x4: { 3328 case kUnboxedInt32x4: {
3443 const VRegister result = locs()->out(0).fpu_reg(); 3329 const VRegister result = locs()->out(0).fpu_reg();
3444 __ LoadQFieldFromOffset(result, box, ValueOffset()); 3330 __ LoadQFieldFromOffset(result, box, ValueOffset());
3445 break; 3331 break;
3446 } 3332 }
3447 3333
3448 default: 3334 default:
3449 UNREACHABLE(); 3335 UNREACHABLE();
3450 break; 3336 break;
3451 } 3337 }
3452 } 3338 }
3453 3339
3454
3455 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { 3340 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) {
3456 const Register box = locs()->in(0).reg(); 3341 const Register box = locs()->in(0).reg();
3457 3342
3458 switch (representation()) { 3343 switch (representation()) {
3459 case kUnboxedMint: { 3344 case kUnboxedMint: {
3460 UNIMPLEMENTED(); 3345 UNIMPLEMENTED();
3461 break; 3346 break;
3462 } 3347 }
3463 3348
3464 case kUnboxedDouble: { 3349 case kUnboxedDouble: {
3465 const VRegister result = locs()->out(0).fpu_reg(); 3350 const VRegister result = locs()->out(0).fpu_reg();
3466 __ SmiUntag(TMP, box); 3351 __ SmiUntag(TMP, box);
3467 __ scvtfdx(result, TMP); 3352 __ scvtfdx(result, TMP);
3468 break; 3353 break;
3469 } 3354 }
3470 3355
3471 default: 3356 default:
3472 UNREACHABLE(); 3357 UNREACHABLE();
3473 break; 3358 break;
3474 } 3359 }
3475 } 3360 }
3476 3361
3477
3478 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3362 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3479 const intptr_t value_cid = value()->Type()->ToCid(); 3363 const intptr_t value_cid = value()->Type()->ToCid();
3480 const intptr_t box_cid = BoxCid(); 3364 const intptr_t box_cid = BoxCid();
3481 3365
3482 if (value_cid == box_cid) { 3366 if (value_cid == box_cid) {
3483 EmitLoadFromBox(compiler); 3367 EmitLoadFromBox(compiler);
3484 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { 3368 } else if (CanConvertSmi() && (value_cid == kSmiCid)) {
3485 EmitSmiConversion(compiler); 3369 EmitSmiConversion(compiler);
3486 } else { 3370 } else {
3487 const Register box = locs()->in(0).reg(); 3371 const Register box = locs()->in(0).reg();
(...skipping 17 matching lines...) Expand all
3505 if (is_smi.IsLinked()) { 3389 if (is_smi.IsLinked()) {
3506 Label done; 3390 Label done;
3507 __ b(&done); 3391 __ b(&done);
3508 __ Bind(&is_smi); 3392 __ Bind(&is_smi);
3509 EmitSmiConversion(compiler); 3393 EmitSmiConversion(compiler);
3510 __ Bind(&done); 3394 __ Bind(&done);
3511 } 3395 }
3512 } 3396 }
3513 } 3397 }
3514 3398
3515
3516 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, 3399 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone,
3517 bool opt) const { 3400 bool opt) const {
3518 ASSERT((from_representation() == kUnboxedInt32) || 3401 ASSERT((from_representation() == kUnboxedInt32) ||
3519 (from_representation() == kUnboxedUint32)); 3402 (from_representation() == kUnboxedUint32));
3520 const intptr_t kNumInputs = 1; 3403 const intptr_t kNumInputs = 1;
3521 const intptr_t kNumTemps = 0; 3404 const intptr_t kNumTemps = 0;
3522 LocationSummary* summary = new (zone) 3405 LocationSummary* summary = new (zone)
3523 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3406 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3524 summary->set_in(0, Location::RequiresRegister()); 3407 summary->set_in(0, Location::RequiresRegister());
3525 summary->set_out(0, Location::RequiresRegister()); 3408 summary->set_out(0, Location::RequiresRegister());
3526 return summary; 3409 return summary;
3527 } 3410 }
3528 3411
3529
3530 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 3412 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3531 Register value = locs()->in(0).reg(); 3413 Register value = locs()->in(0).reg();
3532 Register out = locs()->out(0).reg(); 3414 Register out = locs()->out(0).reg();
3533 ASSERT(value != out); 3415 ASSERT(value != out);
3534 3416
3535 ASSERT(kSmiTagSize == 1); 3417 ASSERT(kSmiTagSize == 1);
3536 // TODO(vegorov) implement and use UBFM/SBFM for this. 3418 // TODO(vegorov) implement and use UBFM/SBFM for this.
3537 __ LslImmediate(out, value, 32); 3419 __ LslImmediate(out, value, 32);
3538 if (from_representation() == kUnboxedInt32) { 3420 if (from_representation() == kUnboxedInt32) {
3539 __ AsrImmediate(out, out, 32 - kSmiTagSize); 3421 __ AsrImmediate(out, out, 32 - kSmiTagSize);
3540 } else { 3422 } else {
3541 ASSERT(from_representation() == kUnboxedUint32); 3423 ASSERT(from_representation() == kUnboxedUint32);
3542 __ LsrImmediate(out, out, 32 - kSmiTagSize); 3424 __ LsrImmediate(out, out, 32 - kSmiTagSize);
3543 } 3425 }
3544 } 3426 }
3545 3427
3546
3547 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr) 3428 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr)
3548 3429
3549
3550 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, 3430 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone,
3551 bool opt) const { 3431 bool opt) const {
3552 const intptr_t kNumInputs = 1; 3432 const intptr_t kNumInputs = 1;
3553 const intptr_t kNumTemps = 0; 3433 const intptr_t kNumTemps = 0;
3554 LocationSummary* summary = new (zone) 3434 LocationSummary* summary = new (zone)
3555 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3435 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3556 summary->set_in(0, Location::RequiresRegister()); 3436 summary->set_in(0, Location::RequiresRegister());
3557 summary->set_out(0, Location::RequiresRegister()); 3437 summary->set_out(0, Location::RequiresRegister());
3558 return summary; 3438 return summary;
3559 } 3439 }
3560 3440
3561
3562 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 3441 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3563 const intptr_t value_cid = value()->Type()->ToCid(); 3442 const intptr_t value_cid = value()->Type()->ToCid();
3564 const Register out = locs()->out(0).reg(); 3443 const Register out = locs()->out(0).reg();
3565 const Register value = locs()->in(0).reg(); 3444 const Register value = locs()->in(0).reg();
3566 Label* deopt = 3445 Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub(
3567 CanDeoptimize() 3446 GetDeoptId(), ICData::kDeoptUnboxInteger)
3568 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) 3447 : NULL;
3569 : NULL;
3570 3448
3571 if (value_cid == kSmiCid) { 3449 if (value_cid == kSmiCid) {
3572 __ SmiUntag(out, value); 3450 __ SmiUntag(out, value);
3573 } else if (value_cid == kMintCid) { 3451 } else if (value_cid == kMintCid) {
3574 __ LoadFieldFromOffset(out, value, Mint::value_offset()); 3452 __ LoadFieldFromOffset(out, value, Mint::value_offset());
3575 } else if (!CanDeoptimize()) { 3453 } else if (!CanDeoptimize()) {
3576 // Type information is not conclusive, but range analysis found 3454 // Type information is not conclusive, but range analysis found
3577 // the value to be in int64 range. Therefore it must be a smi 3455 // the value to be in int64 range. Therefore it must be a smi
3578 // or mint value. 3456 // or mint value.
3579 ASSERT(is_truncating()); 3457 ASSERT(is_truncating());
(...skipping 16 matching lines...) Expand all
3596 3474
3597 // TODO(vegorov): as it is implemented right now truncating unboxing would 3475 // TODO(vegorov): as it is implemented right now truncating unboxing would
3598 // leave "garbage" in the higher word. 3476 // leave "garbage" in the higher word.
3599 if (!is_truncating() && (deopt != NULL)) { 3477 if (!is_truncating() && (deopt != NULL)) {
3600 ASSERT(representation() == kUnboxedInt32); 3478 ASSERT(representation() == kUnboxedInt32);
3601 __ cmp(out, Operand(out, SXTW, 0)); 3479 __ cmp(out, Operand(out, SXTW, 0));
3602 __ b(deopt, NE); 3480 __ b(deopt, NE);
3603 } 3481 }
3604 } 3482 }
3605 3483
3606
3607 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, 3484 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone,
3608 bool opt) const { 3485 bool opt) const {
3609 const intptr_t kNumInputs = 2; 3486 const intptr_t kNumInputs = 2;
3610 const intptr_t kNumTemps = 0; 3487 const intptr_t kNumTemps = 0;
3611 LocationSummary* summary = new (zone) 3488 LocationSummary* summary = new (zone)
3612 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3489 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3613 summary->set_in(0, Location::RequiresFpuRegister()); 3490 summary->set_in(0, Location::RequiresFpuRegister());
3614 summary->set_in(1, Location::RequiresFpuRegister()); 3491 summary->set_in(1, Location::RequiresFpuRegister());
3615 summary->set_out(0, Location::RequiresFpuRegister()); 3492 summary->set_out(0, Location::RequiresFpuRegister());
3616 return summary; 3493 return summary;
3617 } 3494 }
3618 3495
3619
3620 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3496 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3621 const VRegister left = locs()->in(0).fpu_reg(); 3497 const VRegister left = locs()->in(0).fpu_reg();
3622 const VRegister right = locs()->in(1).fpu_reg(); 3498 const VRegister right = locs()->in(1).fpu_reg();
3623 const VRegister result = locs()->out(0).fpu_reg(); 3499 const VRegister result = locs()->out(0).fpu_reg();
3624 switch (op_kind()) { 3500 switch (op_kind()) {
3625 case Token::kADD: 3501 case Token::kADD:
3626 __ faddd(result, left, right); 3502 __ faddd(result, left, right);
3627 break; 3503 break;
3628 case Token::kSUB: 3504 case Token::kSUB:
3629 __ fsubd(result, left, right); 3505 __ fsubd(result, left, right);
3630 break; 3506 break;
3631 case Token::kMUL: 3507 case Token::kMUL:
3632 __ fmuld(result, left, right); 3508 __ fmuld(result, left, right);
3633 break; 3509 break;
3634 case Token::kDIV: 3510 case Token::kDIV:
3635 __ fdivd(result, left, right); 3511 __ fdivd(result, left, right);
3636 break; 3512 break;
3637 default: 3513 default:
3638 UNREACHABLE(); 3514 UNREACHABLE();
3639 } 3515 }
3640 } 3516 }
3641 3517
3642
3643 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, 3518 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone,
3644 bool opt) const { 3519 bool opt) const {
3645 const intptr_t kNumInputs = 1; 3520 const intptr_t kNumInputs = 1;
3646 const intptr_t kNumTemps = 3521 const intptr_t kNumTemps =
3647 op_kind() == MethodRecognizer::kDouble_getIsInfinite ? 1 : 0; 3522 op_kind() == MethodRecognizer::kDouble_getIsInfinite ? 1 : 0;
3648 LocationSummary* summary = new (zone) 3523 LocationSummary* summary = new (zone)
3649 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3524 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3650 summary->set_in(0, Location::RequiresFpuRegister()); 3525 summary->set_in(0, Location::RequiresFpuRegister());
3651 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { 3526 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) {
3652 summary->set_temp(0, Location::RequiresRegister()); 3527 summary->set_temp(0, Location::RequiresRegister());
3653 } 3528 }
3654 summary->set_out(0, Location::RequiresRegister()); 3529 summary->set_out(0, Location::RequiresRegister());
3655 return summary; 3530 return summary;
3656 } 3531 }
3657 3532
3658
3659 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 3533 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
3660 BranchLabels labels) { 3534 BranchLabels labels) {
3661 ASSERT(compiler->is_optimizing()); 3535 ASSERT(compiler->is_optimizing());
3662 const VRegister value = locs()->in(0).fpu_reg(); 3536 const VRegister value = locs()->in(0).fpu_reg();
3663 const bool is_negated = kind() != Token::kEQ; 3537 const bool is_negated = kind() != Token::kEQ;
3664 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { 3538 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) {
3665 __ fcmpd(value, value); 3539 __ fcmpd(value, value);
3666 return is_negated ? VC : VS; 3540 return is_negated ? VC : VS;
3667 } else { 3541 } else {
3668 ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite); 3542 ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite);
3669 const Register temp = locs()->temp(0).reg(); 3543 const Register temp = locs()->temp(0).reg();
3670 __ vmovrd(temp, value, 0); 3544 __ vmovrd(temp, value, 0);
3671 // Mask off the sign. 3545 // Mask off the sign.
3672 __ AndImmediate(temp, temp, 0x7FFFFFFFFFFFFFFFLL); 3546 __ AndImmediate(temp, temp, 0x7FFFFFFFFFFFFFFFLL);
3673 // Compare with +infinity. 3547 // Compare with +infinity.
3674 __ CompareImmediate(temp, 0x7FF0000000000000LL); 3548 __ CompareImmediate(temp, 0x7FF0000000000000LL);
3675 return is_negated ? NE : EQ; 3549 return is_negated ? NE : EQ;
3676 } 3550 }
3677 } 3551 }
3678 3552
3679
3680 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, 3553 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone,
3681 bool opt) const { 3554 bool opt) const {
3682 const intptr_t kNumInputs = 2; 3555 const intptr_t kNumInputs = 2;
3683 const intptr_t kNumTemps = 0; 3556 const intptr_t kNumTemps = 0;
3684 LocationSummary* summary = new (zone) 3557 LocationSummary* summary = new (zone)
3685 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3558 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3686 summary->set_in(0, Location::RequiresFpuRegister()); 3559 summary->set_in(0, Location::RequiresFpuRegister());
3687 summary->set_in(1, Location::RequiresFpuRegister()); 3560 summary->set_in(1, Location::RequiresFpuRegister());
3688 summary->set_out(0, Location::RequiresFpuRegister()); 3561 summary->set_out(0, Location::RequiresFpuRegister());
3689 return summary; 3562 return summary;
3690 } 3563 }
3691 3564
3692
3693 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3565 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3694 const VRegister left = locs()->in(0).fpu_reg(); 3566 const VRegister left = locs()->in(0).fpu_reg();
3695 const VRegister right = locs()->in(1).fpu_reg(); 3567 const VRegister right = locs()->in(1).fpu_reg();
3696 const VRegister result = locs()->out(0).fpu_reg(); 3568 const VRegister result = locs()->out(0).fpu_reg();
3697 3569
3698 switch (op_kind()) { 3570 switch (op_kind()) {
3699 case Token::kADD: 3571 case Token::kADD:
3700 __ vadds(result, left, right); 3572 __ vadds(result, left, right);
3701 break; 3573 break;
3702 case Token::kSUB: 3574 case Token::kSUB:
3703 __ vsubs(result, left, right); 3575 __ vsubs(result, left, right);
3704 break; 3576 break;
3705 case Token::kMUL: 3577 case Token::kMUL:
3706 __ vmuls(result, left, right); 3578 __ vmuls(result, left, right);
3707 break; 3579 break;
3708 case Token::kDIV: 3580 case Token::kDIV:
3709 __ vdivs(result, left, right); 3581 __ vdivs(result, left, right);
3710 break; 3582 break;
3711 default: 3583 default:
3712 UNREACHABLE(); 3584 UNREACHABLE();
3713 } 3585 }
3714 } 3586 }
3715 3587
3716
3717 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, 3588 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone,
3718 bool opt) const { 3589 bool opt) const {
3719 const intptr_t kNumInputs = 2; 3590 const intptr_t kNumInputs = 2;
3720 const intptr_t kNumTemps = 0; 3591 const intptr_t kNumTemps = 0;
3721 LocationSummary* summary = new (zone) 3592 LocationSummary* summary = new (zone)
3722 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3593 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3723 summary->set_in(0, Location::RequiresFpuRegister()); 3594 summary->set_in(0, Location::RequiresFpuRegister());
3724 summary->set_in(1, Location::RequiresFpuRegister()); 3595 summary->set_in(1, Location::RequiresFpuRegister());
3725 summary->set_out(0, Location::RequiresFpuRegister()); 3596 summary->set_out(0, Location::RequiresFpuRegister());
3726 return summary; 3597 return summary;
3727 } 3598 }
3728 3599
3729
3730 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3600 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3731 const VRegister left = locs()->in(0).fpu_reg(); 3601 const VRegister left = locs()->in(0).fpu_reg();
3732 const VRegister right = locs()->in(1).fpu_reg(); 3602 const VRegister right = locs()->in(1).fpu_reg();
3733 const VRegister result = locs()->out(0).fpu_reg(); 3603 const VRegister result = locs()->out(0).fpu_reg();
3734 3604
3735 switch (op_kind()) { 3605 switch (op_kind()) {
3736 case Token::kADD: 3606 case Token::kADD:
3737 __ vaddd(result, left, right); 3607 __ vaddd(result, left, right);
3738 break; 3608 break;
3739 case Token::kSUB: 3609 case Token::kSUB:
3740 __ vsubd(result, left, right); 3610 __ vsubd(result, left, right);
3741 break; 3611 break;
3742 case Token::kMUL: 3612 case Token::kMUL:
3743 __ vmuld(result, left, right); 3613 __ vmuld(result, left, right);
3744 break; 3614 break;
3745 case Token::kDIV: 3615 case Token::kDIV:
3746 __ vdivd(result, left, right); 3616 __ vdivd(result, left, right);
3747 break; 3617 break;
3748 default: 3618 default:
3749 UNREACHABLE(); 3619 UNREACHABLE();
3750 } 3620 }
3751 } 3621 }
3752 3622
3753
3754 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, 3623 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone,
3755 bool opt) const { 3624 bool opt) const {
3756 const intptr_t kNumInputs = 1; 3625 const intptr_t kNumInputs = 1;
3757 const intptr_t kNumTemps = 0; 3626 const intptr_t kNumTemps = 0;
3758 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 3627 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
3759 LocationSummary::kNoCall); 3628 LocationSummary::kNoCall);
3760 summary->set_in(0, Location::RequiresFpuRegister()); 3629 summary->set_in(0, Location::RequiresFpuRegister());
3761 summary->set_out(0, Location::RequiresFpuRegister()); 3630 summary->set_out(0, Location::RequiresFpuRegister());
3762 return summary; 3631 return summary;
3763 } 3632 }
3764 3633
3765
3766 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3634 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3767 const VRegister value = locs()->in(0).fpu_reg(); 3635 const VRegister value = locs()->in(0).fpu_reg();
3768 const VRegister result = locs()->out(0).fpu_reg(); 3636 const VRegister result = locs()->out(0).fpu_reg();
3769 3637
3770 switch (op_kind()) { 3638 switch (op_kind()) {
3771 case MethodRecognizer::kFloat32x4ShuffleX: 3639 case MethodRecognizer::kFloat32x4ShuffleX:
3772 __ vinss(result, 0, value, 0); 3640 __ vinss(result, 0, value, 0);
3773 __ fcvtds(result, result); 3641 __ fcvtds(result, result);
3774 break; 3642 break;
3775 case MethodRecognizer::kFloat32x4ShuffleY: 3643 case MethodRecognizer::kFloat32x4ShuffleY:
(...skipping 23 matching lines...) Expand all
3799 __ vinss(result, 1, value, (mask_ >> 2) & 0x3); 3667 __ vinss(result, 1, value, (mask_ >> 2) & 0x3);
3800 __ vinss(result, 2, value, (mask_ >> 4) & 0x3); 3668 __ vinss(result, 2, value, (mask_ >> 4) & 0x3);
3801 __ vinss(result, 3, value, (mask_ >> 6) & 0x3); 3669 __ vinss(result, 3, value, (mask_ >> 6) & 0x3);
3802 } 3670 }
3803 break; 3671 break;
3804 default: 3672 default:
3805 UNREACHABLE(); 3673 UNREACHABLE();
3806 } 3674 }
3807 } 3675 }
3808 3676
3809
3810 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, 3677 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone,
3811 bool opt) const { 3678 bool opt) const {
3812 const intptr_t kNumInputs = 2; 3679 const intptr_t kNumInputs = 2;
3813 const intptr_t kNumTemps = 0; 3680 const intptr_t kNumTemps = 0;
3814 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 3681 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
3815 LocationSummary::kNoCall); 3682 LocationSummary::kNoCall);
3816 summary->set_in(0, Location::RequiresFpuRegister()); 3683 summary->set_in(0, Location::RequiresFpuRegister());
3817 summary->set_in(1, Location::RequiresFpuRegister()); 3684 summary->set_in(1, Location::RequiresFpuRegister());
3818 summary->set_out(0, Location::RequiresFpuRegister()); 3685 summary->set_out(0, Location::RequiresFpuRegister());
3819 return summary; 3686 return summary;
3820 } 3687 }
3821 3688
3822
3823 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3689 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3824 const VRegister left = locs()->in(0).fpu_reg(); 3690 const VRegister left = locs()->in(0).fpu_reg();
3825 const VRegister right = locs()->in(1).fpu_reg(); 3691 const VRegister right = locs()->in(1).fpu_reg();
3826 const VRegister result = locs()->out(0).fpu_reg(); 3692 const VRegister result = locs()->out(0).fpu_reg();
3827 3693
3828 switch (op_kind()) { 3694 switch (op_kind()) {
3829 case MethodRecognizer::kFloat32x4ShuffleMix: 3695 case MethodRecognizer::kFloat32x4ShuffleMix:
3830 case MethodRecognizer::kInt32x4ShuffleMix: 3696 case MethodRecognizer::kInt32x4ShuffleMix:
3831 __ vinss(result, 0, left, mask_ & 0x3); 3697 __ vinss(result, 0, left, mask_ & 0x3);
3832 __ vinss(result, 1, left, (mask_ >> 2) & 0x3); 3698 __ vinss(result, 1, left, (mask_ >> 2) & 0x3);
3833 __ vinss(result, 2, right, (mask_ >> 4) & 0x3); 3699 __ vinss(result, 2, right, (mask_ >> 4) & 0x3);
3834 __ vinss(result, 3, right, (mask_ >> 6) & 0x3); 3700 __ vinss(result, 3, right, (mask_ >> 6) & 0x3);
3835 break; 3701 break;
3836 default: 3702 default:
3837 UNREACHABLE(); 3703 UNREACHABLE();
3838 } 3704 }
3839 } 3705 }
3840 3706
3841
3842 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, 3707 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone,
3843 bool opt) const { 3708 bool opt) const {
3844 const intptr_t kNumInputs = 1; 3709 const intptr_t kNumInputs = 1;
3845 const intptr_t kNumTemps = 1; 3710 const intptr_t kNumTemps = 1;
3846 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 3711 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
3847 LocationSummary::kNoCall); 3712 LocationSummary::kNoCall);
3848 summary->set_in(0, Location::RequiresFpuRegister()); 3713 summary->set_in(0, Location::RequiresFpuRegister());
3849 summary->set_temp(0, Location::RequiresRegister()); 3714 summary->set_temp(0, Location::RequiresRegister());
3850 summary->set_out(0, Location::RequiresRegister()); 3715 summary->set_out(0, Location::RequiresRegister());
3851 return summary; 3716 return summary;
3852 } 3717 }
3853 3718
3854
3855 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3719 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3856 const VRegister value = locs()->in(0).fpu_reg(); 3720 const VRegister value = locs()->in(0).fpu_reg();
3857 const Register out = locs()->out(0).reg(); 3721 const Register out = locs()->out(0).reg();
3858 const Register temp = locs()->temp(0).reg(); 3722 const Register temp = locs()->temp(0).reg();
3859 3723
3860 // X lane. 3724 // X lane.
3861 __ vmovrs(out, value, 0); 3725 __ vmovrs(out, value, 0);
3862 __ LsrImmediate(out, out, 31); 3726 __ LsrImmediate(out, out, 31);
3863 // Y lane. 3727 // Y lane.
3864 __ vmovrs(temp, value, 1); 3728 __ vmovrs(temp, value, 1);
3865 __ LsrImmediate(temp, temp, 31); 3729 __ LsrImmediate(temp, temp, 31);
3866 __ orr(out, out, Operand(temp, LSL, 1)); 3730 __ orr(out, out, Operand(temp, LSL, 1));
3867 // Z lane. 3731 // Z lane.
3868 __ vmovrs(temp, value, 2); 3732 __ vmovrs(temp, value, 2);
3869 __ LsrImmediate(temp, temp, 31); 3733 __ LsrImmediate(temp, temp, 31);
3870 __ orr(out, out, Operand(temp, LSL, 2)); 3734 __ orr(out, out, Operand(temp, LSL, 2));
3871 // W lane. 3735 // W lane.
3872 __ vmovrs(temp, value, 3); 3736 __ vmovrs(temp, value, 3);
3873 __ LsrImmediate(temp, temp, 31); 3737 __ LsrImmediate(temp, temp, 31);
3874 __ orr(out, out, Operand(temp, LSL, 3)); 3738 __ orr(out, out, Operand(temp, LSL, 3));
3875 // Tag. 3739 // Tag.
3876 __ SmiTag(out); 3740 __ SmiTag(out);
3877 } 3741 }
3878 3742
3879
3880 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( 3743 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary(
3881 Zone* zone, 3744 Zone* zone,
3882 bool opt) const { 3745 bool opt) const {
3883 const intptr_t kNumInputs = 4; 3746 const intptr_t kNumInputs = 4;
3884 const intptr_t kNumTemps = 0; 3747 const intptr_t kNumTemps = 0;
3885 LocationSummary* summary = new (zone) 3748 LocationSummary* summary = new (zone)
3886 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3749 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3887 summary->set_in(0, Location::RequiresFpuRegister()); 3750 summary->set_in(0, Location::RequiresFpuRegister());
3888 summary->set_in(1, Location::RequiresFpuRegister()); 3751 summary->set_in(1, Location::RequiresFpuRegister());
3889 summary->set_in(2, Location::RequiresFpuRegister()); 3752 summary->set_in(2, Location::RequiresFpuRegister());
3890 summary->set_in(3, Location::RequiresFpuRegister()); 3753 summary->set_in(3, Location::RequiresFpuRegister());
3891 summary->set_out(0, Location::RequiresFpuRegister()); 3754 summary->set_out(0, Location::RequiresFpuRegister());
3892 return summary; 3755 return summary;
3893 } 3756 }
3894 3757
3895
3896 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3758 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3897 const VRegister v0 = locs()->in(0).fpu_reg(); 3759 const VRegister v0 = locs()->in(0).fpu_reg();
3898 const VRegister v1 = locs()->in(1).fpu_reg(); 3760 const VRegister v1 = locs()->in(1).fpu_reg();
3899 const VRegister v2 = locs()->in(2).fpu_reg(); 3761 const VRegister v2 = locs()->in(2).fpu_reg();
3900 const VRegister v3 = locs()->in(3).fpu_reg(); 3762 const VRegister v3 = locs()->in(3).fpu_reg();
3901 const VRegister r = locs()->out(0).fpu_reg(); 3763 const VRegister r = locs()->out(0).fpu_reg();
3902 3764
3903 __ fcvtsd(VTMP, v0); 3765 __ fcvtsd(VTMP, v0);
3904 __ vinss(r, 0, VTMP, 0); 3766 __ vinss(r, 0, VTMP, 0);
3905 __ fcvtsd(VTMP, v1); 3767 __ fcvtsd(VTMP, v1);
3906 __ vinss(r, 1, VTMP, 0); 3768 __ vinss(r, 1, VTMP, 0);
3907 __ fcvtsd(VTMP, v2); 3769 __ fcvtsd(VTMP, v2);
3908 __ vinss(r, 2, VTMP, 0); 3770 __ vinss(r, 2, VTMP, 0);
3909 __ fcvtsd(VTMP, v3); 3771 __ fcvtsd(VTMP, v3);
3910 __ vinss(r, 3, VTMP, 0); 3772 __ vinss(r, 3, VTMP, 0);
3911 } 3773 }
3912 3774
3913
3914 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, 3775 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone,
3915 bool opt) const { 3776 bool opt) const {
3916 const intptr_t kNumInputs = 0; 3777 const intptr_t kNumInputs = 0;
3917 const intptr_t kNumTemps = 0; 3778 const intptr_t kNumTemps = 0;
3918 LocationSummary* summary = new (zone) 3779 LocationSummary* summary = new (zone)
3919 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3780 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3920 summary->set_out(0, Location::RequiresFpuRegister()); 3781 summary->set_out(0, Location::RequiresFpuRegister());
3921 return summary; 3782 return summary;
3922 } 3783 }
3923 3784
3924
3925 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3785 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3926 const VRegister v = locs()->out(0).fpu_reg(); 3786 const VRegister v = locs()->out(0).fpu_reg();
3927 __ veor(v, v, v); 3787 __ veor(v, v, v);
3928 } 3788 }
3929 3789
3930
3931 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, 3790 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone,
3932 bool opt) const { 3791 bool opt) const {
3933 const intptr_t kNumInputs = 1; 3792 const intptr_t kNumInputs = 1;
3934 const intptr_t kNumTemps = 0; 3793 const intptr_t kNumTemps = 0;
3935 LocationSummary* summary = new (zone) 3794 LocationSummary* summary = new (zone)
3936 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3795 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3937 summary->set_in(0, Location::RequiresFpuRegister()); 3796 summary->set_in(0, Location::RequiresFpuRegister());
3938 summary->set_out(0, Location::RequiresFpuRegister()); 3797 summary->set_out(0, Location::RequiresFpuRegister());
3939 return summary; 3798 return summary;
3940 } 3799 }
3941 3800
3942
3943 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3801 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3944 const VRegister value = locs()->in(0).fpu_reg(); 3802 const VRegister value = locs()->in(0).fpu_reg();
3945 const VRegister result = locs()->out(0).fpu_reg(); 3803 const VRegister result = locs()->out(0).fpu_reg();
3946 3804
3947 // Convert to Float32. 3805 // Convert to Float32.
3948 __ fcvtsd(VTMP, value); 3806 __ fcvtsd(VTMP, value);
3949 3807
3950 // Splat across all lanes. 3808 // Splat across all lanes.
3951 __ vdups(result, VTMP, 0); 3809 __ vdups(result, VTMP, 0);
3952 } 3810 }
3953 3811
3954
3955 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, 3812 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone,
3956 bool opt) const { 3813 bool opt) const {
3957 const intptr_t kNumInputs = 2; 3814 const intptr_t kNumInputs = 2;
3958 const intptr_t kNumTemps = 0; 3815 const intptr_t kNumTemps = 0;
3959 LocationSummary* summary = new (zone) 3816 LocationSummary* summary = new (zone)
3960 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3817 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3961 summary->set_in(0, Location::RequiresFpuRegister()); 3818 summary->set_in(0, Location::RequiresFpuRegister());
3962 summary->set_in(1, Location::RequiresFpuRegister()); 3819 summary->set_in(1, Location::RequiresFpuRegister());
3963 summary->set_out(0, Location::RequiresFpuRegister()); 3820 summary->set_out(0, Location::RequiresFpuRegister());
3964 return summary; 3821 return summary;
3965 } 3822 }
3966 3823
3967
3968 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3824 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3969 const VRegister left = locs()->in(0).fpu_reg(); 3825 const VRegister left = locs()->in(0).fpu_reg();
3970 const VRegister right = locs()->in(1).fpu_reg(); 3826 const VRegister right = locs()->in(1).fpu_reg();
3971 const VRegister result = locs()->out(0).fpu_reg(); 3827 const VRegister result = locs()->out(0).fpu_reg();
3972 3828
3973 switch (op_kind()) { 3829 switch (op_kind()) {
3974 case MethodRecognizer::kFloat32x4Equal: 3830 case MethodRecognizer::kFloat32x4Equal:
3975 __ vceqs(result, left, right); 3831 __ vceqs(result, left, right);
3976 break; 3832 break;
3977 case MethodRecognizer::kFloat32x4NotEqual: 3833 case MethodRecognizer::kFloat32x4NotEqual:
(...skipping 12 matching lines...) Expand all
3990 break; 3846 break;
3991 case MethodRecognizer::kFloat32x4LessThanOrEqual: 3847 case MethodRecognizer::kFloat32x4LessThanOrEqual:
3992 __ vcges(result, right, left); 3848 __ vcges(result, right, left);
3993 break; 3849 break;
3994 3850
3995 default: 3851 default:
3996 UNREACHABLE(); 3852 UNREACHABLE();
3997 } 3853 }
3998 } 3854 }
3999 3855
4000
4001 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, 3856 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone,
4002 bool opt) const { 3857 bool opt) const {
4003 const intptr_t kNumInputs = 2; 3858 const intptr_t kNumInputs = 2;
4004 const intptr_t kNumTemps = 0; 3859 const intptr_t kNumTemps = 0;
4005 LocationSummary* summary = new (zone) 3860 LocationSummary* summary = new (zone)
4006 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3861 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4007 summary->set_in(0, Location::RequiresFpuRegister()); 3862 summary->set_in(0, Location::RequiresFpuRegister());
4008 summary->set_in(1, Location::RequiresFpuRegister()); 3863 summary->set_in(1, Location::RequiresFpuRegister());
4009 summary->set_out(0, Location::RequiresFpuRegister()); 3864 summary->set_out(0, Location::RequiresFpuRegister());
4010 return summary; 3865 return summary;
4011 } 3866 }
4012 3867
4013
4014 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3868 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4015 const VRegister left = locs()->in(0).fpu_reg(); 3869 const VRegister left = locs()->in(0).fpu_reg();
4016 const VRegister right = locs()->in(1).fpu_reg(); 3870 const VRegister right = locs()->in(1).fpu_reg();
4017 const VRegister result = locs()->out(0).fpu_reg(); 3871 const VRegister result = locs()->out(0).fpu_reg();
4018 3872
4019 switch (op_kind()) { 3873 switch (op_kind()) {
4020 case MethodRecognizer::kFloat32x4Min: 3874 case MethodRecognizer::kFloat32x4Min:
4021 __ vmins(result, left, right); 3875 __ vmins(result, left, right);
4022 break; 3876 break;
4023 case MethodRecognizer::kFloat32x4Max: 3877 case MethodRecognizer::kFloat32x4Max:
4024 __ vmaxs(result, left, right); 3878 __ vmaxs(result, left, right);
4025 break; 3879 break;
4026 default: 3880 default:
4027 UNREACHABLE(); 3881 UNREACHABLE();
4028 } 3882 }
4029 } 3883 }
4030 3884
4031
4032 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, 3885 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone,
4033 bool opt) const { 3886 bool opt) const {
4034 const intptr_t kNumInputs = 1; 3887 const intptr_t kNumInputs = 1;
4035 const intptr_t kNumTemps = 0; 3888 const intptr_t kNumTemps = 0;
4036 LocationSummary* summary = new (zone) 3889 LocationSummary* summary = new (zone)
4037 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3890 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4038 summary->set_in(0, Location::RequiresFpuRegister()); 3891 summary->set_in(0, Location::RequiresFpuRegister());
4039 summary->set_out(0, Location::RequiresFpuRegister()); 3892 summary->set_out(0, Location::RequiresFpuRegister());
4040 return summary; 3893 return summary;
4041 } 3894 }
4042 3895
4043
4044 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3896 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4045 const VRegister left = locs()->in(0).fpu_reg(); 3897 const VRegister left = locs()->in(0).fpu_reg();
4046 const VRegister result = locs()->out(0).fpu_reg(); 3898 const VRegister result = locs()->out(0).fpu_reg();
4047 3899
4048 switch (op_kind()) { 3900 switch (op_kind()) {
4049 case MethodRecognizer::kFloat32x4Sqrt: 3901 case MethodRecognizer::kFloat32x4Sqrt:
4050 __ vsqrts(result, left); 3902 __ vsqrts(result, left);
4051 break; 3903 break;
4052 case MethodRecognizer::kFloat32x4Reciprocal: 3904 case MethodRecognizer::kFloat32x4Reciprocal:
4053 __ VRecps(result, left); 3905 __ VRecps(result, left);
4054 break; 3906 break;
4055 case MethodRecognizer::kFloat32x4ReciprocalSqrt: 3907 case MethodRecognizer::kFloat32x4ReciprocalSqrt:
4056 __ VRSqrts(result, left); 3908 __ VRSqrts(result, left);
4057 break; 3909 break;
4058 default: 3910 default:
4059 UNREACHABLE(); 3911 UNREACHABLE();
4060 } 3912 }
4061 } 3913 }
4062 3914
4063
4064 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, 3915 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone,
4065 bool opt) const { 3916 bool opt) const {
4066 const intptr_t kNumInputs = 2; 3917 const intptr_t kNumInputs = 2;
4067 const intptr_t kNumTemps = 0; 3918 const intptr_t kNumTemps = 0;
4068 LocationSummary* summary = new (zone) 3919 LocationSummary* summary = new (zone)
4069 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3920 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4070 summary->set_in(0, Location::RequiresFpuRegister()); 3921 summary->set_in(0, Location::RequiresFpuRegister());
4071 summary->set_in(1, Location::RequiresFpuRegister()); 3922 summary->set_in(1, Location::RequiresFpuRegister());
4072 summary->set_out(0, Location::RequiresFpuRegister()); 3923 summary->set_out(0, Location::RequiresFpuRegister());
4073 return summary; 3924 return summary;
4074 } 3925 }
4075 3926
4076
4077 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3927 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4078 const VRegister left = locs()->in(0).fpu_reg(); 3928 const VRegister left = locs()->in(0).fpu_reg();
4079 const VRegister right = locs()->in(1).fpu_reg(); 3929 const VRegister right = locs()->in(1).fpu_reg();
4080 const VRegister result = locs()->out(0).fpu_reg(); 3930 const VRegister result = locs()->out(0).fpu_reg();
4081 3931
4082 switch (op_kind()) { 3932 switch (op_kind()) {
4083 case MethodRecognizer::kFloat32x4Scale: 3933 case MethodRecognizer::kFloat32x4Scale:
4084 __ fcvtsd(VTMP, left); 3934 __ fcvtsd(VTMP, left);
4085 __ vdups(result, VTMP, 0); 3935 __ vdups(result, VTMP, 0);
4086 __ vmuls(result, result, right); 3936 __ vmuls(result, result, right);
4087 break; 3937 break;
4088 default: 3938 default:
4089 UNREACHABLE(); 3939 UNREACHABLE();
4090 } 3940 }
4091 } 3941 }
4092 3942
4093
4094 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, 3943 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone,
4095 bool opt) const { 3944 bool opt) const {
4096 const intptr_t kNumInputs = 1; 3945 const intptr_t kNumInputs = 1;
4097 const intptr_t kNumTemps = 0; 3946 const intptr_t kNumTemps = 0;
4098 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 3947 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
4099 LocationSummary::kNoCall); 3948 LocationSummary::kNoCall);
4100 summary->set_in(0, Location::RequiresFpuRegister()); 3949 summary->set_in(0, Location::RequiresFpuRegister());
4101 summary->set_out(0, Location::RequiresFpuRegister()); 3950 summary->set_out(0, Location::RequiresFpuRegister());
4102 return summary; 3951 return summary;
4103 } 3952 }
4104 3953
4105
4106 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3954 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4107 const VRegister left = locs()->in(0).fpu_reg(); 3955 const VRegister left = locs()->in(0).fpu_reg();
4108 const VRegister result = locs()->out(0).fpu_reg(); 3956 const VRegister result = locs()->out(0).fpu_reg();
4109 3957
4110 switch (op_kind()) { 3958 switch (op_kind()) {
4111 case MethodRecognizer::kFloat32x4Negate: 3959 case MethodRecognizer::kFloat32x4Negate:
4112 __ vnegs(result, left); 3960 __ vnegs(result, left);
4113 break; 3961 break;
4114 case MethodRecognizer::kFloat32x4Absolute: 3962 case MethodRecognizer::kFloat32x4Absolute:
4115 __ vabss(result, left); 3963 __ vabss(result, left);
4116 break; 3964 break;
4117 default: 3965 default:
4118 UNREACHABLE(); 3966 UNREACHABLE();
4119 } 3967 }
4120 } 3968 }
4121 3969
4122
4123 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, 3970 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone,
4124 bool opt) const { 3971 bool opt) const {
4125 const intptr_t kNumInputs = 3; 3972 const intptr_t kNumInputs = 3;
4126 const intptr_t kNumTemps = 0; 3973 const intptr_t kNumTemps = 0;
4127 LocationSummary* summary = new (zone) 3974 LocationSummary* summary = new (zone)
4128 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3975 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4129 summary->set_in(0, Location::RequiresFpuRegister()); 3976 summary->set_in(0, Location::RequiresFpuRegister());
4130 summary->set_in(1, Location::RequiresFpuRegister()); 3977 summary->set_in(1, Location::RequiresFpuRegister());
4131 summary->set_in(2, Location::RequiresFpuRegister()); 3978 summary->set_in(2, Location::RequiresFpuRegister());
4132 summary->set_out(0, Location::RequiresFpuRegister()); 3979 summary->set_out(0, Location::RequiresFpuRegister());
4133 return summary; 3980 return summary;
4134 } 3981 }
4135 3982
4136
4137 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3983 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4138 const VRegister left = locs()->in(0).fpu_reg(); 3984 const VRegister left = locs()->in(0).fpu_reg();
4139 const VRegister lower = locs()->in(1).fpu_reg(); 3985 const VRegister lower = locs()->in(1).fpu_reg();
4140 const VRegister upper = locs()->in(2).fpu_reg(); 3986 const VRegister upper = locs()->in(2).fpu_reg();
4141 const VRegister result = locs()->out(0).fpu_reg(); 3987 const VRegister result = locs()->out(0).fpu_reg();
4142 __ vmins(result, left, upper); 3988 __ vmins(result, left, upper);
4143 __ vmaxs(result, result, lower); 3989 __ vmaxs(result, result, lower);
4144 } 3990 }
4145 3991
4146
4147 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, 3992 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone,
4148 bool opt) const { 3993 bool opt) const {
4149 const intptr_t kNumInputs = 2; 3994 const intptr_t kNumInputs = 2;
4150 const intptr_t kNumTemps = 0; 3995 const intptr_t kNumTemps = 0;
4151 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 3996 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
4152 LocationSummary::kNoCall); 3997 LocationSummary::kNoCall);
4153 summary->set_in(0, Location::RequiresFpuRegister()); 3998 summary->set_in(0, Location::RequiresFpuRegister());
4154 summary->set_in(1, Location::RequiresFpuRegister()); 3999 summary->set_in(1, Location::RequiresFpuRegister());
4155 summary->set_out(0, Location::RequiresFpuRegister()); 4000 summary->set_out(0, Location::RequiresFpuRegister());
4156 return summary; 4001 return summary;
4157 } 4002 }
4158 4003
4159
4160 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4004 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4161 const VRegister replacement = locs()->in(0).fpu_reg(); 4005 const VRegister replacement = locs()->in(0).fpu_reg();
4162 const VRegister value = locs()->in(1).fpu_reg(); 4006 const VRegister value = locs()->in(1).fpu_reg();
4163 const VRegister result = locs()->out(0).fpu_reg(); 4007 const VRegister result = locs()->out(0).fpu_reg();
4164 4008
4165 __ fcvtsd(VTMP, replacement); 4009 __ fcvtsd(VTMP, replacement);
4166 if (result != value) { 4010 if (result != value) {
4167 __ vmov(result, value); 4011 __ vmov(result, value);
4168 } 4012 }
4169 4013
4170 switch (op_kind()) { 4014 switch (op_kind()) {
4171 case MethodRecognizer::kFloat32x4WithX: 4015 case MethodRecognizer::kFloat32x4WithX:
4172 __ vinss(result, 0, VTMP, 0); 4016 __ vinss(result, 0, VTMP, 0);
4173 break; 4017 break;
4174 case MethodRecognizer::kFloat32x4WithY: 4018 case MethodRecognizer::kFloat32x4WithY:
4175 __ vinss(result, 1, VTMP, 0); 4019 __ vinss(result, 1, VTMP, 0);
4176 break; 4020 break;
4177 case MethodRecognizer::kFloat32x4WithZ: 4021 case MethodRecognizer::kFloat32x4WithZ:
4178 __ vinss(result, 2, VTMP, 0); 4022 __ vinss(result, 2, VTMP, 0);
4179 break; 4023 break;
4180 case MethodRecognizer::kFloat32x4WithW: 4024 case MethodRecognizer::kFloat32x4WithW:
4181 __ vinss(result, 3, VTMP, 0); 4025 __ vinss(result, 3, VTMP, 0);
4182 break; 4026 break;
4183 default: 4027 default:
4184 UNREACHABLE(); 4028 UNREACHABLE();
4185 } 4029 }
4186 } 4030 }
4187 4031
4188
4189 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, 4032 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone,
4190 bool opt) const { 4033 bool opt) const {
4191 const intptr_t kNumInputs = 1; 4034 const intptr_t kNumInputs = 1;
4192 const intptr_t kNumTemps = 0; 4035 const intptr_t kNumTemps = 0;
4193 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 4036 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
4194 LocationSummary::kNoCall); 4037 LocationSummary::kNoCall);
4195 summary->set_in(0, Location::RequiresFpuRegister()); 4038 summary->set_in(0, Location::RequiresFpuRegister());
4196 summary->set_out(0, Location::RequiresFpuRegister()); 4039 summary->set_out(0, Location::RequiresFpuRegister());
4197 return summary; 4040 return summary;
4198 } 4041 }
4199 4042
4200
4201 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 4043 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
4202 const VRegister value = locs()->in(0).fpu_reg(); 4044 const VRegister value = locs()->in(0).fpu_reg();
4203 const VRegister result = locs()->out(0).fpu_reg(); 4045 const VRegister result = locs()->out(0).fpu_reg();
4204 4046
4205 if (value != result) { 4047 if (value != result) {
4206 __ vmov(result, value); 4048 __ vmov(result, value);
4207 } 4049 }
4208 } 4050 }
4209 4051
4210
4211 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, 4052 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone,
4212 bool opt) const { 4053 bool opt) const {
4213 const intptr_t kNumInputs = 1; 4054 const intptr_t kNumInputs = 1;
4214 const intptr_t kNumTemps = 0; 4055 const intptr_t kNumTemps = 0;
4215 LocationSummary* summary = new (zone) 4056 LocationSummary* summary = new (zone)
4216 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4057 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4217 summary->set_in(0, Location::RequiresFpuRegister()); 4058 summary->set_in(0, Location::RequiresFpuRegister());
4218 summary->set_out(0, Location::RequiresFpuRegister()); 4059 summary->set_out(0, Location::RequiresFpuRegister());
4219 return summary; 4060 return summary;
4220 } 4061 }
4221 4062
4222
4223 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4063 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4224 const VRegister value = locs()->in(0).fpu_reg(); 4064 const VRegister value = locs()->in(0).fpu_reg();
4225 const VRegister result = locs()->out(0).fpu_reg(); 4065 const VRegister result = locs()->out(0).fpu_reg();
4226 4066
4227 switch (op_kind()) { 4067 switch (op_kind()) {
4228 case MethodRecognizer::kFloat64x2GetX: 4068 case MethodRecognizer::kFloat64x2GetX:
4229 __ vinsd(result, 0, value, 0); 4069 __ vinsd(result, 0, value, 0);
4230 break; 4070 break;
4231 case MethodRecognizer::kFloat64x2GetY: 4071 case MethodRecognizer::kFloat64x2GetY:
4232 __ vinsd(result, 0, value, 1); 4072 __ vinsd(result, 0, value, 1);
4233 break; 4073 break;
4234 default: 4074 default:
4235 UNREACHABLE(); 4075 UNREACHABLE();
4236 } 4076 }
4237 } 4077 }
4238 4078
4239
4240 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, 4079 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone,
4241 bool opt) const { 4080 bool opt) const {
4242 const intptr_t kNumInputs = 0; 4081 const intptr_t kNumInputs = 0;
4243 const intptr_t kNumTemps = 0; 4082 const intptr_t kNumTemps = 0;
4244 LocationSummary* summary = new (zone) 4083 LocationSummary* summary = new (zone)
4245 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4084 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4246 summary->set_out(0, Location::RequiresFpuRegister()); 4085 summary->set_out(0, Location::RequiresFpuRegister());
4247 return summary; 4086 return summary;
4248 } 4087 }
4249 4088
4250
4251 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4089 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4252 const VRegister v = locs()->out(0).fpu_reg(); 4090 const VRegister v = locs()->out(0).fpu_reg();
4253 __ veor(v, v, v); 4091 __ veor(v, v, v);
4254 } 4092 }
4255 4093
4256
4257 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, 4094 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone,
4258 bool opt) const { 4095 bool opt) const {
4259 const intptr_t kNumInputs = 1; 4096 const intptr_t kNumInputs = 1;
4260 const intptr_t kNumTemps = 0; 4097 const intptr_t kNumTemps = 0;
4261 LocationSummary* summary = new (zone) 4098 LocationSummary* summary = new (zone)
4262 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4099 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4263 summary->set_in(0, Location::RequiresFpuRegister()); 4100 summary->set_in(0, Location::RequiresFpuRegister());
4264 summary->set_out(0, Location::RequiresFpuRegister()); 4101 summary->set_out(0, Location::RequiresFpuRegister());
4265 return summary; 4102 return summary;
4266 } 4103 }
4267 4104
4268
4269 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4105 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4270 const VRegister value = locs()->in(0).fpu_reg(); 4106 const VRegister value = locs()->in(0).fpu_reg();
4271 const VRegister result = locs()->out(0).fpu_reg(); 4107 const VRegister result = locs()->out(0).fpu_reg();
4272 __ vdupd(result, value, 0); 4108 __ vdupd(result, value, 0);
4273 } 4109 }
4274 4110
4275
4276 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( 4111 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary(
4277 Zone* zone, 4112 Zone* zone,
4278 bool opt) const { 4113 bool opt) const {
4279 const intptr_t kNumInputs = 2; 4114 const intptr_t kNumInputs = 2;
4280 const intptr_t kNumTemps = 0; 4115 const intptr_t kNumTemps = 0;
4281 LocationSummary* summary = new (zone) 4116 LocationSummary* summary = new (zone)
4282 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4117 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4283 summary->set_in(0, Location::RequiresFpuRegister()); 4118 summary->set_in(0, Location::RequiresFpuRegister());
4284 summary->set_in(1, Location::RequiresFpuRegister()); 4119 summary->set_in(1, Location::RequiresFpuRegister());
4285 summary->set_out(0, Location::RequiresFpuRegister()); 4120 summary->set_out(0, Location::RequiresFpuRegister());
4286 return summary; 4121 return summary;
4287 } 4122 }
4288 4123
4289
4290 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4124 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4291 const VRegister v0 = locs()->in(0).fpu_reg(); 4125 const VRegister v0 = locs()->in(0).fpu_reg();
4292 const VRegister v1 = locs()->in(1).fpu_reg(); 4126 const VRegister v1 = locs()->in(1).fpu_reg();
4293 const VRegister r = locs()->out(0).fpu_reg(); 4127 const VRegister r = locs()->out(0).fpu_reg();
4294 __ vinsd(r, 0, v0, 0); 4128 __ vinsd(r, 0, v0, 0);
4295 __ vinsd(r, 1, v1, 0); 4129 __ vinsd(r, 1, v1, 0);
4296 } 4130 }
4297 4131
4298
4299 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( 4132 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary(
4300 Zone* zone, 4133 Zone* zone,
4301 bool opt) const { 4134 bool opt) const {
4302 const intptr_t kNumInputs = 1; 4135 const intptr_t kNumInputs = 1;
4303 const intptr_t kNumTemps = 0; 4136 const intptr_t kNumTemps = 0;
4304 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 4137 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
4305 LocationSummary::kNoCall); 4138 LocationSummary::kNoCall);
4306 summary->set_in(0, Location::RequiresFpuRegister()); 4139 summary->set_in(0, Location::RequiresFpuRegister());
4307 summary->set_out(0, Location::RequiresFpuRegister()); 4140 summary->set_out(0, Location::RequiresFpuRegister());
4308 return summary; 4141 return summary;
4309 } 4142 }
4310 4143
4311
4312 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 4144 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
4313 const VRegister q = locs()->in(0).fpu_reg(); 4145 const VRegister q = locs()->in(0).fpu_reg();
4314 const VRegister r = locs()->out(0).fpu_reg(); 4146 const VRegister r = locs()->out(0).fpu_reg();
4315 4147
4316 // Zero register. 4148 // Zero register.
4317 __ veor(r, r, r); 4149 __ veor(r, r, r);
4318 // Set X lane. 4150 // Set X lane.
4319 __ vinsd(VTMP, 0, q, 0); 4151 __ vinsd(VTMP, 0, q, 0);
4320 __ fcvtsd(VTMP, VTMP); 4152 __ fcvtsd(VTMP, VTMP);
4321 __ vinss(r, 0, VTMP, 0); 4153 __ vinss(r, 0, VTMP, 0);
4322 // Set Y lane. 4154 // Set Y lane.
4323 __ vinsd(VTMP, 0, q, 1); 4155 __ vinsd(VTMP, 0, q, 1);
4324 __ fcvtsd(VTMP, VTMP); 4156 __ fcvtsd(VTMP, VTMP);
4325 __ vinss(r, 1, VTMP, 0); 4157 __ vinss(r, 1, VTMP, 0);
4326 } 4158 }
4327 4159
4328
4329 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( 4160 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary(
4330 Zone* zone, 4161 Zone* zone,
4331 bool opt) const { 4162 bool opt) const {
4332 const intptr_t kNumInputs = 1; 4163 const intptr_t kNumInputs = 1;
4333 const intptr_t kNumTemps = 0; 4164 const intptr_t kNumTemps = 0;
4334 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 4165 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
4335 LocationSummary::kNoCall); 4166 LocationSummary::kNoCall);
4336 summary->set_in(0, Location::RequiresFpuRegister()); 4167 summary->set_in(0, Location::RequiresFpuRegister());
4337 summary->set_out(0, Location::RequiresFpuRegister()); 4168 summary->set_out(0, Location::RequiresFpuRegister());
4338 return summary; 4169 return summary;
4339 } 4170 }
4340 4171
4341
4342 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 4172 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
4343 const VRegister q = locs()->in(0).fpu_reg(); 4173 const VRegister q = locs()->in(0).fpu_reg();
4344 const VRegister r = locs()->out(0).fpu_reg(); 4174 const VRegister r = locs()->out(0).fpu_reg();
4345 4175
4346 // Set X. 4176 // Set X.
4347 __ vinss(VTMP, 0, q, 0); 4177 __ vinss(VTMP, 0, q, 0);
4348 __ fcvtds(VTMP, VTMP); 4178 __ fcvtds(VTMP, VTMP);
4349 __ vinsd(r, 0, VTMP, 0); 4179 __ vinsd(r, 0, VTMP, 0);
4350 // Set Y. 4180 // Set Y.
4351 __ vinss(VTMP, 0, q, 1); 4181 __ vinss(VTMP, 0, q, 1);
4352 __ fcvtds(VTMP, VTMP); 4182 __ fcvtds(VTMP, VTMP);
4353 __ vinsd(r, 1, VTMP, 0); 4183 __ vinsd(r, 1, VTMP, 0);
4354 } 4184 }
4355 4185
4356
4357 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, 4186 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone,
4358 bool opt) const { 4187 bool opt) const {
4359 const intptr_t kNumInputs = 1; 4188 const intptr_t kNumInputs = 1;
4360 const intptr_t kNumTemps = 0; 4189 const intptr_t kNumTemps = 0;
4361 LocationSummary* summary = new (zone) 4190 LocationSummary* summary = new (zone)
4362 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4191 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4363 4192
4364 if (representation() == kTagged) { 4193 if (representation() == kTagged) {
4365 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); 4194 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask);
4366 summary->set_in(0, Location::RequiresFpuRegister()); 4195 summary->set_in(0, Location::RequiresFpuRegister());
4367 summary->set_out(0, Location::RequiresRegister()); 4196 summary->set_out(0, Location::RequiresRegister());
4368 } else { 4197 } else {
4369 summary->set_in(0, Location::RequiresFpuRegister()); 4198 summary->set_in(0, Location::RequiresFpuRegister());
4370 summary->set_out(0, Location::RequiresFpuRegister()); 4199 summary->set_out(0, Location::RequiresFpuRegister());
4371 } 4200 }
4372 return summary; 4201 return summary;
4373 } 4202 }
4374 4203
4375
4376 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4204 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4377 const VRegister value = locs()->in(0).fpu_reg(); 4205 const VRegister value = locs()->in(0).fpu_reg();
4378 4206
4379 if ((op_kind() == MethodRecognizer::kFloat64x2GetSignMask)) { 4207 if ((op_kind() == MethodRecognizer::kFloat64x2GetSignMask)) {
4380 const Register out = locs()->out(0).reg(); 4208 const Register out = locs()->out(0).reg();
4381 4209
4382 // Bits of X lane. 4210 // Bits of X lane.
4383 __ vmovrd(out, value, 0); 4211 __ vmovrd(out, value, 0);
4384 __ LsrImmediate(out, out, 63); 4212 __ LsrImmediate(out, out, 63);
4385 // Bits of Y lane. 4213 // Bits of Y lane.
(...skipping 15 matching lines...) Expand all
4401 __ vabsd(result, value); 4229 __ vabsd(result, value);
4402 break; 4230 break;
4403 case MethodRecognizer::kFloat64x2Sqrt: 4231 case MethodRecognizer::kFloat64x2Sqrt:
4404 __ vsqrtd(result, value); 4232 __ vsqrtd(result, value);
4405 break; 4233 break;
4406 default: 4234 default:
4407 UNREACHABLE(); 4235 UNREACHABLE();
4408 } 4236 }
4409 } 4237 }
4410 4238
4411
4412 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, 4239 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone,
4413 bool opt) const { 4240 bool opt) const {
4414 const intptr_t kNumInputs = 2; 4241 const intptr_t kNumInputs = 2;
4415 const intptr_t kNumTemps = 0; 4242 const intptr_t kNumTemps = 0;
4416 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 4243 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
4417 LocationSummary::kNoCall); 4244 LocationSummary::kNoCall);
4418 summary->set_in(0, Location::RequiresFpuRegister()); 4245 summary->set_in(0, Location::RequiresFpuRegister());
4419 summary->set_in(1, Location::RequiresFpuRegister()); 4246 summary->set_in(1, Location::RequiresFpuRegister());
4420 summary->set_out(0, Location::SameAsFirstInput()); 4247 summary->set_out(0, Location::SameAsFirstInput());
4421 return summary; 4248 return summary;
4422 } 4249 }
4423 4250
4424
4425 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4251 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4426 const VRegister left = locs()->in(0).fpu_reg(); 4252 const VRegister left = locs()->in(0).fpu_reg();
4427 const VRegister right = locs()->in(1).fpu_reg(); 4253 const VRegister right = locs()->in(1).fpu_reg();
4428 const VRegister out = locs()->out(0).fpu_reg(); 4254 const VRegister out = locs()->out(0).fpu_reg();
4429 ASSERT(left == out); 4255 ASSERT(left == out);
4430 4256
4431 switch (op_kind()) { 4257 switch (op_kind()) {
4432 case MethodRecognizer::kFloat64x2Scale: 4258 case MethodRecognizer::kFloat64x2Scale:
4433 __ vdupd(VTMP, right, 0); 4259 __ vdupd(VTMP, right, 0);
4434 __ vmuld(out, left, VTMP); 4260 __ vmuld(out, left, VTMP);
4435 break; 4261 break;
4436 case MethodRecognizer::kFloat64x2WithX: 4262 case MethodRecognizer::kFloat64x2WithX:
4437 __ vinsd(out, 0, right, 0); 4263 __ vinsd(out, 0, right, 0);
4438 break; 4264 break;
4439 case MethodRecognizer::kFloat64x2WithY: 4265 case MethodRecognizer::kFloat64x2WithY:
4440 __ vinsd(out, 1, right, 0); 4266 __ vinsd(out, 1, right, 0);
4441 break; 4267 break;
4442 case MethodRecognizer::kFloat64x2Min: 4268 case MethodRecognizer::kFloat64x2Min:
4443 __ vmind(out, left, right); 4269 __ vmind(out, left, right);
4444 break; 4270 break;
4445 case MethodRecognizer::kFloat64x2Max: 4271 case MethodRecognizer::kFloat64x2Max:
4446 __ vmaxd(out, left, right); 4272 __ vmaxd(out, left, right);
4447 break; 4273 break;
4448 default: 4274 default:
4449 UNREACHABLE(); 4275 UNREACHABLE();
4450 } 4276 }
4451 } 4277 }
4452 4278
4453
4454 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, 4279 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone,
4455 bool opt) const { 4280 bool opt) const {
4456 const intptr_t kNumInputs = 4; 4281 const intptr_t kNumInputs = 4;
4457 const intptr_t kNumTemps = 0; 4282 const intptr_t kNumTemps = 0;
4458 LocationSummary* summary = new (zone) 4283 LocationSummary* summary = new (zone)
4459 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4284 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4460 summary->set_in(0, Location::RequiresRegister()); 4285 summary->set_in(0, Location::RequiresRegister());
4461 summary->set_in(1, Location::RequiresRegister()); 4286 summary->set_in(1, Location::RequiresRegister());
4462 summary->set_in(2, Location::RequiresRegister()); 4287 summary->set_in(2, Location::RequiresRegister());
4463 summary->set_in(3, Location::RequiresRegister()); 4288 summary->set_in(3, Location::RequiresRegister());
4464 summary->set_out(0, Location::RequiresFpuRegister()); 4289 summary->set_out(0, Location::RequiresFpuRegister());
4465 return summary; 4290 return summary;
4466 } 4291 }
4467 4292
4468
4469 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4293 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4470 const Register v0 = locs()->in(0).reg(); 4294 const Register v0 = locs()->in(0).reg();
4471 const Register v1 = locs()->in(1).reg(); 4295 const Register v1 = locs()->in(1).reg();
4472 const Register v2 = locs()->in(2).reg(); 4296 const Register v2 = locs()->in(2).reg();
4473 const Register v3 = locs()->in(3).reg(); 4297 const Register v3 = locs()->in(3).reg();
4474 const VRegister result = locs()->out(0).fpu_reg(); 4298 const VRegister result = locs()->out(0).fpu_reg();
4475 __ veor(result, result, result); 4299 __ veor(result, result, result);
4476 __ vinsw(result, 0, v0); 4300 __ vinsw(result, 0, v0);
4477 __ vinsw(result, 1, v1); 4301 __ vinsw(result, 1, v1);
4478 __ vinsw(result, 2, v2); 4302 __ vinsw(result, 2, v2);
4479 __ vinsw(result, 3, v3); 4303 __ vinsw(result, 3, v3);
4480 } 4304 }
4481 4305
4482
4483 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( 4306 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary(
4484 Zone* zone, 4307 Zone* zone,
4485 bool opt) const { 4308 bool opt) const {
4486 const intptr_t kNumInputs = 4; 4309 const intptr_t kNumInputs = 4;
4487 const intptr_t kNumTemps = 1; 4310 const intptr_t kNumTemps = 1;
4488 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 4311 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
4489 LocationSummary::kNoCall); 4312 LocationSummary::kNoCall);
4490 summary->set_in(0, Location::RequiresRegister()); 4313 summary->set_in(0, Location::RequiresRegister());
4491 summary->set_in(1, Location::RequiresRegister()); 4314 summary->set_in(1, Location::RequiresRegister());
4492 summary->set_in(2, Location::RequiresRegister()); 4315 summary->set_in(2, Location::RequiresRegister());
4493 summary->set_in(3, Location::RequiresRegister()); 4316 summary->set_in(3, Location::RequiresRegister());
4494 summary->set_temp(0, Location::RequiresRegister()); 4317 summary->set_temp(0, Location::RequiresRegister());
4495 summary->set_out(0, Location::RequiresFpuRegister()); 4318 summary->set_out(0, Location::RequiresFpuRegister());
4496 return summary; 4319 return summary;
4497 } 4320 }
4498 4321
4499
4500 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4322 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4501 const Register v0 = locs()->in(0).reg(); 4323 const Register v0 = locs()->in(0).reg();
4502 const Register v1 = locs()->in(1).reg(); 4324 const Register v1 = locs()->in(1).reg();
4503 const Register v2 = locs()->in(2).reg(); 4325 const Register v2 = locs()->in(2).reg();
4504 const Register v3 = locs()->in(3).reg(); 4326 const Register v3 = locs()->in(3).reg();
4505 const Register temp = locs()->temp(0).reg(); 4327 const Register temp = locs()->temp(0).reg();
4506 const VRegister result = locs()->out(0).fpu_reg(); 4328 const VRegister result = locs()->out(0).fpu_reg();
4507 4329
4508 __ veor(result, result, result); 4330 __ veor(result, result, result);
4509 __ LoadImmediate(temp, 0xffffffff); 4331 __ LoadImmediate(temp, 0xffffffff);
(...skipping 13 matching lines...) Expand all
4523 __ CompareRegisters(v2, TMP2); 4345 __ CompareRegisters(v2, TMP2);
4524 __ csel(TMP, temp, ZR, EQ); 4346 __ csel(TMP, temp, ZR, EQ);
4525 __ vinsw(result, 2, TMP); 4347 __ vinsw(result, 2, TMP);
4526 4348
4527 // __ CompareObject(v3, Bool::True()); 4349 // __ CompareObject(v3, Bool::True());
4528 __ CompareRegisters(v3, TMP2); 4350 __ CompareRegisters(v3, TMP2);
4529 __ csel(TMP, temp, ZR, EQ); 4351 __ csel(TMP, temp, ZR, EQ);
4530 __ vinsw(result, 3, TMP); 4352 __ vinsw(result, 3, TMP);
4531 } 4353 }
4532 4354
4533
4534 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, 4355 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone,
4535 bool opt) const { 4356 bool opt) const {
4536 const intptr_t kNumInputs = 1; 4357 const intptr_t kNumInputs = 1;
4537 const intptr_t kNumTemps = 0; 4358 const intptr_t kNumTemps = 0;
4538 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 4359 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
4539 LocationSummary::kNoCall); 4360 LocationSummary::kNoCall);
4540 summary->set_in(0, Location::RequiresFpuRegister()); 4361 summary->set_in(0, Location::RequiresFpuRegister());
4541 summary->set_out(0, Location::RequiresRegister()); 4362 summary->set_out(0, Location::RequiresRegister());
4542 return summary; 4363 return summary;
4543 } 4364 }
4544 4365
4545
4546 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4366 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4547 const VRegister value = locs()->in(0).fpu_reg(); 4367 const VRegister value = locs()->in(0).fpu_reg();
4548 const Register result = locs()->out(0).reg(); 4368 const Register result = locs()->out(0).reg();
4549 4369
4550 switch (op_kind()) { 4370 switch (op_kind()) {
4551 case MethodRecognizer::kInt32x4GetFlagX: 4371 case MethodRecognizer::kInt32x4GetFlagX:
4552 __ vmovrs(result, value, 0); 4372 __ vmovrs(result, value, 0);
4553 break; 4373 break;
4554 case MethodRecognizer::kInt32x4GetFlagY: 4374 case MethodRecognizer::kInt32x4GetFlagY:
4555 __ vmovrs(result, value, 1); 4375 __ vmovrs(result, value, 1);
4556 break; 4376 break;
4557 case MethodRecognizer::kInt32x4GetFlagZ: 4377 case MethodRecognizer::kInt32x4GetFlagZ:
4558 __ vmovrs(result, value, 2); 4378 __ vmovrs(result, value, 2);
4559 break; 4379 break;
4560 case MethodRecognizer::kInt32x4GetFlagW: 4380 case MethodRecognizer::kInt32x4GetFlagW:
4561 __ vmovrs(result, value, 3); 4381 __ vmovrs(result, value, 3);
4562 break; 4382 break;
4563 default: 4383 default:
4564 UNREACHABLE(); 4384 UNREACHABLE();
4565 } 4385 }
4566 4386
4567 __ tst(result, Operand(result)); 4387 __ tst(result, Operand(result));
4568 __ LoadObject(result, Bool::True()); 4388 __ LoadObject(result, Bool::True());
4569 __ LoadObject(TMP, Bool::False()); 4389 __ LoadObject(TMP, Bool::False());
4570 __ csel(result, TMP, result, EQ); 4390 __ csel(result, TMP, result, EQ);
4571 } 4391 }
4572 4392
4573
4574 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, 4393 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone,
4575 bool opt) const { 4394 bool opt) const {
4576 const intptr_t kNumInputs = 3; 4395 const intptr_t kNumInputs = 3;
4577 const intptr_t kNumTemps = 1; 4396 const intptr_t kNumTemps = 1;
4578 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 4397 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
4579 LocationSummary::kNoCall); 4398 LocationSummary::kNoCall);
4580 summary->set_in(0, Location::RequiresFpuRegister()); 4399 summary->set_in(0, Location::RequiresFpuRegister());
4581 summary->set_in(1, Location::RequiresFpuRegister()); 4400 summary->set_in(1, Location::RequiresFpuRegister());
4582 summary->set_in(2, Location::RequiresFpuRegister()); 4401 summary->set_in(2, Location::RequiresFpuRegister());
4583 summary->set_temp(0, Location::RequiresFpuRegister()); 4402 summary->set_temp(0, Location::RequiresFpuRegister());
4584 summary->set_out(0, Location::RequiresFpuRegister()); 4403 summary->set_out(0, Location::RequiresFpuRegister());
4585 return summary; 4404 return summary;
4586 } 4405 }
4587 4406
4588
4589 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4407 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4590 const VRegister mask = locs()->in(0).fpu_reg(); 4408 const VRegister mask = locs()->in(0).fpu_reg();
4591 const VRegister trueValue = locs()->in(1).fpu_reg(); 4409 const VRegister trueValue = locs()->in(1).fpu_reg();
4592 const VRegister falseValue = locs()->in(2).fpu_reg(); 4410 const VRegister falseValue = locs()->in(2).fpu_reg();
4593 const VRegister out = locs()->out(0).fpu_reg(); 4411 const VRegister out = locs()->out(0).fpu_reg();
4594 const VRegister temp = locs()->temp(0).fpu_reg(); 4412 const VRegister temp = locs()->temp(0).fpu_reg();
4595 4413
4596 // Copy mask. 4414 // Copy mask.
4597 __ vmov(temp, mask); 4415 __ vmov(temp, mask);
4598 // Invert it. 4416 // Invert it.
4599 __ vnot(temp, temp); 4417 __ vnot(temp, temp);
4600 // mask = mask & trueValue. 4418 // mask = mask & trueValue.
4601 __ vand(mask, mask, trueValue); 4419 __ vand(mask, mask, trueValue);
4602 // temp = temp & falseValue. 4420 // temp = temp & falseValue.
4603 __ vand(temp, temp, falseValue); 4421 __ vand(temp, temp, falseValue);
4604 // out = mask | temp. 4422 // out = mask | temp.
4605 __ vorr(out, mask, temp); 4423 __ vorr(out, mask, temp);
4606 } 4424 }
4607 4425
4608
4609 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, 4426 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone,
4610 bool opt) const { 4427 bool opt) const {
4611 const intptr_t kNumInputs = 2; 4428 const intptr_t kNumInputs = 2;
4612 const intptr_t kNumTemps = 0; 4429 const intptr_t kNumTemps = 0;
4613 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 4430 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
4614 LocationSummary::kNoCall); 4431 LocationSummary::kNoCall);
4615 summary->set_in(0, Location::RequiresFpuRegister()); 4432 summary->set_in(0, Location::RequiresFpuRegister());
4616 summary->set_in(1, Location::RequiresRegister()); 4433 summary->set_in(1, Location::RequiresRegister());
4617 summary->set_out(0, Location::RequiresFpuRegister()); 4434 summary->set_out(0, Location::RequiresFpuRegister());
4618 return summary; 4435 return summary;
4619 } 4436 }
4620 4437
4621
4622 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4438 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4623 const VRegister mask = locs()->in(0).fpu_reg(); 4439 const VRegister mask = locs()->in(0).fpu_reg();
4624 const Register flag = locs()->in(1).reg(); 4440 const Register flag = locs()->in(1).reg();
4625 const VRegister result = locs()->out(0).fpu_reg(); 4441 const VRegister result = locs()->out(0).fpu_reg();
4626 4442
4627 if (result != mask) { 4443 if (result != mask) {
4628 __ vmov(result, mask); 4444 __ vmov(result, mask);
4629 } 4445 }
4630 4446
4631 __ CompareObject(flag, Bool::True()); 4447 __ CompareObject(flag, Bool::True());
(...skipping 10 matching lines...) Expand all
4642 __ vinsw(result, 2, TMP); 4458 __ vinsw(result, 2, TMP);
4643 break; 4459 break;
4644 case MethodRecognizer::kInt32x4WithFlagW: 4460 case MethodRecognizer::kInt32x4WithFlagW:
4645 __ vinsw(result, 3, TMP); 4461 __ vinsw(result, 3, TMP);
4646 break; 4462 break;
4647 default: 4463 default:
4648 UNREACHABLE(); 4464 UNREACHABLE();
4649 } 4465 }
4650 } 4466 }
4651 4467
4652
4653 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, 4468 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone,
4654 bool opt) const { 4469 bool opt) const {
4655 const intptr_t kNumInputs = 1; 4470 const intptr_t kNumInputs = 1;
4656 const intptr_t kNumTemps = 0; 4471 const intptr_t kNumTemps = 0;
4657 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 4472 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
4658 LocationSummary::kNoCall); 4473 LocationSummary::kNoCall);
4659 summary->set_in(0, Location::RequiresFpuRegister()); 4474 summary->set_in(0, Location::RequiresFpuRegister());
4660 summary->set_out(0, Location::RequiresFpuRegister()); 4475 summary->set_out(0, Location::RequiresFpuRegister());
4661 return summary; 4476 return summary;
4662 } 4477 }
4663 4478
4664
4665 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 4479 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
4666 const VRegister value = locs()->in(0).fpu_reg(); 4480 const VRegister value = locs()->in(0).fpu_reg();
4667 const VRegister result = locs()->out(0).fpu_reg(); 4481 const VRegister result = locs()->out(0).fpu_reg();
4668 4482
4669 if (value != result) { 4483 if (value != result) {
4670 __ vmov(result, value); 4484 __ vmov(result, value);
4671 } 4485 }
4672 } 4486 }
4673 4487
4674
4675 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, 4488 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone,
4676 bool opt) const { 4489 bool opt) const {
4677 const intptr_t kNumInputs = 2; 4490 const intptr_t kNumInputs = 2;
4678 const intptr_t kNumTemps = 0; 4491 const intptr_t kNumTemps = 0;
4679 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, 4492 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps,
4680 LocationSummary::kNoCall); 4493 LocationSummary::kNoCall);
4681 summary->set_in(0, Location::RequiresFpuRegister()); 4494 summary->set_in(0, Location::RequiresFpuRegister());
4682 summary->set_in(1, Location::RequiresFpuRegister()); 4495 summary->set_in(1, Location::RequiresFpuRegister());
4683 summary->set_out(0, Location::RequiresFpuRegister()); 4496 summary->set_out(0, Location::RequiresFpuRegister());
4684 return summary; 4497 return summary;
4685 } 4498 }
4686 4499
4687
4688 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4500 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4689 const VRegister left = locs()->in(0).fpu_reg(); 4501 const VRegister left = locs()->in(0).fpu_reg();
4690 const VRegister right = locs()->in(1).fpu_reg(); 4502 const VRegister right = locs()->in(1).fpu_reg();
4691 const VRegister result = locs()->out(0).fpu_reg(); 4503 const VRegister result = locs()->out(0).fpu_reg();
4692 switch (op_kind()) { 4504 switch (op_kind()) {
4693 case Token::kBIT_AND: 4505 case Token::kBIT_AND:
4694 __ vand(result, left, right); 4506 __ vand(result, left, right);
4695 break; 4507 break;
4696 case Token::kBIT_OR: 4508 case Token::kBIT_OR:
4697 __ vorr(result, left, right); 4509 __ vorr(result, left, right);
4698 break; 4510 break;
4699 case Token::kBIT_XOR: 4511 case Token::kBIT_XOR:
4700 __ veor(result, left, right); 4512 __ veor(result, left, right);
4701 break; 4513 break;
4702 case Token::kADD: 4514 case Token::kADD:
4703 __ vaddw(result, left, right); 4515 __ vaddw(result, left, right);
4704 break; 4516 break;
4705 case Token::kSUB: 4517 case Token::kSUB:
4706 __ vsubw(result, left, right); 4518 __ vsubw(result, left, right);
4707 break; 4519 break;
4708 default: 4520 default:
4709 UNREACHABLE(); 4521 UNREACHABLE();
4710 } 4522 }
4711 } 4523 }
4712 4524
4713
4714 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, 4525 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone,
4715 bool opt) const { 4526 bool opt) const {
4716 ASSERT((kind() == MathUnaryInstr::kSqrt) || 4527 ASSERT((kind() == MathUnaryInstr::kSqrt) ||
4717 (kind() == MathUnaryInstr::kDoubleSquare)); 4528 (kind() == MathUnaryInstr::kDoubleSquare));
4718 const intptr_t kNumInputs = 1; 4529 const intptr_t kNumInputs = 1;
4719 const intptr_t kNumTemps = 0; 4530 const intptr_t kNumTemps = 0;
4720 LocationSummary* summary = new (zone) 4531 LocationSummary* summary = new (zone)
4721 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4532 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4722 summary->set_in(0, Location::RequiresFpuRegister()); 4533 summary->set_in(0, Location::RequiresFpuRegister());
4723 summary->set_out(0, Location::RequiresFpuRegister()); 4534 summary->set_out(0, Location::RequiresFpuRegister());
4724 return summary; 4535 return summary;
4725 } 4536 }
4726 4537
4727
4728 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4538 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4729 if (kind() == MathUnaryInstr::kSqrt) { 4539 if (kind() == MathUnaryInstr::kSqrt) {
4730 const VRegister val = locs()->in(0).fpu_reg(); 4540 const VRegister val = locs()->in(0).fpu_reg();
4731 const VRegister result = locs()->out(0).fpu_reg(); 4541 const VRegister result = locs()->out(0).fpu_reg();
4732 __ fsqrtd(result, val); 4542 __ fsqrtd(result, val);
4733 } else if (kind() == MathUnaryInstr::kDoubleSquare) { 4543 } else if (kind() == MathUnaryInstr::kDoubleSquare) {
4734 const VRegister val = locs()->in(0).fpu_reg(); 4544 const VRegister val = locs()->in(0).fpu_reg();
4735 const VRegister result = locs()->out(0).fpu_reg(); 4545 const VRegister result = locs()->out(0).fpu_reg();
4736 __ fmuld(result, val, val); 4546 __ fmuld(result, val, val);
4737 } else { 4547 } else {
4738 UNREACHABLE(); 4548 UNREACHABLE();
4739 } 4549 }
4740 } 4550 }
4741 4551
4742
4743 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( 4552 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary(
4744 Zone* zone, 4553 Zone* zone,
4745 bool opt) const { 4554 bool opt) const {
4746 const intptr_t kNumTemps = 0; 4555 const intptr_t kNumTemps = 0;
4747 LocationSummary* summary = new (zone) 4556 LocationSummary* summary = new (zone)
4748 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); 4557 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall);
4749 summary->set_in(0, Location::RegisterLocation(R0)); 4558 summary->set_in(0, Location::RegisterLocation(R0));
4750 summary->set_in(1, Location::RegisterLocation(R1)); 4559 summary->set_in(1, Location::RegisterLocation(R1));
4751 summary->set_in(2, Location::RegisterLocation(R2)); 4560 summary->set_in(2, Location::RegisterLocation(R2));
4752 summary->set_in(3, Location::RegisterLocation(R3)); 4561 summary->set_in(3, Location::RegisterLocation(R3));
4753 summary->set_out(0, Location::RegisterLocation(R0)); 4562 summary->set_out(0, Location::RegisterLocation(R0));
4754 return summary; 4563 return summary;
4755 } 4564 }
4756 4565
4757
4758 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( 4566 void CaseInsensitiveCompareUC16Instr::EmitNativeCode(
4759 FlowGraphCompiler* compiler) { 4567 FlowGraphCompiler* compiler) {
4760 // Call the function. 4568 // Call the function.
4761 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); 4569 __ CallRuntime(TargetFunction(), TargetFunction().argument_count());
4762 } 4570 }
4763 4571
4764
4765 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, 4572 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone,
4766 bool opt) const { 4573 bool opt) const {
4767 if (result_cid() == kDoubleCid) { 4574 if (result_cid() == kDoubleCid) {
4768 const intptr_t kNumInputs = 2; 4575 const intptr_t kNumInputs = 2;
4769 const intptr_t kNumTemps = 0; 4576 const intptr_t kNumTemps = 0;
4770 LocationSummary* summary = new (zone) 4577 LocationSummary* summary = new (zone)
4771 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4578 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4772 summary->set_in(0, Location::RequiresFpuRegister()); 4579 summary->set_in(0, Location::RequiresFpuRegister());
4773 summary->set_in(1, Location::RequiresFpuRegister()); 4580 summary->set_in(1, Location::RequiresFpuRegister());
4774 // Reuse the left register so that code can be made shorter. 4581 // Reuse the left register so that code can be made shorter.
4775 summary->set_out(0, Location::SameAsFirstInput()); 4582 summary->set_out(0, Location::SameAsFirstInput());
4776 return summary; 4583 return summary;
4777 } 4584 }
4778 ASSERT(result_cid() == kSmiCid); 4585 ASSERT(result_cid() == kSmiCid);
4779 const intptr_t kNumInputs = 2; 4586 const intptr_t kNumInputs = 2;
4780 const intptr_t kNumTemps = 0; 4587 const intptr_t kNumTemps = 0;
4781 LocationSummary* summary = new (zone) 4588 LocationSummary* summary = new (zone)
4782 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4589 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4783 summary->set_in(0, Location::RequiresRegister()); 4590 summary->set_in(0, Location::RequiresRegister());
4784 summary->set_in(1, Location::RequiresRegister()); 4591 summary->set_in(1, Location::RequiresRegister());
4785 // Reuse the left register so that code can be made shorter. 4592 // Reuse the left register so that code can be made shorter.
4786 summary->set_out(0, Location::SameAsFirstInput()); 4593 summary->set_out(0, Location::SameAsFirstInput());
4787 return summary; 4594 return summary;
4788 } 4595 }
4789 4596
4790
4791 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4597 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4792 ASSERT((op_kind() == MethodRecognizer::kMathMin) || 4598 ASSERT((op_kind() == MethodRecognizer::kMathMin) ||
4793 (op_kind() == MethodRecognizer::kMathMax)); 4599 (op_kind() == MethodRecognizer::kMathMax));
4794 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); 4600 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin);
4795 if (result_cid() == kDoubleCid) { 4601 if (result_cid() == kDoubleCid) {
4796 Label done, returns_nan, are_equal; 4602 Label done, returns_nan, are_equal;
4797 const VRegister left = locs()->in(0).fpu_reg(); 4603 const VRegister left = locs()->in(0).fpu_reg();
4798 const VRegister right = locs()->in(1).fpu_reg(); 4604 const VRegister right = locs()->in(1).fpu_reg();
4799 const VRegister result = locs()->out(0).fpu_reg(); 4605 const VRegister result = locs()->out(0).fpu_reg();
4800 __ fcmpd(left, right); 4606 __ fcmpd(left, right);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
4840 const Register result = locs()->out(0).reg(); 4646 const Register result = locs()->out(0).reg();
4841 __ CompareRegisters(left, right); 4647 __ CompareRegisters(left, right);
4842 ASSERT(result == left); 4648 ASSERT(result == left);
4843 if (is_min) { 4649 if (is_min) {
4844 __ csel(result, right, left, GT); 4650 __ csel(result, right, left, GT);
4845 } else { 4651 } else {
4846 __ csel(result, right, left, LT); 4652 __ csel(result, right, left, LT);
4847 } 4653 }
4848 } 4654 }
4849 4655
4850
4851 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, 4656 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone,
4852 bool opt) const { 4657 bool opt) const {
4853 const intptr_t kNumInputs = 1; 4658 const intptr_t kNumInputs = 1;
4854 const intptr_t kNumTemps = 0; 4659 const intptr_t kNumTemps = 0;
4855 LocationSummary* summary = new (zone) 4660 LocationSummary* summary = new (zone)
4856 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4661 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4857 summary->set_in(0, Location::RequiresRegister()); 4662 summary->set_in(0, Location::RequiresRegister());
4858 // We make use of 3-operand instructions by not requiring result register 4663 // We make use of 3-operand instructions by not requiring result register
4859 // to be identical to first input register as on Intel. 4664 // to be identical to first input register as on Intel.
4860 summary->set_out(0, Location::RequiresRegister()); 4665 summary->set_out(0, Location::RequiresRegister());
4861 return summary; 4666 return summary;
4862 } 4667 }
4863 4668
4864
4865 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4669 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4866 const Register value = locs()->in(0).reg(); 4670 const Register value = locs()->in(0).reg();
4867 const Register result = locs()->out(0).reg(); 4671 const Register result = locs()->out(0).reg();
4868 switch (op_kind()) { 4672 switch (op_kind()) {
4869 case Token::kNEGATE: { 4673 case Token::kNEGATE: {
4870 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); 4674 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
4871 __ subs(result, ZR, Operand(value)); 4675 __ subs(result, ZR, Operand(value));
4872 __ b(deopt, VS); 4676 __ b(deopt, VS);
4873 break; 4677 break;
4874 } 4678 }
4875 case Token::kBIT_NOT: 4679 case Token::kBIT_NOT:
4876 __ mvn(result, value); 4680 __ mvn(result, value);
4877 // Remove inverted smi-tag. 4681 // Remove inverted smi-tag.
4878 __ andi(result, result, Immediate(~kSmiTagMask)); 4682 __ andi(result, result, Immediate(~kSmiTagMask));
4879 break; 4683 break;
4880 default: 4684 default:
4881 UNREACHABLE(); 4685 UNREACHABLE();
4882 } 4686 }
4883 } 4687 }
4884 4688
4885
4886 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, 4689 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone,
4887 bool opt) const { 4690 bool opt) const {
4888 const intptr_t kNumInputs = 1; 4691 const intptr_t kNumInputs = 1;
4889 const intptr_t kNumTemps = 0; 4692 const intptr_t kNumTemps = 0;
4890 LocationSummary* summary = new (zone) 4693 LocationSummary* summary = new (zone)
4891 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4694 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4892 summary->set_in(0, Location::RequiresFpuRegister()); 4695 summary->set_in(0, Location::RequiresFpuRegister());
4893 summary->set_out(0, Location::RequiresFpuRegister()); 4696 summary->set_out(0, Location::RequiresFpuRegister());
4894 return summary; 4697 return summary;
4895 } 4698 }
4896 4699
4897
4898 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4700 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4899 const VRegister result = locs()->out(0).fpu_reg(); 4701 const VRegister result = locs()->out(0).fpu_reg();
4900 const VRegister value = locs()->in(0).fpu_reg(); 4702 const VRegister value = locs()->in(0).fpu_reg();
4901 __ fnegd(result, value); 4703 __ fnegd(result, value);
4902 } 4704 }
4903 4705
4904
4905 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, 4706 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone,
4906 bool opt) const { 4707 bool opt) const {
4907 const intptr_t kNumInputs = 1; 4708 const intptr_t kNumInputs = 1;
4908 const intptr_t kNumTemps = 0; 4709 const intptr_t kNumTemps = 0;
4909 LocationSummary* result = new (zone) 4710 LocationSummary* result = new (zone)
4910 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4711 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4911 result->set_in(0, Location::RequiresRegister()); 4712 result->set_in(0, Location::RequiresRegister());
4912 result->set_out(0, Location::RequiresFpuRegister()); 4713 result->set_out(0, Location::RequiresFpuRegister());
4913 return result; 4714 return result;
4914 } 4715 }
4915 4716
4916
4917 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4717 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4918 const Register value = locs()->in(0).reg(); 4718 const Register value = locs()->in(0).reg();
4919 const VRegister result = locs()->out(0).fpu_reg(); 4719 const VRegister result = locs()->out(0).fpu_reg();
4920 __ scvtfdw(result, value); 4720 __ scvtfdw(result, value);
4921 } 4721 }
4922 4722
4923
4924 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, 4723 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone,
4925 bool opt) const { 4724 bool opt) const {
4926 const intptr_t kNumInputs = 1; 4725 const intptr_t kNumInputs = 1;
4927 const intptr_t kNumTemps = 0; 4726 const intptr_t kNumTemps = 0;
4928 LocationSummary* result = new (zone) 4727 LocationSummary* result = new (zone)
4929 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4728 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4930 result->set_in(0, Location::RequiresRegister()); 4729 result->set_in(0, Location::RequiresRegister());
4931 result->set_out(0, Location::RequiresFpuRegister()); 4730 result->set_out(0, Location::RequiresFpuRegister());
4932 return result; 4731 return result;
4933 } 4732 }
4934 4733
4935
4936 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4734 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4937 const Register value = locs()->in(0).reg(); 4735 const Register value = locs()->in(0).reg();
4938 const VRegister result = locs()->out(0).fpu_reg(); 4736 const VRegister result = locs()->out(0).fpu_reg();
4939 __ SmiUntag(TMP, value); 4737 __ SmiUntag(TMP, value);
4940 __ scvtfdx(result, TMP); 4738 __ scvtfdx(result, TMP);
4941 } 4739 }
4942 4740
4943
4944 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone, 4741 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone,
4945 bool opt) const { 4742 bool opt) const {
4946 UNIMPLEMENTED(); 4743 UNIMPLEMENTED();
4947 return NULL; 4744 return NULL;
4948 } 4745 }
4949 4746
4950
4951 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4747 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4952 UNIMPLEMENTED(); 4748 UNIMPLEMENTED();
4953 } 4749 }
4954 4750
4955
4956 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, 4751 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone,
4957 bool opt) const { 4752 bool opt) const {
4958 const intptr_t kNumInputs = 1; 4753 const intptr_t kNumInputs = 1;
4959 const intptr_t kNumTemps = 0; 4754 const intptr_t kNumTemps = 0;
4960 LocationSummary* result = new (zone) 4755 LocationSummary* result = new (zone)
4961 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); 4756 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
4962 result->set_in(0, Location::RegisterLocation(R1)); 4757 result->set_in(0, Location::RegisterLocation(R1));
4963 result->set_out(0, Location::RegisterLocation(R0)); 4758 result->set_out(0, Location::RegisterLocation(R0));
4964 return result; 4759 return result;
4965 } 4760 }
4966 4761
4967
4968 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4762 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4969 const Register result = locs()->out(0).reg(); 4763 const Register result = locs()->out(0).reg();
4970 const Register value_obj = locs()->in(0).reg(); 4764 const Register value_obj = locs()->in(0).reg();
4971 ASSERT(result == R0); 4765 ASSERT(result == R0);
4972 ASSERT(result != value_obj); 4766 ASSERT(result != value_obj);
4973 __ LoadDFieldFromOffset(VTMP, value_obj, Double::value_offset()); 4767 __ LoadDFieldFromOffset(VTMP, value_obj, Double::value_offset());
4974 4768
4975 Label do_call, done; 4769 Label do_call, done;
4976 // First check for NaN. Checking for minint after the conversion doesn't work 4770 // First check for NaN. Checking for minint after the conversion doesn't work
4977 // on ARM64 because fcvtzds gives 0 for NaN. 4771 // on ARM64 because fcvtzds gives 0 for NaN.
(...skipping 16 matching lines...) Expand all
4994 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); 4788 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
4995 const int kTypeArgsLen = 0; 4789 const int kTypeArgsLen = 0;
4996 const int kNumberOfArguments = 1; 4790 const int kNumberOfArguments = 1;
4997 const Array& kNoArgumentNames = Object::null_array(); 4791 const Array& kNoArgumentNames = Object::null_array();
4998 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); 4792 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
4999 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, 4793 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
5000 args_info, locs(), ICData::Handle()); 4794 args_info, locs(), ICData::Handle());
5001 __ Bind(&done); 4795 __ Bind(&done);
5002 } 4796 }
5003 4797
5004
5005 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, 4798 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone,
5006 bool opt) const { 4799 bool opt) const {
5007 const intptr_t kNumInputs = 1; 4800 const intptr_t kNumInputs = 1;
5008 const intptr_t kNumTemps = 0; 4801 const intptr_t kNumTemps = 0;
5009 LocationSummary* result = new (zone) 4802 LocationSummary* result = new (zone)
5010 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4803 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5011 result->set_in(0, Location::RequiresFpuRegister()); 4804 result->set_in(0, Location::RequiresFpuRegister());
5012 result->set_out(0, Location::RequiresRegister()); 4805 result->set_out(0, Location::RequiresRegister());
5013 return result; 4806 return result;
5014 } 4807 }
5015 4808
5016
5017 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4809 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5018 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); 4810 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi);
5019 const Register result = locs()->out(0).reg(); 4811 const Register result = locs()->out(0).reg();
5020 const VRegister value = locs()->in(0).fpu_reg(); 4812 const VRegister value = locs()->in(0).fpu_reg();
5021 // First check for NaN. Checking for minint after the conversion doesn't work 4813 // First check for NaN. Checking for minint after the conversion doesn't work
5022 // on ARM64 because fcvtzds gives 0 for NaN. 4814 // on ARM64 because fcvtzds gives 0 for NaN.
5023 // TODO(zra): Check spec that this is true. 4815 // TODO(zra): Check spec that this is true.
5024 __ fcmpd(value, value); 4816 __ fcmpd(value, value);
5025 __ b(deopt, VS); 4817 __ b(deopt, VS);
5026 4818
5027 __ fcvtzds(result, value); 4819 __ fcvtzds(result, value);
5028 // Check for overflow and that it fits into Smi. 4820 // Check for overflow and that it fits into Smi.
5029 __ CompareImmediate(result, 0xC000000000000000); 4821 __ CompareImmediate(result, 0xC000000000000000);
5030 __ b(deopt, MI); 4822 __ b(deopt, MI);
5031 __ SmiTag(result); 4823 __ SmiTag(result);
5032 } 4824 }
5033 4825
5034
5035 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, 4826 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
5036 bool opt) const { 4827 bool opt) const {
5037 UNIMPLEMENTED(); 4828 UNIMPLEMENTED();
5038 return NULL; 4829 return NULL;
5039 } 4830 }
5040 4831
5041
5042 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4832 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5043 UNIMPLEMENTED(); 4833 UNIMPLEMENTED();
5044 } 4834 }
5045 4835
5046
5047 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, 4836 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone,
5048 bool opt) const { 4837 bool opt) const {
5049 const intptr_t kNumInputs = 1; 4838 const intptr_t kNumInputs = 1;
5050 const intptr_t kNumTemps = 0; 4839 const intptr_t kNumTemps = 0;
5051 LocationSummary* result = new (zone) 4840 LocationSummary* result = new (zone)
5052 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4841 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5053 result->set_in(0, Location::RequiresFpuRegister()); 4842 result->set_in(0, Location::RequiresFpuRegister());
5054 result->set_out(0, Location::RequiresFpuRegister()); 4843 result->set_out(0, Location::RequiresFpuRegister());
5055 return result; 4844 return result;
5056 } 4845 }
5057 4846
5058
5059 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4847 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5060 const VRegister value = locs()->in(0).fpu_reg(); 4848 const VRegister value = locs()->in(0).fpu_reg();
5061 const VRegister result = locs()->out(0).fpu_reg(); 4849 const VRegister result = locs()->out(0).fpu_reg();
5062 __ fcvtsd(result, value); 4850 __ fcvtsd(result, value);
5063 } 4851 }
5064 4852
5065
5066 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, 4853 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone,
5067 bool opt) const { 4854 bool opt) const {
5068 const intptr_t kNumInputs = 1; 4855 const intptr_t kNumInputs = 1;
5069 const intptr_t kNumTemps = 0; 4856 const intptr_t kNumTemps = 0;
5070 LocationSummary* result = new (zone) 4857 LocationSummary* result = new (zone)
5071 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4858 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5072 result->set_in(0, Location::RequiresFpuRegister()); 4859 result->set_in(0, Location::RequiresFpuRegister());
5073 result->set_out(0, Location::RequiresFpuRegister()); 4860 result->set_out(0, Location::RequiresFpuRegister());
5074 return result; 4861 return result;
5075 } 4862 }
5076 4863
5077
5078 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4864 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5079 const VRegister value = locs()->in(0).fpu_reg(); 4865 const VRegister value = locs()->in(0).fpu_reg();
5080 const VRegister result = locs()->out(0).fpu_reg(); 4866 const VRegister result = locs()->out(0).fpu_reg();
5081 __ fcvtds(result, value); 4867 __ fcvtds(result, value);
5082 } 4868 }
5083 4869
5084
5085 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, 4870 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone,
5086 bool opt) const { 4871 bool opt) const {
5087 ASSERT((InputCount() == 1) || (InputCount() == 2)); 4872 ASSERT((InputCount() == 1) || (InputCount() == 2));
5088 const intptr_t kNumTemps = 4873 const intptr_t kNumTemps =
5089 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0; 4874 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0;
5090 LocationSummary* result = new (zone) 4875 LocationSummary* result = new (zone)
5091 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); 4876 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall);
5092 result->set_in(0, Location::FpuRegisterLocation(V0)); 4877 result->set_in(0, Location::FpuRegisterLocation(V0));
5093 if (InputCount() == 2) { 4878 if (InputCount() == 2) {
5094 result->set_in(1, Location::FpuRegisterLocation(V1)); 4879 result->set_in(1, Location::FpuRegisterLocation(V1));
5095 } 4880 }
5096 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { 4881 if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
5097 result->set_temp(0, Location::FpuRegisterLocation(V30)); 4882 result->set_temp(0, Location::FpuRegisterLocation(V30));
5098 } 4883 }
5099 result->set_out(0, Location::FpuRegisterLocation(V0)); 4884 result->set_out(0, Location::FpuRegisterLocation(V0));
5100 return result; 4885 return result;
5101 } 4886 }
5102 4887
5103
5104 // Pseudo code: 4888 // Pseudo code:
5105 // if (exponent == 0.0) return 1.0; 4889 // if (exponent == 0.0) return 1.0;
5106 // // Speed up simple cases. 4890 // // Speed up simple cases.
5107 // if (exponent == 1.0) return base; 4891 // if (exponent == 1.0) return base;
5108 // if (exponent == 2.0) return base * base; 4892 // if (exponent == 2.0) return base * base;
5109 // if (exponent == 3.0) return base * base * base; 4893 // if (exponent == 3.0) return base * base * base;
5110 // if (base == 1.0) return 1.0; 4894 // if (base == 1.0) return 1.0;
5111 // if (base.isNaN || exponent.isNaN) { 4895 // if (base.isNaN || exponent.isNaN) {
5112 // return double.NAN; 4896 // return double.NAN;
5113 // } 4897 // }
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
5206 __ LoadDImmediate(result, 0.0); 4990 __ LoadDImmediate(result, 0.0);
5207 __ b(&skip_call); 4991 __ b(&skip_call);
5208 4992
5209 __ Bind(&do_pow); 4993 __ Bind(&do_pow);
5210 __ fmovdd(base, saved_base); // Restore base. 4994 __ fmovdd(base, saved_base); // Restore base.
5211 4995
5212 __ CallRuntime(instr->TargetFunction(), kInputCount); 4996 __ CallRuntime(instr->TargetFunction(), kInputCount);
5213 __ Bind(&skip_call); 4997 __ Bind(&skip_call);
5214 } 4998 }
5215 4999
5216
5217 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5000 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5218 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { 5001 if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
5219 InvokeDoublePow(compiler, this); 5002 InvokeDoublePow(compiler, this);
5220 return; 5003 return;
5221 } 5004 }
5222 __ CallRuntime(TargetFunction(), InputCount()); 5005 __ CallRuntime(TargetFunction(), InputCount());
5223 } 5006 }
5224 5007
5225
5226 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, 5008 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone,
5227 bool opt) const { 5009 bool opt) const {
5228 // Only use this instruction in optimized code. 5010 // Only use this instruction in optimized code.
5229 ASSERT(opt); 5011 ASSERT(opt);
5230 const intptr_t kNumInputs = 1; 5012 const intptr_t kNumInputs = 1;
5231 LocationSummary* summary = 5013 LocationSummary* summary =
5232 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); 5014 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall);
5233 if (representation() == kUnboxedDouble) { 5015 if (representation() == kUnboxedDouble) {
5234 if (index() == 0) { 5016 if (index() == 0) {
5235 summary->set_in( 5017 summary->set_in(
(...skipping 12 matching lines...) Expand all
5248 } else { 5030 } else {
5249 ASSERT(index() == 1); 5031 ASSERT(index() == 1);
5250 summary->set_in( 5032 summary->set_in(
5251 0, Location::Pair(Location::Any(), Location::RequiresRegister())); 5033 0, Location::Pair(Location::Any(), Location::RequiresRegister()));
5252 } 5034 }
5253 summary->set_out(0, Location::RequiresRegister()); 5035 summary->set_out(0, Location::RequiresRegister());
5254 } 5036 }
5255 return summary; 5037 return summary;
5256 } 5038 }
5257 5039
5258
5259 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5040 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5260 ASSERT(locs()->in(0).IsPairLocation()); 5041 ASSERT(locs()->in(0).IsPairLocation());
5261 PairLocation* pair = locs()->in(0).AsPairLocation(); 5042 PairLocation* pair = locs()->in(0).AsPairLocation();
5262 Location in_loc = pair->At(index()); 5043 Location in_loc = pair->At(index());
5263 if (representation() == kUnboxedDouble) { 5044 if (representation() == kUnboxedDouble) {
5264 const VRegister out = locs()->out(0).fpu_reg(); 5045 const VRegister out = locs()->out(0).fpu_reg();
5265 const VRegister in = in_loc.fpu_reg(); 5046 const VRegister in = in_loc.fpu_reg();
5266 __ fmovdd(out, in); 5047 __ fmovdd(out, in);
5267 } else { 5048 } else {
5268 ASSERT(representation() == kTagged); 5049 ASSERT(representation() == kTagged);
5269 const Register out = locs()->out(0).reg(); 5050 const Register out = locs()->out(0).reg();
5270 const Register in = in_loc.reg(); 5051 const Register in = in_loc.reg();
5271 __ mov(out, in); 5052 __ mov(out, in);
5272 } 5053 }
5273 } 5054 }
5274 5055
5275
5276 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone, 5056 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
5277 bool opt) const { 5057 bool opt) const {
5278 const intptr_t kNumInputs = 2; 5058 const intptr_t kNumInputs = 2;
5279 const intptr_t kNumTemps = 0; 5059 const intptr_t kNumTemps = 0;
5280 LocationSummary* summary = new (zone) 5060 LocationSummary* summary = new (zone)
5281 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5061 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5282 summary->set_in(0, Location::RequiresRegister()); 5062 summary->set_in(0, Location::RequiresRegister());
5283 summary->set_in(1, Location::RequiresRegister()); 5063 summary->set_in(1, Location::RequiresRegister());
5284 // Output is a pair of registers. 5064 // Output is a pair of registers.
5285 summary->set_out(0, Location::Pair(Location::RequiresRegister(), 5065 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5286 Location::RequiresRegister())); 5066 Location::RequiresRegister()));
5287 return summary; 5067 return summary;
5288 } 5068 }
5289 5069
5290
5291 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5070 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5292 ASSERT(CanDeoptimize()); 5071 ASSERT(CanDeoptimize());
5293 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); 5072 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
5294 const Register left = locs()->in(0).reg(); 5073 const Register left = locs()->in(0).reg();
5295 const Register right = locs()->in(1).reg(); 5074 const Register right = locs()->in(1).reg();
5296 ASSERT(locs()->out(0).IsPairLocation()); 5075 ASSERT(locs()->out(0).IsPairLocation());
5297 const PairLocation* pair = locs()->out(0).AsPairLocation(); 5076 const PairLocation* pair = locs()->out(0).AsPairLocation();
5298 const Register result_div = pair->At(0).reg(); 5077 const Register result_div = pair->At(0).reg();
5299 const Register result_mod = pair->At(1).reg(); 5078 const Register result_mod = pair->At(1).reg();
5300 if (RangeUtils::CanBeZero(divisor_range())) { 5079 if (RangeUtils::CanBeZero(divisor_range())) {
(...skipping 28 matching lines...) Expand all
5329 __ CompareRegisters(result_mod, ZR); 5108 __ CompareRegisters(result_mod, ZR);
5330 __ b(&done, GE); 5109 __ b(&done, GE);
5331 // Result is negative, adjust it. 5110 // Result is negative, adjust it.
5332 __ CompareRegisters(right, ZR); 5111 __ CompareRegisters(right, ZR);
5333 __ sub(TMP2, result_mod, Operand(right)); 5112 __ sub(TMP2, result_mod, Operand(right));
5334 __ add(TMP, result_mod, Operand(right)); 5113 __ add(TMP, result_mod, Operand(right));
5335 __ csel(result_mod, TMP, TMP2, GE); 5114 __ csel(result_mod, TMP, TMP2, GE);
5336 __ Bind(&done); 5115 __ Bind(&done);
5337 } 5116 }
5338 5117
5339
5340 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( 5118 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
5341 Zone* zone, 5119 Zone* zone,
5342 bool opt) const { 5120 bool opt) const {
5343 return MakeCallSummary(zone); 5121 return MakeCallSummary(zone);
5344 } 5122 }
5345 5123
5346
5347 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { 5124 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const {
5348 comparison()->InitializeLocationSummary(zone, opt); 5125 comparison()->InitializeLocationSummary(zone, opt);
5349 // Branches don't produce a result. 5126 // Branches don't produce a result.
5350 comparison()->locs()->set_out(0, Location::NoLocation()); 5127 comparison()->locs()->set_out(0, Location::NoLocation());
5351 return comparison()->locs(); 5128 return comparison()->locs();
5352 } 5129 }
5353 5130
5354
5355 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5131 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5356 comparison()->EmitBranchCode(compiler, this); 5132 comparison()->EmitBranchCode(compiler, this);
5357 } 5133 }
5358 5134
5359
5360 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, 5135 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone,
5361 bool opt) const { 5136 bool opt) const {
5362 const intptr_t kNumInputs = 1; 5137 const intptr_t kNumInputs = 1;
5363 const bool need_mask_temp = IsBitTest(); 5138 const bool need_mask_temp = IsBitTest();
5364 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; 5139 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0;
5365 LocationSummary* summary = new (zone) 5140 LocationSummary* summary = new (zone)
5366 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5141 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5367 summary->set_in(0, Location::RequiresRegister()); 5142 summary->set_in(0, Location::RequiresRegister());
5368 if (!IsNullCheck()) { 5143 if (!IsNullCheck()) {
5369 summary->set_temp(0, Location::RequiresRegister()); 5144 summary->set_temp(0, Location::RequiresRegister());
5370 if (need_mask_temp) { 5145 if (need_mask_temp) {
5371 summary->set_temp(1, Location::RequiresRegister()); 5146 summary->set_temp(1, Location::RequiresRegister());
5372 } 5147 }
5373 } 5148 }
5374 return summary; 5149 return summary;
5375 } 5150 }
5376 5151
5377
5378 void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) { 5152 void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) {
5379 __ CompareObject(locs()->in(0).reg(), Object::null_object()); 5153 __ CompareObject(locs()->in(0).reg(), Object::null_object());
5380 ASSERT(IsDeoptIfNull() || IsDeoptIfNotNull()); 5154 ASSERT(IsDeoptIfNull() || IsDeoptIfNotNull());
5381 Condition cond = IsDeoptIfNull() ? EQ : NE; 5155 Condition cond = IsDeoptIfNull() ? EQ : NE;
5382 __ b(deopt, cond); 5156 __ b(deopt, cond);
5383 } 5157 }
5384 5158
5385
5386 void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler, 5159 void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler,
5387 intptr_t min, 5160 intptr_t min,
5388 intptr_t max, 5161 intptr_t max,
5389 intptr_t mask, 5162 intptr_t mask,
5390 Label* deopt) { 5163 Label* deopt) {
5391 Register biased_cid = locs()->temp(0).reg(); 5164 Register biased_cid = locs()->temp(0).reg();
5392 __ AddImmediate(biased_cid, -min); 5165 __ AddImmediate(biased_cid, -min);
5393 __ CompareImmediate(biased_cid, max - min); 5166 __ CompareImmediate(biased_cid, max - min);
5394 __ b(deopt, HI); 5167 __ b(deopt, HI);
5395 5168
5396 Register bit_reg = locs()->temp(1).reg(); 5169 Register bit_reg = locs()->temp(1).reg();
5397 __ LoadImmediate(bit_reg, 1); 5170 __ LoadImmediate(bit_reg, 1);
5398 __ lslv(bit_reg, bit_reg, biased_cid); 5171 __ lslv(bit_reg, bit_reg, biased_cid);
5399 __ TestImmediate(bit_reg, mask); 5172 __ TestImmediate(bit_reg, mask);
5400 __ b(deopt, EQ); 5173 __ b(deopt, EQ);
5401 } 5174 }
5402 5175
5403
5404 int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler, 5176 int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler,
5405 int bias, 5177 int bias,
5406 intptr_t cid_start, 5178 intptr_t cid_start,
5407 intptr_t cid_end, 5179 intptr_t cid_end,
5408 bool is_last, 5180 bool is_last,
5409 Label* is_ok, 5181 Label* is_ok,
5410 Label* deopt, 5182 Label* deopt,
5411 bool use_near_jump) { 5183 bool use_near_jump) {
5412 Register biased_cid = locs()->temp(0).reg(); 5184 Register biased_cid = locs()->temp(0).reg();
5413 Condition no_match, match; 5185 Condition no_match, match;
(...skipping 11 matching lines...) Expand all
5425 match = LS; // Unsigned lower or same. 5197 match = LS; // Unsigned lower or same.
5426 } 5198 }
5427 if (is_last) { 5199 if (is_last) {
5428 __ b(deopt, no_match); 5200 __ b(deopt, no_match);
5429 } else { 5201 } else {
5430 __ b(is_ok, match); 5202 __ b(is_ok, match);
5431 } 5203 }
5432 return bias; 5204 return bias;
5433 } 5205 }
5434 5206
5435
5436 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, 5207 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
5437 bool opt) const { 5208 bool opt) const {
5438 const intptr_t kNumInputs = 1; 5209 const intptr_t kNumInputs = 1;
5439 const intptr_t kNumTemps = 0; 5210 const intptr_t kNumTemps = 0;
5440 LocationSummary* summary = new (zone) 5211 LocationSummary* summary = new (zone)
5441 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5212 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5442 summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister() 5213 summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister()
5443 : Location::WritableRegister()); 5214 : Location::WritableRegister());
5444 return summary; 5215 return summary;
5445 } 5216 }
5446 5217
5447
5448 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5218 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5449 Register value = locs()->in(0).reg(); 5219 Register value = locs()->in(0).reg();
5450 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); 5220 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass);
5451 if (cids_.IsSingleCid()) { 5221 if (cids_.IsSingleCid()) {
5452 __ CompareImmediate(value, Smi::RawValue(cids_.cid_start)); 5222 __ CompareImmediate(value, Smi::RawValue(cids_.cid_start));
5453 __ b(deopt, NE); 5223 __ b(deopt, NE);
5454 } else { 5224 } else {
5455 __ AddImmediate(value, -Smi::RawValue(cids_.cid_start)); 5225 __ AddImmediate(value, -Smi::RawValue(cids_.cid_start));
5456 __ CompareImmediate(value, Smi::RawValue(cids_.cid_end - cids_.cid_start)); 5226 __ CompareImmediate(value, Smi::RawValue(cids_.cid_end - cids_.cid_start));
5457 __ b(deopt, HI); // Unsigned higher. 5227 __ b(deopt, HI); // Unsigned higher.
5458 } 5228 }
5459 } 5229 }
5460 5230
5461
5462 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, 5231 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone,
5463 bool opt) const { 5232 bool opt) const {
5464 const intptr_t kNumInputs = 1; 5233 const intptr_t kNumInputs = 1;
5465 const intptr_t kNumTemps = 0; 5234 const intptr_t kNumTemps = 0;
5466 LocationSummary* summary = new (zone) 5235 LocationSummary* summary = new (zone)
5467 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5236 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5468 summary->set_in(0, Location::RequiresRegister()); 5237 summary->set_in(0, Location::RequiresRegister());
5469 return summary; 5238 return summary;
5470 } 5239 }
5471 5240
5472
5473 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5241 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5474 const Register value = locs()->in(0).reg(); 5242 const Register value = locs()->in(0).reg();
5475 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, 5243 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi,
5476 licm_hoisted_ ? ICData::kHoisted : 0); 5244 licm_hoisted_ ? ICData::kHoisted : 0);
5477 __ BranchIfNotSmi(value, deopt); 5245 __ BranchIfNotSmi(value, deopt);
5478 } 5246 }
5479 5247
5480
5481 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, 5248 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone,
5482 bool opt) const { 5249 bool opt) const {
5483 const intptr_t kNumInputs = 2; 5250 const intptr_t kNumInputs = 2;
5484 const intptr_t kNumTemps = 0; 5251 const intptr_t kNumTemps = 0;
5485 LocationSummary* locs = new (zone) LocationSummary( 5252 LocationSummary* locs = new (zone) LocationSummary(
5486 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); 5253 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
5487 locs->set_in(kLengthPos, Location::RequiresRegister()); 5254 locs->set_in(kLengthPos, Location::RequiresRegister());
5488 locs->set_in(kIndexPos, Location::RequiresRegister()); 5255 locs->set_in(kIndexPos, Location::RequiresRegister());
5489 return locs; 5256 return locs;
5490 } 5257 }
5491 5258
5492
5493 class RangeErrorSlowPath : public SlowPathCode { 5259 class RangeErrorSlowPath : public SlowPathCode {
5494 public: 5260 public:
5495 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) 5261 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index)
5496 : instruction_(instruction), try_index_(try_index) {} 5262 : instruction_(instruction), try_index_(try_index) {}
5497 5263
5498 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 5264 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
5499 if (Assembler::EmittingComments()) { 5265 if (Assembler::EmittingComments()) {
5500 __ Comment("slow path check bound operation"); 5266 __ Comment("slow path check bound operation");
5501 } 5267 }
5502 __ Bind(entry_label()); 5268 __ Bind(entry_label());
5503 LocationSummary* locs = instruction_->locs(); 5269 LocationSummary* locs = instruction_->locs();
5504 compiler->SaveLiveRegisters(locs); 5270 compiler->SaveLiveRegisters(locs);
5505 __ Push(locs->in(0).reg()); 5271 __ Push(locs->in(0).reg());
5506 __ Push(locs->in(1).reg()); 5272 __ Push(locs->in(1).reg());
5507 __ CallRuntime(kRangeErrorRuntimeEntry, 2); 5273 __ CallRuntime(kRangeErrorRuntimeEntry, 2);
5508 compiler->AddDescriptor( 5274 compiler->AddDescriptor(
5509 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), 5275 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(),
5510 instruction_->deopt_id(), instruction_->token_pos(), try_index_); 5276 instruction_->deopt_id(), instruction_->token_pos(), try_index_);
5511 compiler->RecordSafepoint(locs, 2); 5277 compiler->RecordSafepoint(locs, 2);
5512 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); 5278 Environment* env = compiler->SlowPathEnvironmentFor(instruction_);
5513 compiler->EmitCatchEntryState(env, try_index_); 5279 compiler->EmitCatchEntryState(env, try_index_);
5514 __ brk(0); 5280 __ brk(0);
5515 } 5281 }
5516 5282
5517 private: 5283 private:
5518 GenericCheckBoundInstr* instruction_; 5284 GenericCheckBoundInstr* instruction_;
5519 intptr_t try_index_; 5285 intptr_t try_index_;
5520 }; 5286 };
5521 5287
5522
5523 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5288 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5524 RangeErrorSlowPath* slow_path = 5289 RangeErrorSlowPath* slow_path =
5525 new RangeErrorSlowPath(this, compiler->CurrentTryIndex()); 5290 new RangeErrorSlowPath(this, compiler->CurrentTryIndex());
5526 compiler->AddSlowPathCode(slow_path); 5291 compiler->AddSlowPathCode(slow_path);
5527 5292
5528 Location length_loc = locs()->in(kLengthPos); 5293 Location length_loc = locs()->in(kLengthPos);
5529 Location index_loc = locs()->in(kIndexPos); 5294 Location index_loc = locs()->in(kIndexPos);
5530 Register length = length_loc.reg(); 5295 Register length = length_loc.reg();
5531 Register index = index_loc.reg(); 5296 Register index = index_loc.reg();
5532 const intptr_t index_cid = this->index()->Type()->ToCid(); 5297 const intptr_t index_cid = this->index()->Type()->ToCid();
5533 if (index_cid != kSmiCid) { 5298 if (index_cid != kSmiCid) {
5534 __ BranchIfNotSmi(index, slow_path->entry_label()); 5299 __ BranchIfNotSmi(index, slow_path->entry_label());
5535 } 5300 }
5536 __ cmp(index, Operand(length)); 5301 __ cmp(index, Operand(length));
5537 __ b(slow_path->entry_label(), CS); 5302 __ b(slow_path->entry_label(), CS);
5538 } 5303 }
5539 5304
5540
5541 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, 5305 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone,
5542 bool opt) const { 5306 bool opt) const {
5543 const intptr_t kNumInputs = 2; 5307 const intptr_t kNumInputs = 2;
5544 const intptr_t kNumTemps = 0; 5308 const intptr_t kNumTemps = 0;
5545 LocationSummary* locs = new (zone) 5309 LocationSummary* locs = new (zone)
5546 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5310 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5547 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); 5311 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length()));
5548 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); 5312 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index()));
5549 return locs; 5313 return locs;
5550 } 5314 }
5551 5315
5552
5553 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5316 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5554 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; 5317 uint32_t flags = generalized_ ? ICData::kGeneralized : 0;
5555 flags |= licm_hoisted_ ? ICData::kHoisted : 0; 5318 flags |= licm_hoisted_ ? ICData::kHoisted : 0;
5556 Label* deopt = 5319 Label* deopt =
5557 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); 5320 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags);
5558 5321
5559 Location length_loc = locs()->in(kLengthPos); 5322 Location length_loc = locs()->in(kLengthPos);
5560 Location index_loc = locs()->in(kIndexPos); 5323 Location index_loc = locs()->in(kIndexPos);
5561 5324
5562 const intptr_t index_cid = index()->Type()->ToCid(); 5325 const intptr_t index_cid = index()->Type()->ToCid();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
5599 const Register length = length_loc.reg(); 5362 const Register length = length_loc.reg();
5600 const Register index = index_loc.reg(); 5363 const Register index = index_loc.reg();
5601 if (index_cid != kSmiCid) { 5364 if (index_cid != kSmiCid) {
5602 __ BranchIfNotSmi(index, deopt); 5365 __ BranchIfNotSmi(index, deopt);
5603 } 5366 }
5604 __ CompareRegisters(index, length); 5367 __ CompareRegisters(index, length);
5605 __ b(deopt, CS); 5368 __ b(deopt, CS);
5606 } 5369 }
5607 } 5370 }
5608 5371
5609
5610 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, 5372 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone,
5611 bool opt) const { 5373 bool opt) const {
5612 UNIMPLEMENTED(); 5374 UNIMPLEMENTED();
5613 return NULL; 5375 return NULL;
5614 } 5376 }
5615 5377
5616
5617 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5378 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5618 UNIMPLEMENTED(); 5379 UNIMPLEMENTED();
5619 } 5380 }
5620 5381
5621
5622 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, 5382 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone,
5623 bool opt) const { 5383 bool opt) const {
5624 UNIMPLEMENTED(); 5384 UNIMPLEMENTED();
5625 return NULL; 5385 return NULL;
5626 } 5386 }
5627 5387
5628
5629 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5388 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5630 UNIMPLEMENTED(); 5389 UNIMPLEMENTED();
5631 } 5390 }
5632 5391
5633
5634 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, 5392 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone,
5635 bool opt) const { 5393 bool opt) const {
5636 UNIMPLEMENTED(); 5394 UNIMPLEMENTED();
5637 return NULL; 5395 return NULL;
5638 } 5396 }
5639 5397
5640
5641 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5398 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5642 UNIMPLEMENTED(); 5399 UNIMPLEMENTED();
5643 } 5400 }
5644 5401
5645
5646 CompileType BinaryUint32OpInstr::ComputeType() const { 5402 CompileType BinaryUint32OpInstr::ComputeType() const {
5647 return CompileType::FromCid(kSmiCid); 5403 return CompileType::FromCid(kSmiCid);
5648 } 5404 }
5649 5405
5650
5651 CompileType ShiftUint32OpInstr::ComputeType() const { 5406 CompileType ShiftUint32OpInstr::ComputeType() const {
5652 return CompileType::FromCid(kSmiCid); 5407 return CompileType::FromCid(kSmiCid);
5653 } 5408 }
5654 5409
5655
5656 CompileType UnaryUint32OpInstr::ComputeType() const { 5410 CompileType UnaryUint32OpInstr::ComputeType() const {
5657 return CompileType::FromCid(kSmiCid); 5411 return CompileType::FromCid(kSmiCid);
5658 } 5412 }
5659 5413
5660
5661 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) 5414 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr)
5662 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) 5415 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr)
5663 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) 5416 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr)
5664 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) 5417 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr)
5665 5418
5666
5667 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, 5419 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone,
5668 bool opt) const { 5420 bool opt) const {
5669 const intptr_t kNumInputs = 1; 5421 const intptr_t kNumInputs = 1;
5670 const intptr_t kNumTemps = 0; 5422 const intptr_t kNumTemps = 0;
5671 LocationSummary* summary = new (zone) 5423 LocationSummary* summary = new (zone)
5672 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5424 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5673 if (from() == kUnboxedMint) { 5425 if (from() == kUnboxedMint) {
5674 UNREACHABLE(); 5426 UNREACHABLE();
5675 } else if (to() == kUnboxedMint) { 5427 } else if (to() == kUnboxedMint) {
5676 UNREACHABLE(); 5428 UNREACHABLE();
5677 } else { 5429 } else {
5678 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); 5430 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32));
5679 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); 5431 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32));
5680 summary->set_in(0, Location::RequiresRegister()); 5432 summary->set_in(0, Location::RequiresRegister());
5681 summary->set_out(0, Location::RequiresRegister()); 5433 summary->set_out(0, Location::RequiresRegister());
5682 } 5434 }
5683 return summary; 5435 return summary;
5684 } 5436 }
5685 5437
5686
5687 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5438 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5688 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { 5439 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) {
5689 const Register value = locs()->in(0).reg(); 5440 const Register value = locs()->in(0).reg();
5690 const Register out = locs()->out(0).reg(); 5441 const Register out = locs()->out(0).reg();
5691 // Representations are bitwise equivalent but we want to normalize 5442 // Representations are bitwise equivalent but we want to normalize
5692 // upperbits for safety reasons. 5443 // upperbits for safety reasons.
5693 // TODO(vegorov) if we ensure that we never use kDoubleWord size 5444 // TODO(vegorov) if we ensure that we never use kDoubleWord size
5694 // with it then we could avoid this. 5445 // with it then we could avoid this.
5695 // TODO(vegorov) implement and use UBFM for zero extension. 5446 // TODO(vegorov) implement and use UBFM for zero extension.
5696 __ LslImmediate(out, value, 32); 5447 __ LslImmediate(out, value, 32);
(...skipping 16 matching lines...) Expand all
5713 } else if (from() == kUnboxedMint) { 5464 } else if (from() == kUnboxedMint) {
5714 UNREACHABLE(); 5465 UNREACHABLE();
5715 } else if (to() == kUnboxedMint) { 5466 } else if (to() == kUnboxedMint) {
5716 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); 5467 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32));
5717 UNREACHABLE(); 5468 UNREACHABLE();
5718 } else { 5469 } else {
5719 UNREACHABLE(); 5470 UNREACHABLE();
5720 } 5471 }
5721 } 5472 }
5722 5473
5723
5724 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { 5474 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
5725 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); 5475 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall);
5726 } 5476 }
5727 5477
5728
5729 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5478 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5730 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, 5479 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1,
5731 locs()); 5480 locs());
5732 __ brk(0); 5481 __ brk(0);
5733 } 5482 }
5734 5483
5735
5736 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { 5484 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
5737 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); 5485 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall);
5738 } 5486 }
5739 5487
5740
5741 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5488 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5742 compiler->SetNeedsStackTrace(catch_try_index()); 5489 compiler->SetNeedsStackTrace(catch_try_index());
5743 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, 5490 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry,
5744 2, locs()); 5491 2, locs());
5745 __ brk(0); 5492 __ brk(0);
5746 } 5493 }
5747 5494
5748
5749 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { 5495 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const {
5750 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); 5496 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
5751 } 5497 }
5752 5498
5753
5754 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5499 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5755 __ Stop(message()); 5500 __ Stop(message());
5756 } 5501 }
5757 5502
5758
5759 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5503 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5760 if (!compiler->CanFallThroughTo(normal_entry())) { 5504 if (!compiler->CanFallThroughTo(normal_entry())) {
5761 __ b(compiler->GetJumpLabel(normal_entry())); 5505 __ b(compiler->GetJumpLabel(normal_entry()));
5762 } 5506 }
5763 } 5507 }
5764 5508
5765
5766 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { 5509 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const {
5767 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); 5510 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
5768 } 5511 }
5769 5512
5770
5771 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5513 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5772 if (!compiler->is_optimizing()) { 5514 if (!compiler->is_optimizing()) {
5773 if (FLAG_reorder_basic_blocks) { 5515 if (FLAG_reorder_basic_blocks) {
5774 compiler->EmitEdgeCounter(block()->preorder_number()); 5516 compiler->EmitEdgeCounter(block()->preorder_number());
5775 } 5517 }
5776 // Add a deoptimization descriptor for deoptimizing instructions that 5518 // Add a deoptimization descriptor for deoptimizing instructions that
5777 // may be inserted before this instruction. 5519 // may be inserted before this instruction.
5778 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), 5520 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(),
5779 TokenPosition::kNoSource); 5521 TokenPosition::kNoSource);
5780 } 5522 }
5781 if (HasParallelMove()) { 5523 if (HasParallelMove()) {
5782 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); 5524 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
5783 } 5525 }
5784 5526
5785 // We can fall through if the successor is the next block in the list. 5527 // We can fall through if the successor is the next block in the list.
5786 // Otherwise, we need a jump. 5528 // Otherwise, we need a jump.
5787 if (!compiler->CanFallThroughTo(successor())) { 5529 if (!compiler->CanFallThroughTo(successor())) {
5788 __ b(compiler->GetJumpLabel(successor())); 5530 __ b(compiler->GetJumpLabel(successor()));
5789 } 5531 }
5790 } 5532 }
5791 5533
5792
5793 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, 5534 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone,
5794 bool opt) const { 5535 bool opt) const {
5795 const intptr_t kNumInputs = 1; 5536 const intptr_t kNumInputs = 1;
5796 const intptr_t kNumTemps = 1; 5537 const intptr_t kNumTemps = 1;
5797 5538
5798 LocationSummary* summary = new (zone) 5539 LocationSummary* summary = new (zone)
5799 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5540 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5800 5541
5801 summary->set_in(0, Location::RequiresRegister()); 5542 summary->set_in(0, Location::RequiresRegister());
5802 summary->set_temp(0, Location::RequiresRegister()); 5543 summary->set_temp(0, Location::RequiresRegister());
5803 5544
5804 return summary; 5545 return summary;
5805 } 5546 }
5806 5547
5807
5808 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5548 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5809 Register target_address_reg = locs()->temp_slot(0)->reg(); 5549 Register target_address_reg = locs()->temp_slot(0)->reg();
5810 5550
5811 // Load code entry point. 5551 // Load code entry point.
5812 const intptr_t entry_offset = __ CodeSize(); 5552 const intptr_t entry_offset = __ CodeSize();
5813 if (Utils::IsInt(21, -entry_offset)) { 5553 if (Utils::IsInt(21, -entry_offset)) {
5814 __ adr(target_address_reg, Immediate(-entry_offset)); 5554 __ adr(target_address_reg, Immediate(-entry_offset));
5815 } else { 5555 } else {
5816 __ adr(target_address_reg, Immediate(0)); 5556 __ adr(target_address_reg, Immediate(0));
5817 __ AddImmediate(target_address_reg, -entry_offset); 5557 __ AddImmediate(target_address_reg, -entry_offset);
5818 } 5558 }
5819 5559
5820 // Add the offset. 5560 // Add the offset.
5821 Register offset_reg = locs()->in(0).reg(); 5561 Register offset_reg = locs()->in(0).reg();
5822 Operand offset_opr = (offset()->definition()->representation() == kTagged) 5562 Operand offset_opr = (offset()->definition()->representation() == kTagged)
5823 ? Operand(offset_reg, ASR, kSmiTagSize) 5563 ? Operand(offset_reg, ASR, kSmiTagSize)
5824 : Operand(offset_reg); 5564 : Operand(offset_reg);
5825 __ add(target_address_reg, target_address_reg, offset_opr); 5565 __ add(target_address_reg, target_address_reg, offset_opr);
5826 5566
5827 // Jump to the absolute address. 5567 // Jump to the absolute address.
5828 __ br(target_address_reg); 5568 __ br(target_address_reg);
5829 } 5569 }
5830 5570
5831
5832 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, 5571 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone,
5833 bool opt) const { 5572 bool opt) const {
5834 const intptr_t kNumInputs = 2; 5573 const intptr_t kNumInputs = 2;
5835 const intptr_t kNumTemps = 0; 5574 const intptr_t kNumTemps = 0;
5836 if (needs_number_check()) { 5575 if (needs_number_check()) {
5837 LocationSummary* locs = new (zone) 5576 LocationSummary* locs = new (zone)
5838 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); 5577 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
5839 locs->set_in(0, Location::RegisterLocation(R0)); 5578 locs->set_in(0, Location::RegisterLocation(R0));
5840 locs->set_in(1, Location::RegisterLocation(R1)); 5579 locs->set_in(1, Location::RegisterLocation(R1));
5841 locs->set_out(0, Location::RegisterLocation(R0)); 5580 locs->set_out(0, Location::RegisterLocation(R0));
5842 return locs; 5581 return locs;
5843 } 5582 }
5844 LocationSummary* locs = new (zone) 5583 LocationSummary* locs = new (zone)
5845 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5584 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5846 locs->set_in(0, Location::RegisterOrConstant(left())); 5585 locs->set_in(0, Location::RegisterOrConstant(left()));
5847 // Only one of the inputs can be a constant. Choose register if the first one 5586 // Only one of the inputs can be a constant. Choose register if the first one
5848 // is a constant. 5587 // is a constant.
5849 locs->set_in(1, locs->in(0).IsConstant() 5588 locs->set_in(1, locs->in(0).IsConstant()
5850 ? Location::RequiresRegister() 5589 ? Location::RequiresRegister()
5851 : Location::RegisterOrConstant(right())); 5590 : Location::RegisterOrConstant(right()));
5852 locs->set_out(0, Location::RequiresRegister()); 5591 locs->set_out(0, Location::RequiresRegister());
5853 return locs; 5592 return locs;
5854 } 5593 }
5855 5594
5856
5857 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 5595 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
5858 BranchLabels labels) { 5596 BranchLabels labels) {
5859 Location left = locs()->in(0); 5597 Location left = locs()->in(0);
5860 Location right = locs()->in(1); 5598 Location right = locs()->in(1);
5861 ASSERT(!left.IsConstant() || !right.IsConstant()); 5599 ASSERT(!left.IsConstant() || !right.IsConstant());
5862 Condition true_condition; 5600 Condition true_condition;
5863 if (left.IsConstant()) { 5601 if (left.IsConstant()) {
5864 true_condition = compiler->EmitEqualityRegConstCompare( 5602 true_condition = compiler->EmitEqualityRegConstCompare(
5865 right.reg(), left.constant(), needs_number_check(), token_pos(), 5603 right.reg(), left.constant(), needs_number_check(), token_pos(),
5866 deopt_id_); 5604 deopt_id_);
5867 } else if (right.IsConstant()) { 5605 } else if (right.IsConstant()) {
5868 true_condition = compiler->EmitEqualityRegConstCompare( 5606 true_condition = compiler->EmitEqualityRegConstCompare(
5869 left.reg(), right.constant(), needs_number_check(), token_pos(), 5607 left.reg(), right.constant(), needs_number_check(), token_pos(),
5870 deopt_id_); 5608 deopt_id_);
5871 } else { 5609 } else {
5872 true_condition = compiler->EmitEqualityRegRegCompare( 5610 true_condition = compiler->EmitEqualityRegRegCompare(
5873 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); 5611 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_);
5874 } 5612 }
5875 if (kind() != Token::kEQ_STRICT) { 5613 if (kind() != Token::kEQ_STRICT) {
5876 ASSERT(kind() == Token::kNE_STRICT); 5614 ASSERT(kind() == Token::kNE_STRICT);
5877 true_condition = NegateCondition(true_condition); 5615 true_condition = NegateCondition(true_condition);
5878 } 5616 }
5879 return true_condition; 5617 return true_condition;
5880 } 5618 }
5881 5619
5882
5883 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5620 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5884 Label is_true, is_false; 5621 Label is_true, is_false;
5885 BranchLabels labels = {&is_true, &is_false, &is_false}; 5622 BranchLabels labels = {&is_true, &is_false, &is_false};
5886 Condition true_condition = EmitComparisonCode(compiler, labels); 5623 Condition true_condition = EmitComparisonCode(compiler, labels);
5887 const Register result = this->locs()->out(0).reg(); 5624 const Register result = this->locs()->out(0).reg();
5888 5625
5889 // TODO(dartbug.com/29908): Use csel here for better branch prediction? 5626 // TODO(dartbug.com/29908): Use csel here for better branch prediction?
5890 if (true_condition != kInvalidCondition) { 5627 if (true_condition != kInvalidCondition) {
5891 EmitBranchOnCondition(compiler, true_condition, labels); 5628 EmitBranchOnCondition(compiler, true_condition, labels);
5892 } 5629 }
5893 Label done; 5630 Label done;
5894 __ Bind(&is_false); 5631 __ Bind(&is_false);
5895 __ LoadObject(result, Bool::False()); 5632 __ LoadObject(result, Bool::False());
5896 __ b(&done); 5633 __ b(&done);
5897 __ Bind(&is_true); 5634 __ Bind(&is_true);
5898 __ LoadObject(result, Bool::True()); 5635 __ LoadObject(result, Bool::True());
5899 __ Bind(&done); 5636 __ Bind(&done);
5900 } 5637 }
5901 5638
5902
5903 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, 5639 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
5904 BranchInstr* branch) { 5640 BranchInstr* branch) {
5905 BranchLabels labels = compiler->CreateBranchLabels(branch); 5641 BranchLabels labels = compiler->CreateBranchLabels(branch);
5906 Condition true_condition = EmitComparisonCode(compiler, labels); 5642 Condition true_condition = EmitComparisonCode(compiler, labels);
5907 if (true_condition != kInvalidCondition) { 5643 if (true_condition != kInvalidCondition) {
5908 EmitBranchOnCondition(compiler, true_condition, labels); 5644 EmitBranchOnCondition(compiler, true_condition, labels);
5909 } 5645 }
5910 } 5646 }
5911 5647
5912
5913 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, 5648 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone,
5914 bool opt) const { 5649 bool opt) const {
5915 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), 5650 return LocationSummary::Make(zone, 1, Location::RequiresRegister(),
5916 LocationSummary::kNoCall); 5651 LocationSummary::kNoCall);
5917 } 5652 }
5918 5653
5919
5920 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5654 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5921 const Register value = locs()->in(0).reg(); 5655 const Register value = locs()->in(0).reg();
5922 const Register result = locs()->out(0).reg(); 5656 const Register result = locs()->out(0).reg();
5923 5657
5924 __ LoadObject(result, Bool::True()); 5658 __ LoadObject(result, Bool::True());
5925 __ LoadObject(TMP, Bool::False()); 5659 __ LoadObject(TMP, Bool::False());
5926 __ CompareRegisters(result, value); 5660 __ CompareRegisters(result, value);
5927 __ csel(result, TMP, result, EQ); 5661 __ csel(result, TMP, result, EQ);
5928 } 5662 }
5929 5663
5930
5931 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, 5664 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
5932 bool opt) const { 5665 bool opt) const {
5933 return MakeCallSummary(zone); 5666 return MakeCallSummary(zone);
5934 } 5667 }
5935 5668
5936
5937 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5669 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5938 const Code& stub = Code::ZoneHandle( 5670 const Code& stub = Code::ZoneHandle(
5939 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); 5671 compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
5940 const StubEntry stub_entry(stub); 5672 const StubEntry stub_entry(stub);
5941 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, 5673 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther,
5942 locs()); 5674 locs());
5943 compiler->AddStubCallTarget(stub); 5675 compiler->AddStubCallTarget(stub);
5944 __ Drop(ArgumentCount()); // Discard arguments. 5676 __ Drop(ArgumentCount()); // Discard arguments.
5945 } 5677 }
5946 5678
5947
5948 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5679 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5949 ASSERT(!compiler->is_optimizing()); 5680 ASSERT(!compiler->is_optimizing());
5950 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); 5681 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry());
5951 compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos()); 5682 compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
5952 compiler->RecordSafepoint(locs()); 5683 compiler->RecordSafepoint(locs());
5953 } 5684 }
5954 5685
5955
5956 } // namespace dart 5686 } // namespace dart
5957 5687
5958 #endif // defined TARGET_ARCH_ARM64 5688 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/intermediate_language_dbc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698