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

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

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

Powered by Google App Engine
This is Rietveld 408576698