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

Side by Side Diff: runtime/vm/intermediate_language_ia32.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_dbc.cc ('k') | runtime/vm/intermediate_language_mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 12 matching lines...) Expand all
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 EAX. 29 // on the stack and return the result in a fixed register EAX.
30 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { 30 LocationSummary* Instruction::MakeCallSummary(Zone* zone) {
31 const intptr_t kNumInputs = 0; 31 const intptr_t kNumInputs = 0;
32 const intptr_t kNumTemps = 0; 32 const intptr_t kNumTemps = 0;
33 LocationSummary* result = new(zone) LocationSummary( 33 LocationSummary* result = new (zone)
34 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 34 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
35 result->set_out(0, Location::RegisterLocation(EAX)); 35 result->set_out(0, Location::RegisterLocation(EAX));
36 return result; 36 return result;
37 } 37 }
38 38
39 39
40 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, 40 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone,
41 bool opt) const { 41 bool opt) const {
42 const intptr_t kNumInputs = 1; 42 const intptr_t kNumInputs = 1;
43 const intptr_t kNumTemps = 0; 43 const intptr_t kNumTemps = 0;
44 LocationSummary* locs = new(zone) LocationSummary( 44 LocationSummary* locs = new (zone)
45 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 45 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
46 locs->set_in(0, Location::AnyOrConstant(value())); 46 locs->set_in(0, Location::AnyOrConstant(value()));
47 return locs; 47 return locs;
48 } 48 }
49 49
50 50
51 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 51 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
52 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode 52 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode
53 // where PushArgument is handled by BindInstr::EmitNativeCode. 53 // where PushArgument is handled by BindInstr::EmitNativeCode.
54 if (compiler->is_optimizing()) { 54 if (compiler->is_optimizing()) {
55 Location value = locs()->in(0); 55 Location value = locs()->in(0);
56 if (value.IsRegister()) { 56 if (value.IsRegister()) {
57 __ pushl(value.reg()); 57 __ pushl(value.reg());
58 } else if (value.IsConstant()) { 58 } else if (value.IsConstant()) {
59 __ PushObject(value.constant()); 59 __ PushObject(value.constant());
60 } else { 60 } else {
61 ASSERT(value.IsStackSlot()); 61 ASSERT(value.IsStackSlot());
62 __ pushl(value.ToStackSlotAddress()); 62 __ pushl(value.ToStackSlotAddress());
63 } 63 }
64 } 64 }
65 } 65 }
66 66
67 67
68 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, 68 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const {
69 bool opt) const {
70 const intptr_t kNumInputs = 1; 69 const intptr_t kNumInputs = 1;
71 const intptr_t kNumTemps = 0; 70 const intptr_t kNumTemps = 0;
72 LocationSummary* locs = new(zone) LocationSummary( 71 LocationSummary* locs = new (zone)
73 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 72 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
74 locs->set_in(0, Location::RegisterLocation(EAX)); 73 locs->set_in(0, Location::RegisterLocation(EAX));
75 return locs; 74 return locs;
76 } 75 }
77 76
78 77
79 // Attempt optimized compilation at return instruction instead of at the entry. 78 // Attempt optimized compilation at return instruction instead of at the entry.
80 // The entry needs to be patchable, no inlined objects are allowed in the area 79 // The entry needs to be patchable, no inlined objects are allowed in the area
81 // that will be overwritten by the patch instruction: a jump). 80 // that will be overwritten by the patch instruction: a jump).
82 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 81 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
83 Register result = locs()->in(0).reg(); 82 Register result = locs()->in(0).reg();
(...skipping 20 matching lines...) Expand all
104 #endif 103 #endif
105 __ LeaveFrame(); 104 __ LeaveFrame();
106 __ ret(); 105 __ ret();
107 } 106 }
108 107
109 108
110 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, 109 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone,
111 bool opt) const { 110 bool opt) const {
112 const intptr_t kNumInputs = 0; 111 const intptr_t kNumInputs = 0;
113 const intptr_t stack_index = (local().index() < 0) 112 const intptr_t stack_index = (local().index() < 0)
114 ? kFirstLocalSlotFromFp - local().index() 113 ? kFirstLocalSlotFromFp - local().index()
115 : kParamEndSlotFromFp - local().index(); 114 : kParamEndSlotFromFp - local().index();
116 return LocationSummary::Make(zone, 115 return LocationSummary::Make(zone, kNumInputs,
117 kNumInputs,
118 Location::StackSlot(stack_index), 116 Location::StackSlot(stack_index),
119 LocationSummary::kNoCall); 117 LocationSummary::kNoCall);
120 } 118 }
121 119
122 120
123 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 121 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
124 ASSERT(!compiler->is_optimizing()); 122 ASSERT(!compiler->is_optimizing());
125 // Nothing to do. 123 // Nothing to do.
126 } 124 }
127 125
128 126
129 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, 127 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone,
130 bool opt) const { 128 bool opt) const {
131 const intptr_t kNumInputs = 1; 129 const intptr_t kNumInputs = 1;
132 return LocationSummary::Make(zone, 130 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(),
133 kNumInputs,
134 Location::SameAsFirstInput(),
135 LocationSummary::kNoCall); 131 LocationSummary::kNoCall);
136 } 132 }
137 133
138 134
139 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 135 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
140 Register value = locs()->in(0).reg(); 136 Register value = locs()->in(0).reg();
141 Register result = locs()->out(0).reg(); 137 Register result = locs()->out(0).reg();
142 ASSERT(result == value); // Assert that register assignment is correct. 138 ASSERT(result == value); // Assert that register assignment is correct.
143 __ movl(Address(EBP, local().index() * kWordSize), value); 139 __ movl(Address(EBP, local().index() * kWordSize), value);
144 } 140 }
145 141
146 142
147 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, 143 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone,
148 bool opt) const { 144 bool opt) const {
149 const intptr_t kNumInputs = 0; 145 const intptr_t kNumInputs = 0;
150 return LocationSummary::Make(zone, 146 return LocationSummary::Make(zone, kNumInputs,
151 kNumInputs,
152 Assembler::IsSafe(value()) 147 Assembler::IsSafe(value())
153 ? Location::Constant(this) 148 ? Location::Constant(this)
154 : Location::RequiresRegister(), 149 : Location::RequiresRegister(),
155 LocationSummary::kNoCall); 150 LocationSummary::kNoCall);
156 } 151 }
157 152
158 153
159 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 154 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
160 // The register allocator drops constant definitions that have no uses. 155 // The register allocator drops constant definitions that have no uses.
161 Location out = locs()->out(0); 156 Location out = locs()->out(0);
162 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); 157 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid());
163 if (out.IsRegister()) { 158 if (out.IsRegister()) {
164 Register result = out.reg(); 159 Register result = out.reg();
165 __ LoadObjectSafely(result, value()); 160 __ LoadObjectSafely(result, value());
166 } 161 }
167 } 162 }
168 163
169 164
170 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, 165 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone,
171 bool opt) const { 166 bool opt) const {
172 const intptr_t kNumInputs = 0; 167 const intptr_t kNumInputs = 0;
173 const intptr_t kNumTemps = 168 const intptr_t kNumTemps =
174 (constant_address() == 0) && (representation() != kUnboxedInt32) ? 1 : 0; 169 (constant_address() == 0) && (representation() != kUnboxedInt32) ? 1 : 0;
175 LocationSummary* locs = new(zone) LocationSummary( 170 LocationSummary* locs = new (zone)
176 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 171 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
177 if (representation() == kUnboxedDouble) { 172 if (representation() == kUnboxedDouble) {
178 locs->set_out(0, Location::RequiresFpuRegister()); 173 locs->set_out(0, Location::RequiresFpuRegister());
179 } else { 174 } else {
180 ASSERT(representation() == kUnboxedInt32); 175 ASSERT(representation() == kUnboxedInt32);
181 locs->set_out(0, Location::RequiresRegister()); 176 locs->set_out(0, Location::RequiresRegister());
182 } 177 }
183 if (kNumTemps == 1) { 178 if (kNumTemps == 1) {
184 locs->set_temp(0, Location::RequiresRegister()); 179 locs->set_temp(0, Location::RequiresRegister());
185 } 180 }
186 return locs; 181 return locs;
(...skipping 24 matching lines...) Expand all
211 UNREACHABLE(); 206 UNREACHABLE();
212 } 207 }
213 } 208 }
214 } 209 }
215 210
216 211
217 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, 212 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
218 bool opt) const { 213 bool opt) const {
219 const intptr_t kNumInputs = 2; 214 const intptr_t kNumInputs = 2;
220 const intptr_t kNumTemps = 0; 215 const intptr_t kNumTemps = 0;
221 LocationSummary* summary = new(zone) LocationSummary( 216 LocationSummary* summary = new (zone)
222 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 217 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
223 summary->set_in(0, Location::RegisterLocation(EAX)); // Value. 218 summary->set_in(0, Location::RegisterLocation(EAX)); // Value.
224 summary->set_in(1, Location::RegisterLocation(EDX)); // Type arguments. 219 summary->set_in(1, Location::RegisterLocation(EDX)); // Type arguments.
225 summary->set_out(0, Location::RegisterLocation(EAX)); 220 summary->set_out(0, Location::RegisterLocation(EAX));
226 return summary; 221 return summary;
227 } 222 }
228 223
229 224
230 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, 225 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone,
231 bool opt) const { 226 bool opt) const {
232 const intptr_t kNumInputs = 1; 227 const intptr_t kNumInputs = 1;
233 const intptr_t kNumTemps = 0; 228 const intptr_t kNumTemps = 0;
234 LocationSummary* locs = new(zone) LocationSummary( 229 LocationSummary* locs = new (zone)
235 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 230 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
236 locs->set_in(0, Location::RegisterLocation(EAX)); 231 locs->set_in(0, Location::RegisterLocation(EAX));
237 locs->set_out(0, Location::RegisterLocation(EAX)); 232 locs->set_out(0, Location::RegisterLocation(EAX));
238 return locs; 233 return locs;
239 } 234 }
240 235
241 236
242 static void EmitAssertBoolean(Register reg, 237 static void EmitAssertBoolean(Register reg,
243 TokenPosition token_pos, 238 TokenPosition token_pos,
244 intptr_t deopt_id, 239 intptr_t deopt_id,
245 LocationSummary* locs, 240 LocationSummary* locs,
246 FlowGraphCompiler* compiler) { 241 FlowGraphCompiler* compiler) {
247 // Check that the type of the value is allowed in conditional context. 242 // Check that the type of the value is allowed in conditional context.
248 // Call the runtime if the object is not bool::true or bool::false. 243 // Call the runtime if the object is not bool::true or bool::false.
249 ASSERT(locs->always_calls()); 244 ASSERT(locs->always_calls());
250 Label done; 245 Label done;
251 246
252 if (Isolate::Current()->type_checks()) { 247 if (Isolate::Current()->type_checks()) {
253 __ CompareObject(reg, Bool::True()); 248 __ CompareObject(reg, Bool::True());
254 __ j(EQUAL, &done, Assembler::kNearJump); 249 __ j(EQUAL, &done, Assembler::kNearJump);
255 __ CompareObject(reg, Bool::False()); 250 __ CompareObject(reg, Bool::False());
256 __ j(EQUAL, &done, Assembler::kNearJump); 251 __ j(EQUAL, &done, Assembler::kNearJump);
257 } else { 252 } else {
258 ASSERT(Isolate::Current()->asserts()); 253 ASSERT(Isolate::Current()->asserts());
259 __ CompareObject(reg, Object::null_instance()); 254 __ CompareObject(reg, Object::null_instance());
260 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 255 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
261 } 256 }
262 257
263 __ pushl(reg); // Push the source object. 258 __ pushl(reg); // Push the source object.
264 compiler->GenerateRuntimeCall(token_pos, 259 compiler->GenerateRuntimeCall(token_pos, deopt_id,
265 deopt_id, 260 kNonBoolTypeErrorRuntimeEntry, 1, locs);
266 kNonBoolTypeErrorRuntimeEntry,
267 1,
268 locs);
269 // We should never return here. 261 // We should never return here.
270 __ int3(); 262 __ int3();
271 __ Bind(&done); 263 __ Bind(&done);
272 } 264 }
273 265
274 266
275 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 267 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
276 Register obj = locs()->in(0).reg(); 268 Register obj = locs()->in(0).reg();
277 Register result = locs()->out(0).reg(); 269 Register result = locs()->out(0).reg();
278 270
279 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); 271 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler);
280 ASSERT(obj == result); 272 ASSERT(obj == result);
281 } 273 }
282 274
283 275
284 static Condition TokenKindToSmiCondition(Token::Kind kind) { 276 static Condition TokenKindToSmiCondition(Token::Kind kind) {
285 switch (kind) { 277 switch (kind) {
286 case Token::kEQ: return EQUAL; 278 case Token::kEQ:
287 case Token::kNE: return NOT_EQUAL; 279 return EQUAL;
288 case Token::kLT: return LESS; 280 case Token::kNE:
289 case Token::kGT: return GREATER; 281 return NOT_EQUAL;
290 case Token::kLTE: return LESS_EQUAL; 282 case Token::kLT:
291 case Token::kGTE: return GREATER_EQUAL; 283 return LESS;
284 case Token::kGT:
285 return GREATER;
286 case Token::kLTE:
287 return LESS_EQUAL;
288 case Token::kGTE:
289 return GREATER_EQUAL;
292 default: 290 default:
293 UNREACHABLE(); 291 UNREACHABLE();
294 return OVERFLOW; 292 return OVERFLOW;
295 } 293 }
296 } 294 }
297 295
298 296
299 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, 297 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone,
300 bool opt) const { 298 bool opt) const {
301 const intptr_t kNumInputs = 2; 299 const intptr_t kNumInputs = 2;
302 if (operation_cid() == kMintCid) { 300 if (operation_cid() == kMintCid) {
303 const intptr_t kNumTemps = 0; 301 const intptr_t kNumTemps = 0;
304 LocationSummary* locs = new(zone) LocationSummary( 302 LocationSummary* locs = new (zone)
305 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 303 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
306 locs->set_in(0, Location::Pair(Location::RequiresRegister(), 304 locs->set_in(0, Location::Pair(Location::RequiresRegister(),
307 Location::RequiresRegister())); 305 Location::RequiresRegister()));
308 locs->set_in(1, Location::Pair(Location::RequiresRegister(), 306 locs->set_in(1, Location::Pair(Location::RequiresRegister(),
309 Location::RequiresRegister())); 307 Location::RequiresRegister()));
310 locs->set_out(0, Location::RequiresRegister()); 308 locs->set_out(0, Location::RequiresRegister());
311 return locs; 309 return locs;
312 } 310 }
313 if (operation_cid() == kDoubleCid) { 311 if (operation_cid() == kDoubleCid) {
314 const intptr_t kNumTemps = 0; 312 const intptr_t kNumTemps = 0;
315 LocationSummary* locs = new(zone) LocationSummary( 313 LocationSummary* locs = new (zone)
316 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 314 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
317 locs->set_in(0, Location::RequiresFpuRegister()); 315 locs->set_in(0, Location::RequiresFpuRegister());
318 locs->set_in(1, Location::RequiresFpuRegister()); 316 locs->set_in(1, Location::RequiresFpuRegister());
319 locs->set_out(0, Location::RequiresRegister()); 317 locs->set_out(0, Location::RequiresRegister());
320 return locs; 318 return locs;
321 } 319 }
322 if (operation_cid() == kSmiCid) { 320 if (operation_cid() == kSmiCid) {
323 const intptr_t kNumTemps = 0; 321 const intptr_t kNumTemps = 0;
324 LocationSummary* locs = new(zone) LocationSummary( 322 LocationSummary* locs = new (zone)
325 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 323 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
326 locs->set_in(0, Location::RegisterOrConstant(left())); 324 locs->set_in(0, Location::RegisterOrConstant(left()));
327 // Only one input can be a constant operand. The case of two constant 325 // Only one input can be a constant operand. The case of two constant
328 // operands should be handled by constant propagation. 326 // operands should be handled by constant propagation.
329 // Only right can be a stack slot. 327 // Only right can be a stack slot.
330 locs->set_in(1, locs->in(0).IsConstant() 328 locs->set_in(1, locs->in(0).IsConstant()
331 ? Location::RequiresRegister() 329 ? Location::RequiresRegister()
332 : Location::RegisterOrConstant(right())); 330 : Location::RegisterOrConstant(right()));
333 locs->set_out(0, Location::RequiresRegister()); 331 locs->set_out(0, Location::RequiresRegister());
334 return locs; 332 return locs;
335 } 333 }
(...skipping 16 matching lines...) Expand all
352 } else { 350 } else {
353 __ j(ZERO, value_is_smi); 351 __ j(ZERO, value_is_smi);
354 } 352 }
355 __ LoadClassId(value_cid_reg, value_reg); 353 __ LoadClassId(value_cid_reg, value_reg);
356 __ Bind(&done); 354 __ Bind(&done);
357 } 355 }
358 356
359 357
360 static Condition FlipCondition(Condition condition) { 358 static Condition FlipCondition(Condition condition) {
361 switch (condition) { 359 switch (condition) {
362 case EQUAL: return EQUAL; 360 case EQUAL:
363 case NOT_EQUAL: return NOT_EQUAL; 361 return EQUAL;
364 case LESS: return GREATER; 362 case NOT_EQUAL:
365 case LESS_EQUAL: return GREATER_EQUAL; 363 return NOT_EQUAL;
366 case GREATER: return LESS; 364 case LESS:
367 case GREATER_EQUAL: return LESS_EQUAL; 365 return GREATER;
368 case BELOW: return ABOVE; 366 case LESS_EQUAL:
369 case BELOW_EQUAL: return ABOVE_EQUAL; 367 return GREATER_EQUAL;
370 case ABOVE: return BELOW; 368 case GREATER:
371 case ABOVE_EQUAL: return BELOW_EQUAL; 369 return LESS;
370 case GREATER_EQUAL:
371 return LESS_EQUAL;
372 case BELOW:
373 return ABOVE;
374 case BELOW_EQUAL:
375 return ABOVE_EQUAL;
376 case ABOVE:
377 return BELOW;
378 case ABOVE_EQUAL:
379 return BELOW_EQUAL;
372 default: 380 default:
373 UNIMPLEMENTED(); 381 UNIMPLEMENTED();
374 return EQUAL; 382 return EQUAL;
375 } 383 }
376 } 384 }
377 385
378 386
379 static Condition NegateCondition(Condition condition) { 387 static Condition NegateCondition(Condition condition) {
380 switch (condition) { 388 switch (condition) {
381 case EQUAL: return NOT_EQUAL; 389 case EQUAL:
382 case NOT_EQUAL: return EQUAL; 390 return NOT_EQUAL;
383 case LESS: return GREATER_EQUAL; 391 case NOT_EQUAL:
384 case LESS_EQUAL: return GREATER; 392 return EQUAL;
385 case GREATER: return LESS_EQUAL; 393 case LESS:
386 case GREATER_EQUAL: return LESS; 394 return GREATER_EQUAL;
387 case BELOW: return ABOVE_EQUAL; 395 case LESS_EQUAL:
388 case BELOW_EQUAL: return ABOVE; 396 return GREATER;
389 case ABOVE: return BELOW_EQUAL; 397 case GREATER:
390 case ABOVE_EQUAL: return BELOW; 398 return LESS_EQUAL;
391 case PARITY_ODD: return PARITY_EVEN; 399 case GREATER_EQUAL:
392 case PARITY_EVEN: return PARITY_ODD; 400 return LESS;
401 case BELOW:
402 return ABOVE_EQUAL;
403 case BELOW_EQUAL:
404 return ABOVE;
405 case ABOVE:
406 return BELOW_EQUAL;
407 case ABOVE_EQUAL:
408 return BELOW;
409 case PARITY_ODD:
410 return PARITY_EVEN;
411 case PARITY_EVEN:
412 return PARITY_ODD;
393 default: 413 default:
394 UNIMPLEMENTED(); 414 UNIMPLEMENTED();
395 return EQUAL; 415 return EQUAL;
396 } 416 }
397 } 417 }
398 418
399 419
400 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, 420 static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
401 Condition true_condition, 421 Condition true_condition,
402 BranchLabels labels) { 422 BranchLabels labels) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 __ cmpl(left.reg(), right.ToStackSlotAddress()); 455 __ cmpl(left.reg(), right.ToStackSlotAddress());
436 } else { 456 } else {
437 __ cmpl(left.reg(), right.reg()); 457 __ cmpl(left.reg(), right.reg());
438 } 458 }
439 return true_condition; 459 return true_condition;
440 } 460 }
441 461
442 462
443 static Condition TokenKindToMintCondition(Token::Kind kind) { 463 static Condition TokenKindToMintCondition(Token::Kind kind) {
444 switch (kind) { 464 switch (kind) {
445 case Token::kEQ: return EQUAL; 465 case Token::kEQ:
446 case Token::kNE: return NOT_EQUAL; 466 return EQUAL;
447 case Token::kLT: return LESS; 467 case Token::kNE:
448 case Token::kGT: return GREATER; 468 return NOT_EQUAL;
449 case Token::kLTE: return LESS_EQUAL; 469 case Token::kLT:
450 case Token::kGTE: return GREATER_EQUAL; 470 return LESS;
471 case Token::kGT:
472 return GREATER;
473 case Token::kLTE:
474 return LESS_EQUAL;
475 case Token::kGTE:
476 return GREATER_EQUAL;
451 default: 477 default:
452 UNREACHABLE(); 478 UNREACHABLE();
453 return OVERFLOW; 479 return OVERFLOW;
454 } 480 }
455 } 481 }
456 482
457 483
458 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 484 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
459 const LocationSummary& locs, 485 const LocationSummary& locs,
460 Token::Kind kind, 486 Token::Kind kind,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 __ j(FlipCondition(hi_cond), labels.false_label); 543 __ j(FlipCondition(hi_cond), labels.false_label);
518 544
519 // If upper is equal, compare lower half. 545 // If upper is equal, compare lower half.
520 __ cmpl(left1, right1); 546 __ cmpl(left1, right1);
521 return lo_cond; 547 return lo_cond;
522 } 548 }
523 549
524 550
525 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 551 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
526 switch (kind) { 552 switch (kind) {
527 case Token::kEQ: return EQUAL; 553 case Token::kEQ:
528 case Token::kNE: return NOT_EQUAL; 554 return EQUAL;
529 case Token::kLT: return BELOW; 555 case Token::kNE:
530 case Token::kGT: return ABOVE; 556 return NOT_EQUAL;
531 case Token::kLTE: return BELOW_EQUAL; 557 case Token::kLT:
532 case Token::kGTE: return ABOVE_EQUAL; 558 return BELOW;
559 case Token::kGT:
560 return ABOVE;
561 case Token::kLTE:
562 return BELOW_EQUAL;
563 case Token::kGTE:
564 return ABOVE_EQUAL;
533 default: 565 default:
534 UNREACHABLE(); 566 UNREACHABLE();
535 return OVERFLOW; 567 return OVERFLOW;
536 } 568 }
537 } 569 }
538 570
539 571
540 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 572 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
541 const LocationSummary& locs, 573 const LocationSummary& locs,
542 Token::Kind kind, 574 Token::Kind kind,
543 BranchLabels labels) { 575 BranchLabels labels) {
544 XmmRegister left = locs.in(0).fpu_reg(); 576 XmmRegister left = locs.in(0).fpu_reg();
545 XmmRegister right = locs.in(1).fpu_reg(); 577 XmmRegister right = locs.in(1).fpu_reg();
546 578
547 __ comisd(left, right); 579 __ comisd(left, right);
548 580
549 Condition true_condition = TokenKindToDoubleCondition(kind); 581 Condition true_condition = TokenKindToDoubleCondition(kind);
550 Label* nan_result = (true_condition == NOT_EQUAL) 582 Label* nan_result =
551 ? labels.true_label : labels.false_label; 583 (true_condition == NOT_EQUAL) ? labels.true_label : labels.false_label;
552 __ j(PARITY_EVEN, nan_result); 584 __ j(PARITY_EVEN, nan_result);
553 return true_condition; 585 return true_condition;
554 } 586 }
555 587
556 588
557 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 589 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
558 BranchLabels labels) { 590 BranchLabels labels) {
559 if (operation_cid() == kSmiCid) { 591 if (operation_cid() == kSmiCid) {
560 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); 592 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
561 } else if (operation_cid() == kMintCid) { 593 } else if (operation_cid() == kMintCid) {
562 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels); 594 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
563 } else { 595 } else {
564 ASSERT(operation_cid() == kDoubleCid); 596 ASSERT(operation_cid() == kDoubleCid);
565 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); 597 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
566 } 598 }
567 } 599 }
568 600
569 601
570 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 602 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
571 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 603 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
572 604
573 Label is_true, is_false; 605 Label is_true, is_false;
574 BranchLabels labels = { &is_true, &is_false, &is_false }; 606 BranchLabels labels = {&is_true, &is_false, &is_false};
575 Condition true_condition = EmitComparisonCode(compiler, labels); 607 Condition true_condition = EmitComparisonCode(compiler, labels);
576 EmitBranchOnCondition(compiler, true_condition, labels); 608 EmitBranchOnCondition(compiler, true_condition, labels);
577 609
578 Register result = locs()->out(0).reg(); 610 Register result = locs()->out(0).reg();
579 Label done; 611 Label done;
580 __ Bind(&is_false); 612 __ Bind(&is_false);
581 __ LoadObject(result, Bool::False()); 613 __ LoadObject(result, Bool::False());
582 __ jmp(&done, Assembler::kNearJump); 614 __ jmp(&done, Assembler::kNearJump);
583 __ Bind(&is_true); 615 __ Bind(&is_true);
584 __ LoadObject(result, Bool::True()); 616 __ LoadObject(result, Bool::True());
585 __ Bind(&done); 617 __ Bind(&done);
586 } 618 }
587 619
588 620
589 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 621 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
590 BranchInstr* branch) { 622 BranchInstr* branch) {
591 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 623 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
592 624
593 BranchLabels labels = compiler->CreateBranchLabels(branch); 625 BranchLabels labels = compiler->CreateBranchLabels(branch);
594 Condition true_condition = EmitComparisonCode(compiler, labels); 626 Condition true_condition = EmitComparisonCode(compiler, labels);
595 EmitBranchOnCondition(compiler, true_condition, labels); 627 EmitBranchOnCondition(compiler, true_condition, labels);
596 } 628 }
597 629
598 630
599 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, 631 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const {
600 bool opt) const {
601 const intptr_t kNumInputs = 2; 632 const intptr_t kNumInputs = 2;
602 const intptr_t kNumTemps = 0; 633 const intptr_t kNumTemps = 0;
603 LocationSummary* locs = new(zone) LocationSummary( 634 LocationSummary* locs = new (zone)
604 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 635 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
605 locs->set_in(0, Location::RequiresRegister()); 636 locs->set_in(0, Location::RequiresRegister());
606 // Only one input can be a constant operand. The case of two constant 637 // Only one input can be a constant operand. The case of two constant
607 // operands should be handled by constant propagation. 638 // operands should be handled by constant propagation.
608 locs->set_in(1, Location::RegisterOrConstant(right())); 639 locs->set_in(1, Location::RegisterOrConstant(right()));
609 return locs; 640 return locs;
610 } 641 }
611 642
612 643
613 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 644 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
614 BranchLabels labels) { 645 BranchLabels labels) {
615 Register left = locs()->in(0).reg(); 646 Register left = locs()->in(0).reg();
616 Location right = locs()->in(1); 647 Location right = locs()->in(1);
617 if (right.IsConstant()) { 648 if (right.IsConstant()) {
618 ASSERT(right.constant().IsSmi()); 649 ASSERT(right.constant().IsSmi());
619 const int32_t imm = 650 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw());
620 reinterpret_cast<int32_t>(right.constant().raw());
621 __ testl(left, Immediate(imm)); 651 __ testl(left, Immediate(imm));
622 } else { 652 } else {
623 __ testl(left, right.reg()); 653 __ testl(left, right.reg());
624 } 654 }
625 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; 655 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO;
626 return true_condition; 656 return true_condition;
627 } 657 }
628 658
629 659
630 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 660 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
631 // Never emitted outside of the BranchInstr. 661 // Never emitted outside of the BranchInstr.
632 UNREACHABLE(); 662 UNREACHABLE();
633 } 663 }
634 664
635 665
636 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, 666 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
637 BranchInstr* branch) { 667 BranchInstr* branch) {
638 BranchLabels labels = compiler->CreateBranchLabels(branch); 668 BranchLabels labels = compiler->CreateBranchLabels(branch);
639 Condition true_condition = EmitComparisonCode(compiler, labels); 669 Condition true_condition = EmitComparisonCode(compiler, labels);
640 EmitBranchOnCondition(compiler, true_condition, labels); 670 EmitBranchOnCondition(compiler, true_condition, labels);
641 } 671 }
642 672
643 673
644
645 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, 674 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone,
646 bool opt) const { 675 bool opt) const {
647 const intptr_t kNumInputs = 1; 676 const intptr_t kNumInputs = 1;
648 const intptr_t kNumTemps = 1; 677 const intptr_t kNumTemps = 1;
649 LocationSummary* locs = new(zone) LocationSummary( 678 LocationSummary* locs = new (zone)
650 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 679 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
651 locs->set_in(0, Location::RequiresRegister()); 680 locs->set_in(0, Location::RequiresRegister());
652 locs->set_temp(0, Location::RequiresRegister()); 681 locs->set_temp(0, Location::RequiresRegister());
653 locs->set_out(0, Location::RequiresRegister()); 682 locs->set_out(0, Location::RequiresRegister());
654 return locs; 683 return locs;
655 } 684 }
656 685
657 686
658 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 687 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
659 BranchLabels labels) { 688 BranchLabels labels) {
660 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); 689 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT));
661 Register val_reg = locs()->in(0).reg(); 690 Register val_reg = locs()->in(0).reg();
662 Register cid_reg = locs()->temp(0).reg(); 691 Register cid_reg = locs()->temp(0).reg();
663 692
664 Label* deopt = CanDeoptimize() 693 Label* deopt =
665 ? compiler->AddDeoptStub(deopt_id(), 694 CanDeoptimize()
666 ICData::kDeoptTestCids, 695 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids,
667 licm_hoisted_ ? ICData::kHoisted : 0) 696 licm_hoisted_ ? ICData::kHoisted : 0)
668 : NULL; 697 : NULL;
669 698
670 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; 699 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
671 const ZoneGrowableArray<intptr_t>& data = cid_results(); 700 const ZoneGrowableArray<intptr_t>& data = cid_results();
672 ASSERT(data[0] == kSmiCid); 701 ASSERT(data[0] == kSmiCid);
673 bool result = data[1] == true_result; 702 bool result = data[1] == true_result;
674 __ testl(val_reg, Immediate(kSmiTagMask)); 703 __ testl(val_reg, Immediate(kSmiTagMask));
675 __ j(ZERO, result ? labels.true_label : labels.false_label); 704 __ j(ZERO, result ? labels.true_label : labels.false_label);
676 __ LoadClassId(cid_reg, val_reg); 705 __ LoadClassId(cid_reg, val_reg);
677 for (intptr_t i = 2; i < data.length(); i += 2) { 706 for (intptr_t i = 2; i < data.length(); i += 2) {
678 const intptr_t test_cid = data[i]; 707 const intptr_t test_cid = data[i];
679 ASSERT(test_cid != kSmiCid); 708 ASSERT(test_cid != kSmiCid);
680 result = data[i + 1] == true_result; 709 result = data[i + 1] == true_result;
681 __ cmpl(cid_reg, Immediate(test_cid)); 710 __ cmpl(cid_reg, Immediate(test_cid));
682 __ j(EQUAL, result ? labels.true_label : labels.false_label); 711 __ j(EQUAL, result ? labels.true_label : labels.false_label);
683 } 712 }
684 // No match found, deoptimize or false. 713 // No match found, deoptimize or false.
685 if (deopt == NULL) { 714 if (deopt == NULL) {
686 Label* target = result ? labels.false_label : labels.true_label; 715 Label* target = result ? labels.false_label : labels.true_label;
687 if (target != labels.fall_through) { 716 if (target != labels.fall_through) {
688 __ jmp(target); 717 __ jmp(target);
689 } 718 }
690 } else { 719 } else {
691 __ jmp(deopt); 720 __ jmp(deopt);
692 } 721 }
693 // Dummy result as the last instruction is a jump, any conditional 722 // Dummy result as the last instruction is a jump, any conditional
694 // branch using the result will therefore be skipped. 723 // branch using the result will therefore be skipped.
695 return ZERO; 724 return ZERO;
696 } 725 }
697 726
698 727
699 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, 728 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
700 BranchInstr* branch) { 729 BranchInstr* branch) {
701 BranchLabels labels = compiler->CreateBranchLabels(branch); 730 BranchLabels labels = compiler->CreateBranchLabels(branch);
702 EmitComparisonCode(compiler, labels); 731 EmitComparisonCode(compiler, labels);
703 } 732 }
704 733
705 734
706 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 735 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
707 Register result_reg = locs()->out(0).reg(); 736 Register result_reg = locs()->out(0).reg();
708 Label is_true, is_false, done; 737 Label is_true, is_false, done;
709 BranchLabels labels = { &is_true, &is_false, &is_false }; 738 BranchLabels labels = {&is_true, &is_false, &is_false};
710 EmitComparisonCode(compiler, labels); 739 EmitComparisonCode(compiler, labels);
711 __ Bind(&is_false); 740 __ Bind(&is_false);
712 __ LoadObject(result_reg, Bool::False()); 741 __ LoadObject(result_reg, Bool::False());
713 __ jmp(&done, Assembler::kNearJump); 742 __ jmp(&done, Assembler::kNearJump);
714 __ Bind(&is_true); 743 __ Bind(&is_true);
715 __ LoadObject(result_reg, Bool::True()); 744 __ LoadObject(result_reg, Bool::True());
716 __ Bind(&done); 745 __ Bind(&done);
717 } 746 }
718 747
719 748
720 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, 749 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone,
721 bool opt) const { 750 bool opt) const {
722 const intptr_t kNumInputs = 2; 751 const intptr_t kNumInputs = 2;
723 const intptr_t kNumTemps = 0; 752 const intptr_t kNumTemps = 0;
724 if (operation_cid() == kMintCid) { 753 if (operation_cid() == kMintCid) {
725 const intptr_t kNumTemps = 0; 754 const intptr_t kNumTemps = 0;
726 LocationSummary* locs = new(zone) LocationSummary( 755 LocationSummary* locs = new (zone)
727 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 756 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
728 locs->set_in(0, Location::Pair(Location::RequiresRegister(), 757 locs->set_in(0, Location::Pair(Location::RequiresRegister(),
729 Location::RequiresRegister())); 758 Location::RequiresRegister()));
730 locs->set_in(1, Location::Pair(Location::RequiresRegister(), 759 locs->set_in(1, Location::Pair(Location::RequiresRegister(),
731 Location::RequiresRegister())); 760 Location::RequiresRegister()));
732 locs->set_out(0, Location::RequiresRegister()); 761 locs->set_out(0, Location::RequiresRegister());
733 return locs; 762 return locs;
734 } 763 }
735 if (operation_cid() == kDoubleCid) { 764 if (operation_cid() == kDoubleCid) {
736 LocationSummary* summary = new(zone) LocationSummary( 765 LocationSummary* summary = new (zone)
737 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 766 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
738 summary->set_in(0, Location::RequiresFpuRegister()); 767 summary->set_in(0, Location::RequiresFpuRegister());
739 summary->set_in(1, Location::RequiresFpuRegister()); 768 summary->set_in(1, Location::RequiresFpuRegister());
740 summary->set_out(0, Location::RequiresRegister()); 769 summary->set_out(0, Location::RequiresRegister());
741 return summary; 770 return summary;
742 } 771 }
743 ASSERT(operation_cid() == kSmiCid); 772 ASSERT(operation_cid() == kSmiCid);
744 LocationSummary* summary = new(zone) LocationSummary( 773 LocationSummary* summary = new (zone)
745 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 774 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
746 summary->set_in(0, Location::RegisterOrConstant(left())); 775 summary->set_in(0, Location::RegisterOrConstant(left()));
747 // Only one input can be a constant operand. The case of two constant 776 // Only one input can be a constant operand. The case of two constant
748 // operands should be handled by constant propagation. 777 // operands should be handled by constant propagation.
749 summary->set_in(1, summary->in(0).IsConstant() 778 summary->set_in(1, summary->in(0).IsConstant()
750 ? Location::RequiresRegister() 779 ? Location::RequiresRegister()
751 : Location::RegisterOrConstant(right())); 780 : Location::RegisterOrConstant(right()));
752 summary->set_out(0, Location::RequiresRegister()); 781 summary->set_out(0, Location::RequiresRegister());
753 return summary; 782 return summary;
754 } 783 }
755 784
756 785
757 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 786 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
758 BranchLabels labels) { 787 BranchLabels labels) {
759 if (operation_cid() == kSmiCid) { 788 if (operation_cid() == kSmiCid) {
760 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); 789 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
761 } else if (operation_cid() == kMintCid) { 790 } else if (operation_cid() == kMintCid) {
762 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); 791 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
763 } else { 792 } else {
764 ASSERT(operation_cid() == kDoubleCid); 793 ASSERT(operation_cid() == kDoubleCid);
765 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); 794 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
766 } 795 }
767 } 796 }
768 797
769 798
770 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 799 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
771 Label is_true, is_false; 800 Label is_true, is_false;
772 BranchLabels labels = { &is_true, &is_false, &is_false }; 801 BranchLabels labels = {&is_true, &is_false, &is_false};
773 Condition true_condition = EmitComparisonCode(compiler, labels); 802 Condition true_condition = EmitComparisonCode(compiler, labels);
774 EmitBranchOnCondition(compiler, true_condition, labels); 803 EmitBranchOnCondition(compiler, true_condition, labels);
775 804
776 Register result = locs()->out(0).reg(); 805 Register result = locs()->out(0).reg();
777 Label done; 806 Label done;
778 __ Bind(&is_false); 807 __ Bind(&is_false);
779 __ LoadObject(result, Bool::False()); 808 __ LoadObject(result, Bool::False());
780 __ jmp(&done, Assembler::kNearJump); 809 __ jmp(&done, Assembler::kNearJump);
781 __ Bind(&is_true); 810 __ Bind(&is_true);
782 __ LoadObject(result, Bool::True()); 811 __ LoadObject(result, Bool::True());
(...skipping 17 matching lines...) Expand all
800 829
801 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 830 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
802 SetupNative(); 831 SetupNative();
803 Register result = locs()->out(0).reg(); 832 Register result = locs()->out(0).reg();
804 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); 833 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
805 834
806 // Push the result place holder initialized to NULL. 835 // Push the result place holder initialized to NULL.
807 __ PushObject(Object::null_object()); 836 __ PushObject(Object::null_object());
808 // Pass a pointer to the first argument in EAX. 837 // Pass a pointer to the first argument in EAX.
809 if (!function().HasOptionalParameters()) { 838 if (!function().HasOptionalParameters()) {
810 __ leal(EAX, Address(EBP, (kParamEndSlotFromFp + 839 __ leal(EAX,
811 function().NumParameters()) * kWordSize)); 840 Address(EBP, (kParamEndSlotFromFp + function().NumParameters()) *
841 kWordSize));
812 } else { 842 } else {
813 __ leal(EAX, Address(EBP, kFirstLocalSlotFromFp * kWordSize)); 843 __ leal(EAX, Address(EBP, kFirstLocalSlotFromFp * kWordSize));
814 } 844 }
815 __ movl(EDX, Immediate(argc_tag)); 845 __ movl(EDX, Immediate(argc_tag));
816 846
817 const StubEntry* stub_entry; 847 const StubEntry* stub_entry;
818 if (link_lazily()) { 848 if (link_lazily()) {
819 stub_entry = StubCode::CallBootstrapCFunction_entry(); 849 stub_entry = StubCode::CallBootstrapCFunction_entry();
820 __ movl(ECX, Immediate(NativeEntry::LinkNativeCallEntry())); 850 __ movl(ECX, Immediate(NativeEntry::LinkNativeCallEntry()));
821 } else { 851 } else {
822 stub_entry = (is_bootstrap_native()) ? 852 stub_entry = (is_bootstrap_native())
823 StubCode::CallBootstrapCFunction_entry() : 853 ? StubCode::CallBootstrapCFunction_entry()
824 StubCode::CallNativeCFunction_entry(); 854 : StubCode::CallNativeCFunction_entry();
825 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); 855 const ExternalLabel label(reinterpret_cast<uword>(native_c_function()));
826 __ movl(ECX, Immediate(label.address())); 856 __ movl(ECX, Immediate(label.address()));
827 } 857 }
828 compiler->GenerateCall(token_pos(), 858 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
829 *stub_entry,
830 RawPcDescriptors::kOther,
831 locs()); 859 locs());
832 __ popl(result); 860 __ popl(result);
833 } 861 }
834 862
835 863
836 static bool CanBeImmediateIndex(Value* value, intptr_t cid) { 864 static bool CanBeImmediateIndex(Value* value, intptr_t cid) {
837 ConstantInstr* constant = value->definition()->AsConstant(); 865 ConstantInstr* constant = value->definition()->AsConstant();
838 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) { 866 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) {
839 return false; 867 return false;
840 } 868 }
841 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); 869 const int64_t index = Smi::Cast(constant->value()).AsInt64Value();
842 const intptr_t scale = Instance::ElementSizeFor(cid); 870 const intptr_t scale = Instance::ElementSizeFor(cid);
843 const intptr_t offset = Instance::DataOffsetFor(cid); 871 const intptr_t offset = Instance::DataOffsetFor(cid);
844 const int64_t displacement = index * scale + offset; 872 const int64_t displacement = index * scale + offset;
845 return Utils::IsInt(32, displacement); 873 return Utils::IsInt(32, displacement);
846 } 874 }
847 875
848 876
849 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( 877 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
850 Zone* zone, bool opt) const { 878 Zone* zone,
879 bool opt) const {
851 const intptr_t kNumInputs = 1; 880 const intptr_t kNumInputs = 1;
852 // TODO(fschneider): Allow immediate operands for the char code. 881 // TODO(fschneider): Allow immediate operands for the char code.
853 return LocationSummary::Make(zone, 882 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(),
854 kNumInputs,
855 Location::RequiresRegister(),
856 LocationSummary::kNoCall); 883 LocationSummary::kNoCall);
857 } 884 }
858 885
859 886
860 void OneByteStringFromCharCodeInstr::EmitNativeCode( 887 void OneByteStringFromCharCodeInstr::EmitNativeCode(
861 FlowGraphCompiler* compiler) { 888 FlowGraphCompiler* compiler) {
862 Register char_code = locs()->in(0).reg(); 889 Register char_code = locs()->in(0).reg();
863 Register result = locs()->out(0).reg(); 890 Register result = locs()->out(0).reg();
864 __ movl(result, 891 __ movl(result,
865 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress()))); 892 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress())));
866 __ movl(result, Address(result, 893 __ movl(result, Address(result, char_code,
867 char_code,
868 TIMES_HALF_WORD_SIZE, // Char code is a smi. 894 TIMES_HALF_WORD_SIZE, // Char code is a smi.
869 Symbols::kNullCharCodeSymbolOffset * kWordSize)); 895 Symbols::kNullCharCodeSymbolOffset * kWordSize));
870 } 896 }
871 897
872 898
873 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, 899 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone,
874 bool opt) const { 900 bool opt) const {
875 const intptr_t kNumInputs = 1; 901 const intptr_t kNumInputs = 1;
876 return LocationSummary::Make(zone, 902 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(),
877 kNumInputs,
878 Location::RequiresRegister(),
879 LocationSummary::kNoCall); 903 LocationSummary::kNoCall);
880 } 904 }
881 905
882 906
883 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 907 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
884 ASSERT(cid_ == kOneByteStringCid); 908 ASSERT(cid_ == kOneByteStringCid);
885 Register str = locs()->in(0).reg(); 909 Register str = locs()->in(0).reg();
886 Register result = locs()->out(0).reg(); 910 Register result = locs()->out(0).reg();
887 Label is_one, done; 911 Label is_one, done;
888 __ movl(result, FieldAddress(str, String::length_offset())); 912 __ movl(result, FieldAddress(str, String::length_offset()));
889 __ cmpl(result, Immediate(Smi::RawValue(1))); 913 __ cmpl(result, Immediate(Smi::RawValue(1)));
890 __ j(EQUAL, &is_one, Assembler::kNearJump); 914 __ j(EQUAL, &is_one, Assembler::kNearJump);
891 __ movl(result, Immediate(Smi::RawValue(-1))); 915 __ movl(result, Immediate(Smi::RawValue(-1)));
892 __ jmp(&done); 916 __ jmp(&done);
893 __ Bind(&is_one); 917 __ Bind(&is_one);
894 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); 918 __ movzxb(result, FieldAddress(str, OneByteString::data_offset()));
895 __ SmiTag(result); 919 __ SmiTag(result);
896 __ Bind(&done); 920 __ Bind(&done);
897 } 921 }
898 922
899 923
900 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, 924 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone,
901 bool opt) const { 925 bool opt) const {
902 const intptr_t kNumInputs = 1; 926 const intptr_t kNumInputs = 1;
903 const intptr_t kNumTemps = 0; 927 const intptr_t kNumTemps = 0;
904 LocationSummary* summary = new(zone) LocationSummary( 928 LocationSummary* summary = new (zone)
905 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 929 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
906 summary->set_in(0, Location::RegisterLocation(EAX)); 930 summary->set_in(0, Location::RegisterLocation(EAX));
907 summary->set_out(0, Location::RegisterLocation(EAX)); 931 summary->set_out(0, Location::RegisterLocation(EAX));
908 return summary; 932 return summary;
909 } 933 }
910 934
911 935
912 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 936 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
913 Register array = locs()->in(0).reg(); 937 Register array = locs()->in(0).reg();
914 __ pushl(array); 938 __ pushl(array);
915 const int kNumberOfArguments = 1; 939 const int kNumberOfArguments = 1;
916 const Array& kNoArgumentNames = Object::null_array(); 940 const Array& kNoArgumentNames = Object::null_array();
917 compiler->GenerateStaticCall(deopt_id(), 941 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
918 token_pos(), 942 kNumberOfArguments, kNoArgumentNames, locs(),
919 CallFunction(),
920 kNumberOfArguments,
921 kNoArgumentNames,
922 locs(),
923 ICData::Handle()); 943 ICData::Handle());
924 ASSERT(locs()->out(0).reg() == EAX); 944 ASSERT(locs()->out(0).reg() == EAX);
925 } 945 }
926 946
927 947
928 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, 948 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone,
929 bool opt) const { 949 bool opt) const {
930 const intptr_t kNumInputs = 1; 950 const intptr_t kNumInputs = 1;
931 return LocationSummary::Make(zone, 951 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(),
932 kNumInputs,
933 Location::SameAsFirstInput(),
934 LocationSummary::kNoCall); 952 LocationSummary::kNoCall);
935 } 953 }
936 954
937 955
938 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 956 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
939 Register obj = locs()->in(0).reg(); 957 Register obj = locs()->in(0).reg();
940 Register result = locs()->out(0).reg(); 958 Register result = locs()->out(0).reg();
941 if (object()->definition()->representation() == kUntagged) { 959 if (object()->definition()->representation() == kUntagged) {
942 __ movl(result, Address(obj, offset())); 960 __ movl(result, Address(obj, offset()));
943 } else { 961 } else {
944 ASSERT(object()->definition()->representation() == kTagged); 962 ASSERT(object()->definition()->representation() == kTagged);
945 __ movl(result, FieldAddress(obj, offset())); 963 __ movl(result, FieldAddress(obj, offset()));
946 } 964 }
947 } 965 }
948 966
949 967
950 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, 968 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone,
951 bool opt) const { 969 bool opt) const {
952 const intptr_t kNumInputs = 1; 970 const intptr_t kNumInputs = 1;
953 return LocationSummary::Make(zone, 971 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(),
954 kNumInputs,
955 Location::RequiresRegister(),
956 LocationSummary::kNoCall); 972 LocationSummary::kNoCall);
957 } 973 }
958 974
959 975
960 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 976 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
961 const Register object = locs()->in(0).reg(); 977 const Register object = locs()->in(0).reg();
962 const Register result = locs()->out(0).reg(); 978 const Register result = locs()->out(0).reg();
963 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); 979 const AbstractType& value_type = *this->object()->Type()->ToAbstractType();
964 if (CompileType::Smi().IsAssignableTo(value_type) || 980 if (CompileType::Smi().IsAssignableTo(value_type) ||
965 value_type.IsTypeParameter()) { 981 value_type.IsTypeParameter()) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 UNIMPLEMENTED(); 1071 UNIMPLEMENTED();
1056 return kTagged; 1072 return kTagged;
1057 } 1073 }
1058 } 1074 }
1059 1075
1060 1076
1061 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, 1077 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone,
1062 bool opt) const { 1078 bool opt) const {
1063 const intptr_t kNumInputs = 2; 1079 const intptr_t kNumInputs = 2;
1064 const intptr_t kNumTemps = 0; 1080 const intptr_t kNumTemps = 0;
1065 LocationSummary* locs = new(zone) LocationSummary( 1081 LocationSummary* locs = new (zone)
1066 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 1082 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
1067 locs->set_in(0, Location::RequiresRegister()); 1083 locs->set_in(0, Location::RequiresRegister());
1068 if (CanBeImmediateIndex(index(), class_id())) { 1084 if (CanBeImmediateIndex(index(), class_id())) {
1069 // CanBeImmediateIndex must return false for unsafe smis. 1085 // CanBeImmediateIndex must return false for unsafe smis.
1070 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); 1086 locs->set_in(1, Location::Constant(index()->definition()->AsConstant()));
1071 } else { 1087 } else {
1072 // The index is either untagged (element size == 1) or a smi (for all 1088 // The index is either untagged (element size == 1) or a smi (for all
1073 // element sizes > 1). 1089 // element sizes > 1).
1074 locs->set_in(1, (index_scale() == 1) 1090 locs->set_in(1, (index_scale() == 1) ? Location::WritableRegister()
1075 ? Location::WritableRegister() 1091 : Location::RequiresRegister());
1076 : Location::RequiresRegister());
1077 } 1092 }
1078 if ((representation() == kUnboxedDouble) || 1093 if ((representation() == kUnboxedDouble) ||
1079 (representation() == kUnboxedFloat32x4) || 1094 (representation() == kUnboxedFloat32x4) ||
1080 (representation() == kUnboxedInt32x4) || 1095 (representation() == kUnboxedInt32x4) ||
1081 (representation() == kUnboxedFloat64x2)) { 1096 (representation() == kUnboxedFloat64x2)) {
1082 locs->set_out(0, Location::RequiresFpuRegister()); 1097 locs->set_out(0, Location::RequiresFpuRegister());
1083 } else if (representation() == kUnboxedUint32) { 1098 } else if (representation() == kUnboxedUint32) {
1084 ASSERT(class_id() == kTypedDataUint32ArrayCid); 1099 ASSERT(class_id() == kTypedDataUint32ArrayCid);
1085 locs->set_out(0, Location::RequiresRegister()); 1100 locs->set_out(0, Location::RequiresRegister());
1086 } else if (representation() == kUnboxedInt32) { 1101 } else if (representation() == kUnboxedInt32) {
1087 ASSERT(class_id() == kTypedDataInt32ArrayCid); 1102 ASSERT(class_id() == kTypedDataInt32ArrayCid);
1088 locs->set_out(0, Location::RequiresRegister()); 1103 locs->set_out(0, Location::RequiresRegister());
1089 } else { 1104 } else {
1090 ASSERT(representation() == kTagged); 1105 ASSERT(representation() == kTagged);
1091 locs->set_out(0, Location::RequiresRegister()); 1106 locs->set_out(0, Location::RequiresRegister());
1092 } 1107 }
1093 return locs; 1108 return locs;
1094 } 1109 }
1095 1110
1096 1111
1097 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1112 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1098 // The array register points to the backing store for external arrays. 1113 // The array register points to the backing store for external arrays.
1099 const Register array = locs()->in(0).reg(); 1114 const Register array = locs()->in(0).reg();
1100 const Location index = locs()->in(1); 1115 const Location index = locs()->in(1);
1101 1116
1102 Address element_address = index.IsRegister() 1117 Address element_address =
1103 ? Assembler::ElementAddressForRegIndex( 1118 index.IsRegister()
1104 IsExternal(), class_id(), index_scale(), array, index.reg()) 1119 ? Assembler::ElementAddressForRegIndex(
1105 : Assembler::ElementAddressForIntIndex( 1120 IsExternal(), class_id(), index_scale(), array, index.reg())
1106 IsExternal(), class_id(), index_scale(), 1121 : Assembler::ElementAddressForIntIndex(
1107 array, Smi::Cast(index.constant()).Value()); 1122 IsExternal(), class_id(), index_scale(), array,
1123 Smi::Cast(index.constant()).Value());
1108 1124
1109 if ((representation() == kUnboxedDouble) || 1125 if ((representation() == kUnboxedDouble) ||
1110 (representation() == kUnboxedFloat32x4) || 1126 (representation() == kUnboxedFloat32x4) ||
1111 (representation() == kUnboxedInt32x4) || 1127 (representation() == kUnboxedInt32x4) ||
1112 (representation() == kUnboxedFloat64x2)) { 1128 (representation() == kUnboxedFloat64x2)) {
1113 XmmRegister result = locs()->out(0).fpu_reg(); 1129 XmmRegister result = locs()->out(0).fpu_reg();
1114 if ((index_scale() == 1) && index.IsRegister()) { 1130 if ((index_scale() == 1) && index.IsRegister()) {
1115 __ SmiUntag(index.reg()); 1131 __ SmiUntag(index.reg());
1116 } 1132 }
1117 switch (class_id()) { 1133 switch (class_id()) {
(...skipping 17 matching lines...) Expand all
1135 if ((representation() == kUnboxedUint32) || 1151 if ((representation() == kUnboxedUint32) ||
1136 (representation() == kUnboxedInt32)) { 1152 (representation() == kUnboxedInt32)) {
1137 Register result = locs()->out(0).reg(); 1153 Register result = locs()->out(0).reg();
1138 if ((index_scale() == 1) && index.IsRegister()) { 1154 if ((index_scale() == 1) && index.IsRegister()) {
1139 __ SmiUntag(index.reg()); 1155 __ SmiUntag(index.reg());
1140 } 1156 }
1141 switch (class_id()) { 1157 switch (class_id()) {
1142 case kTypedDataInt32ArrayCid: 1158 case kTypedDataInt32ArrayCid:
1143 ASSERT(representation() == kUnboxedInt32); 1159 ASSERT(representation() == kUnboxedInt32);
1144 __ movl(result, element_address); 1160 __ movl(result, element_address);
1145 break; 1161 break;
1146 case kTypedDataUint32ArrayCid: 1162 case kTypedDataUint32ArrayCid:
1147 ASSERT(representation() == kUnboxedUint32); 1163 ASSERT(representation() == kUnboxedUint32);
1148 __ movl(result, element_address); 1164 __ movl(result, element_address);
1149 break; 1165 break;
1150 default: 1166 default:
1151 UNREACHABLE(); 1167 UNREACHABLE();
1152 } 1168 }
1153 return; 1169 return;
1154 } 1170 }
1155 1171
1156 ASSERT(representation() == kTagged); 1172 ASSERT(representation() == kTagged);
1157 1173
1158 Register result = locs()->out(0).reg(); 1174 Register result = locs()->out(0).reg();
1159 if ((index_scale() == 1) && index.IsRegister()) { 1175 if ((index_scale() == 1) && index.IsRegister()) {
(...skipping 29 matching lines...) Expand all
1189 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); 1205 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
1190 __ movl(result, element_address); 1206 __ movl(result, element_address);
1191 break; 1207 break;
1192 } 1208 }
1193 } 1209 }
1194 1210
1195 1211
1196 Representation StoreIndexedInstr::RequiredInputRepresentation( 1212 Representation StoreIndexedInstr::RequiredInputRepresentation(
1197 intptr_t idx) const { 1213 intptr_t idx) const {
1198 // Array can be a Dart object or a pointer to external data. 1214 // Array can be a Dart object or a pointer to external data.
1199 if (idx == 0) return kNoRepresentation; // Flexible input representation. 1215 if (idx == 0) return kNoRepresentation; // Flexible input representation.
1200 if (idx == 1) return kTagged; // Index is a smi. 1216 if (idx == 1) return kTagged; // Index is a smi.
1201 ASSERT(idx == 2); 1217 ASSERT(idx == 2);
1202 switch (class_id_) { 1218 switch (class_id_) {
1203 case kArrayCid: 1219 case kArrayCid:
1204 case kOneByteStringCid: 1220 case kOneByteStringCid:
1205 case kTypedDataInt8ArrayCid: 1221 case kTypedDataInt8ArrayCid:
1206 case kTypedDataUint8ArrayCid: 1222 case kTypedDataUint8ArrayCid:
1207 case kExternalTypedDataUint8ArrayCid: 1223 case kExternalTypedDataUint8ArrayCid:
1208 case kTypedDataUint8ClampedArrayCid: 1224 case kTypedDataUint8ClampedArrayCid:
1209 case kExternalTypedDataUint8ClampedArrayCid: 1225 case kExternalTypedDataUint8ClampedArrayCid:
1210 case kTypedDataInt16ArrayCid: 1226 case kTypedDataInt16ArrayCid:
(...skipping 16 matching lines...) Expand all
1227 UNIMPLEMENTED(); 1243 UNIMPLEMENTED();
1228 return kTagged; 1244 return kTagged;
1229 } 1245 }
1230 } 1246 }
1231 1247
1232 1248
1233 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, 1249 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
1234 bool opt) const { 1250 bool opt) const {
1235 const intptr_t kNumInputs = 3; 1251 const intptr_t kNumInputs = 3;
1236 const intptr_t kNumTemps = 0; 1252 const intptr_t kNumTemps = 0;
1237 LocationSummary* locs = new(zone) LocationSummary( 1253 LocationSummary* locs = new (zone)
1238 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 1254 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
1239 locs->set_in(0, Location::RequiresRegister()); 1255 locs->set_in(0, Location::RequiresRegister());
1240 if (CanBeImmediateIndex(index(), class_id())) { 1256 if (CanBeImmediateIndex(index(), class_id())) {
1241 // CanBeImmediateIndex must return false for unsafe smis. 1257 // CanBeImmediateIndex must return false for unsafe smis.
1242 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); 1258 locs->set_in(1, Location::Constant(index()->definition()->AsConstant()));
1243 } else { 1259 } else {
1244 // The index is either untagged (element size == 1) or a smi (for all 1260 // The index is either untagged (element size == 1) or a smi (for all
1245 // element sizes > 1). 1261 // element sizes > 1).
1246 locs->set_in(1, (index_scale() == 1) 1262 locs->set_in(1, (index_scale() == 1) ? Location::WritableRegister()
1247 ? Location::WritableRegister() 1263 : Location::RequiresRegister());
1248 : Location::RequiresRegister());
1249 } 1264 }
1250 switch (class_id()) { 1265 switch (class_id()) {
1251 case kArrayCid: 1266 case kArrayCid:
1252 locs->set_in(2, ShouldEmitStoreBarrier() 1267 locs->set_in(2, ShouldEmitStoreBarrier()
1253 ? Location::WritableRegister() 1268 ? Location::WritableRegister()
1254 : Location::RegisterOrConstant(value())); 1269 : Location::RegisterOrConstant(value()));
1255 break; 1270 break;
1256 case kExternalTypedDataUint8ArrayCid: 1271 case kExternalTypedDataUint8ArrayCid:
1257 case kExternalTypedDataUint8ClampedArrayCid: 1272 case kExternalTypedDataUint8ClampedArrayCid:
1258 case kTypedDataInt8ArrayCid: 1273 case kTypedDataInt8ArrayCid:
1259 case kTypedDataUint8ArrayCid: 1274 case kTypedDataUint8ArrayCid:
1260 case kTypedDataUint8ClampedArrayCid: 1275 case kTypedDataUint8ClampedArrayCid:
1261 case kOneByteStringCid: 1276 case kOneByteStringCid:
1262 // TODO(fschneider): Add location constraint for byte registers (EAX, 1277 // TODO(fschneider): Add location constraint for byte registers (EAX,
1263 // EBX, ECX, EDX) instead of using a fixed register. 1278 // EBX, ECX, EDX) instead of using a fixed register.
1264 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); 1279 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX));
(...skipping 23 matching lines...) Expand all
1288 } 1303 }
1289 return locs; 1304 return locs;
1290 } 1305 }
1291 1306
1292 1307
1293 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1308 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1294 // The array register points to the backing store for external arrays. 1309 // The array register points to the backing store for external arrays.
1295 const Register array = locs()->in(0).reg(); 1310 const Register array = locs()->in(0).reg();
1296 const Location index = locs()->in(1); 1311 const Location index = locs()->in(1);
1297 1312
1298 Address element_address = index.IsRegister() 1313 Address element_address =
1299 ? Assembler::ElementAddressForRegIndex( 1314 index.IsRegister()
1300 IsExternal(), class_id(), index_scale(), array, index.reg()) 1315 ? Assembler::ElementAddressForRegIndex(
1301 : Assembler::ElementAddressForIntIndex( 1316 IsExternal(), class_id(), index_scale(), array, index.reg())
1302 IsExternal(), class_id(), index_scale(), 1317 : Assembler::ElementAddressForIntIndex(
1303 array, Smi::Cast(index.constant()).Value()); 1318 IsExternal(), class_id(), index_scale(), array,
1319 Smi::Cast(index.constant()).Value());
1304 1320
1305 if ((index_scale() == 1) && index.IsRegister()) { 1321 if ((index_scale() == 1) && index.IsRegister()) {
1306 __ SmiUntag(index.reg()); 1322 __ SmiUntag(index.reg());
1307 } 1323 }
1308 switch (class_id()) { 1324 switch (class_id()) {
1309 case kArrayCid: 1325 case kArrayCid:
1310 if (ShouldEmitStoreBarrier()) { 1326 if (ShouldEmitStoreBarrier()) {
1311 Register value = locs()->in(2).reg(); 1327 Register value = locs()->in(2).reg();
1312 __ StoreIntoObject(array, element_address, value); 1328 __ StoreIntoObject(array, element_address, value);
1313 } else if (locs()->in(2).IsConstant()) { 1329 } else if (locs()->in(2).IsConstant()) {
(...skipping 22 matching lines...) Expand all
1336 case kExternalTypedDataUint8ClampedArrayCid: { 1352 case kExternalTypedDataUint8ClampedArrayCid: {
1337 if (locs()->in(2).IsConstant()) { 1353 if (locs()->in(2).IsConstant()) {
1338 const Smi& constant = Smi::Cast(locs()->in(2).constant()); 1354 const Smi& constant = Smi::Cast(locs()->in(2).constant());
1339 intptr_t value = constant.Value(); 1355 intptr_t value = constant.Value();
1340 // Clamp to 0x0 or 0xFF respectively. 1356 // Clamp to 0x0 or 0xFF respectively.
1341 if (value > 0xFF) { 1357 if (value > 0xFF) {
1342 value = 0xFF; 1358 value = 0xFF;
1343 } else if (value < 0) { 1359 } else if (value < 0) {
1344 value = 0; 1360 value = 0;
1345 } 1361 }
1346 __ movb(element_address, 1362 __ movb(element_address, Immediate(static_cast<int8_t>(value)));
1347 Immediate(static_cast<int8_t>(value)));
1348 } else { 1363 } else {
1349 ASSERT(locs()->in(2).reg() == EAX); 1364 ASSERT(locs()->in(2).reg() == EAX);
1350 Label store_value, store_0xff; 1365 Label store_value, store_0xff;
1351 __ SmiUntag(EAX); 1366 __ SmiUntag(EAX);
1352 __ cmpl(EAX, Immediate(0xFF)); 1367 __ cmpl(EAX, Immediate(0xFF));
1353 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); 1368 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump);
1354 // Clamp to 0x0 or 0xFF respectively. 1369 // Clamp to 0x0 or 0xFF respectively.
1355 __ j(GREATER, &store_0xff); 1370 __ j(GREATER, &store_0xff);
1356 __ xorl(EAX, EAX); 1371 __ xorl(EAX, EAX);
1357 __ jmp(&store_value, Assembler::kNearJump); 1372 __ jmp(&store_value, Assembler::kNearJump);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1392 1407
1393 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, 1408 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone,
1394 bool opt) const { 1409 bool opt) const {
1395 const intptr_t kNumInputs = 1; 1410 const intptr_t kNumInputs = 1;
1396 1411
1397 const intptr_t value_cid = value()->Type()->ToCid(); 1412 const intptr_t value_cid = value()->Type()->ToCid();
1398 const intptr_t field_cid = field().guarded_cid(); 1413 const intptr_t field_cid = field().guarded_cid();
1399 1414
1400 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); 1415 const bool emit_full_guard = !opt || (field_cid == kIllegalCid);
1401 const bool needs_value_cid_temp_reg = 1416 const bool needs_value_cid_temp_reg =
1402 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); 1417 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
1403 const bool needs_field_temp_reg = emit_full_guard; 1418 const bool needs_field_temp_reg = emit_full_guard;
1404 1419
1405 intptr_t num_temps = 0; 1420 intptr_t num_temps = 0;
1406 if (needs_value_cid_temp_reg) { 1421 if (needs_value_cid_temp_reg) {
1407 num_temps++; 1422 num_temps++;
1408 } 1423 }
1409 if (needs_field_temp_reg) { 1424 if (needs_field_temp_reg) {
1410 num_temps++; 1425 num_temps++;
1411 } 1426 }
1412 1427
1413 LocationSummary* summary = new(zone) LocationSummary( 1428 LocationSummary* summary = new (zone)
1414 zone, kNumInputs, num_temps, LocationSummary::kNoCall); 1429 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall);
1415 summary->set_in(0, Location::RequiresRegister()); 1430 summary->set_in(0, Location::RequiresRegister());
1416 1431
1417 for (intptr_t i = 0; i < num_temps; i++) { 1432 for (intptr_t i = 0; i < num_temps; i++) {
1418 summary->set_temp(i, Location::RequiresRegister()); 1433 summary->set_temp(i, Location::RequiresRegister());
1419 } 1434 }
1420 1435
1421 return summary; 1436 return summary;
1422 } 1437 }
1423 1438
1424 1439
1425 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1440 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1426 ASSERT(sizeof(classid_t) == kInt16Size); 1441 ASSERT(sizeof(classid_t) == kInt16Size);
1427 const intptr_t value_cid = value()->Type()->ToCid(); 1442 const intptr_t value_cid = value()->Type()->ToCid();
1428 const intptr_t field_cid = field().guarded_cid(); 1443 const intptr_t field_cid = field().guarded_cid();
1429 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; 1444 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
1430 1445
1431 if (field_cid == kDynamicCid) { 1446 if (field_cid == kDynamicCid) {
1432 if (Compiler::IsBackgroundCompilation()) { 1447 if (Compiler::IsBackgroundCompilation()) {
1433 // Field state changed while compiling. 1448 // Field state changed while compiling.
1434 Compiler::AbortBackgroundCompilation(deopt_id(), 1449 Compiler::AbortBackgroundCompilation(
1450 deopt_id(),
1435 "GuardFieldClassInstr: field state changed while compiling"); 1451 "GuardFieldClassInstr: field state changed while compiling");
1436 } 1452 }
1437 ASSERT(!compiler->is_optimizing()); 1453 ASSERT(!compiler->is_optimizing());
1438 return; // Nothing to emit. 1454 return; // Nothing to emit.
1439 } 1455 }
1440 1456
1441 const bool emit_full_guard = 1457 const bool emit_full_guard =
1442 !compiler->is_optimizing() || (field_cid == kIllegalCid); 1458 !compiler->is_optimizing() || (field_cid == kIllegalCid);
1443 1459
1444 const bool needs_value_cid_temp_reg = 1460 const bool needs_value_cid_temp_reg =
1445 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); 1461 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
1446 1462
1447 const bool needs_field_temp_reg = emit_full_guard; 1463 const bool needs_field_temp_reg = emit_full_guard;
1448 1464
1449 const Register value_reg = locs()->in(0).reg(); 1465 const Register value_reg = locs()->in(0).reg();
1450 1466
1451 const Register value_cid_reg = needs_value_cid_temp_reg ? 1467 const Register value_cid_reg =
1452 locs()->temp(0).reg() : kNoRegister; 1468 needs_value_cid_temp_reg ? locs()->temp(0).reg() : kNoRegister;
1453 1469
1454 const Register field_reg = needs_field_temp_reg ? 1470 const Register field_reg = needs_field_temp_reg
1455 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; 1471 ? locs()->temp(locs()->temp_count() - 1).reg()
1472 : kNoRegister;
1456 1473
1457 Label ok, fail_label; 1474 Label ok, fail_label;
1458 1475
1459 Label* deopt = compiler->is_optimizing() ? 1476 Label* deopt =
1460 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; 1477 compiler->is_optimizing()
1478 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField)
1479 : NULL;
1461 1480
1462 Label* fail = (deopt != NULL) ? deopt : &fail_label; 1481 Label* fail = (deopt != NULL) ? deopt : &fail_label;
1463 1482
1464 if (emit_full_guard) { 1483 if (emit_full_guard) {
1465 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); 1484 __ LoadObject(field_reg, Field::ZoneHandle(field().Original()));
1466 1485
1467 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); 1486 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
1468 FieldAddress field_nullability_operand( 1487 FieldAddress field_nullability_operand(field_reg,
1469 field_reg, Field::is_nullable_offset()); 1488 Field::is_nullable_offset());
1470 1489
1471 if (value_cid == kDynamicCid) { 1490 if (value_cid == kDynamicCid) {
1472 LoadValueCid(compiler, value_cid_reg, value_reg); 1491 LoadValueCid(compiler, value_cid_reg, value_reg);
1473 __ cmpw(value_cid_reg, field_cid_operand); 1492 __ cmpw(value_cid_reg, field_cid_operand);
1474 __ j(EQUAL, &ok); 1493 __ j(EQUAL, &ok);
1475 __ cmpw(value_cid_reg, field_nullability_operand); 1494 __ cmpw(value_cid_reg, field_nullability_operand);
1476 } else if (value_cid == kNullCid) { 1495 } else if (value_cid == kNullCid) {
1477 // Value in graph known to be null. 1496 // Value in graph known to be null.
1478 // Compare with null. 1497 // Compare with null.
1479 __ cmpw(field_nullability_operand, Immediate(value_cid)); 1498 __ cmpw(field_nullability_operand, Immediate(value_cid));
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1562 } 1581 }
1563 __ Bind(&ok); 1582 __ Bind(&ok);
1564 } 1583 }
1565 1584
1566 1585
1567 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, 1586 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone,
1568 bool opt) const { 1587 bool opt) const {
1569 const intptr_t kNumInputs = 1; 1588 const intptr_t kNumInputs = 1;
1570 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { 1589 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) {
1571 const intptr_t kNumTemps = 3; 1590 const intptr_t kNumTemps = 3;
1572 LocationSummary* summary = new(zone) LocationSummary( 1591 LocationSummary* summary = new (zone)
1573 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 1592 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
1574 summary->set_in(0, Location::RequiresRegister()); 1593 summary->set_in(0, Location::RequiresRegister());
1575 // We need temporaries for field object, length offset and expected length. 1594 // We need temporaries for field object, length offset and expected length.
1576 summary->set_temp(0, Location::RequiresRegister()); 1595 summary->set_temp(0, Location::RequiresRegister());
1577 summary->set_temp(1, Location::RequiresRegister()); 1596 summary->set_temp(1, Location::RequiresRegister());
1578 summary->set_temp(2, Location::RequiresRegister()); 1597 summary->set_temp(2, Location::RequiresRegister());
1579 return summary; 1598 return summary;
1580 } else { 1599 } else {
1581 LocationSummary* summary = new(zone) LocationSummary( 1600 LocationSummary* summary = new (zone)
1582 zone, kNumInputs, 0, LocationSummary::kNoCall); 1601 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall);
1583 summary->set_in(0, Location::RequiresRegister()); 1602 summary->set_in(0, Location::RequiresRegister());
1584 return summary; 1603 return summary;
1585 } 1604 }
1586 UNREACHABLE(); 1605 UNREACHABLE();
1587 } 1606 }
1588 1607
1589 1608
1590 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1609 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1591 if (field().guarded_list_length() == Field::kNoFixedLength) { 1610 if (field().guarded_list_length() == Field::kNoFixedLength) {
1592 if (Compiler::IsBackgroundCompilation()) { 1611 if (Compiler::IsBackgroundCompilation()) {
1593 // Field state changed while compiling. 1612 // Field state changed while compiling.
1594 Compiler::AbortBackgroundCompilation(deopt_id(), 1613 Compiler::AbortBackgroundCompilation(
1614 deopt_id(),
1595 "GuardFieldLengthInstr: field state changed while compiling"); 1615 "GuardFieldLengthInstr: field state changed while compiling");
1596 } 1616 }
1597 ASSERT(!compiler->is_optimizing()); 1617 ASSERT(!compiler->is_optimizing());
1598 return; // Nothing to emit. 1618 return; // Nothing to emit.
1599 } 1619 }
1600 1620
1601 Label* deopt = compiler->is_optimizing() ? 1621 Label* deopt =
1602 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; 1622 compiler->is_optimizing()
1623 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField)
1624 : NULL;
1603 1625
1604 const Register value_reg = locs()->in(0).reg(); 1626 const Register value_reg = locs()->in(0).reg();
1605 1627
1606 if (!compiler->is_optimizing() || 1628 if (!compiler->is_optimizing() ||
1607 (field().guarded_list_length() == Field::kUnknownFixedLength)) { 1629 (field().guarded_list_length() == Field::kUnknownFixedLength)) {
1608 const Register field_reg = locs()->temp(0).reg(); 1630 const Register field_reg = locs()->temp(0).reg();
1609 const Register offset_reg = locs()->temp(1).reg(); 1631 const Register offset_reg = locs()->temp(1).reg();
1610 const Register length_reg = locs()->temp(2).reg(); 1632 const Register length_reg = locs()->temp(2).reg();
1611 1633
1612 Label ok; 1634 Label ok;
1613 1635
1614 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); 1636 __ LoadObject(field_reg, Field::ZoneHandle(field().Original()));
1615 1637
1616 __ movsxb(offset_reg, FieldAddress(field_reg, 1638 __ movsxb(
1617 Field::guarded_list_length_in_object_offset_offset())); 1639 offset_reg,
1618 __ movl(length_reg, FieldAddress(field_reg, 1640 FieldAddress(field_reg,
1619 Field::guarded_list_length_offset())); 1641 Field::guarded_list_length_in_object_offset_offset()));
1642 __ movl(length_reg,
1643 FieldAddress(field_reg, Field::guarded_list_length_offset()));
1620 1644
1621 __ cmpl(offset_reg, Immediate(0)); 1645 __ cmpl(offset_reg, Immediate(0));
1622 __ j(NEGATIVE, &ok); 1646 __ j(NEGATIVE, &ok);
1623 1647
1624 // Load the length from the value. GuardFieldClass already verified that 1648 // Load the length from the value. GuardFieldClass already verified that
1625 // value's class matches guarded class id of the field. 1649 // value's class matches guarded class id of the field.
1626 // offset_reg contains offset already corrected by -kHeapObjectTag that is 1650 // offset_reg contains offset already corrected by -kHeapObjectTag that is
1627 // why we use Address instead of FieldAddress. 1651 // why we use Address instead of FieldAddress.
1628 __ cmpl(length_reg, Address(value_reg, offset_reg, TIMES_1, 0)); 1652 __ cmpl(length_reg, Address(value_reg, offset_reg, TIMES_1, 0));
1629 1653
1630 if (deopt == NULL) { 1654 if (deopt == NULL) {
1631 __ j(EQUAL, &ok); 1655 __ j(EQUAL, &ok);
1632 1656
1633 __ pushl(field_reg); 1657 __ pushl(field_reg);
1634 __ pushl(value_reg); 1658 __ pushl(value_reg);
1635 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); 1659 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
1636 __ Drop(2); // Drop the field and the value. 1660 __ Drop(2); // Drop the field and the value.
1637 } else { 1661 } else {
1638 __ j(NOT_EQUAL, deopt); 1662 __ j(NOT_EQUAL, deopt);
1639 } 1663 }
1640 1664
1641 __ Bind(&ok); 1665 __ Bind(&ok);
1642 } else { 1666 } else {
1643 ASSERT(compiler->is_optimizing()); 1667 ASSERT(compiler->is_optimizing());
1644 ASSERT(field().guarded_list_length() >= 0); 1668 ASSERT(field().guarded_list_length() >= 0);
1645 ASSERT(field().guarded_list_length_in_object_offset() != 1669 ASSERT(field().guarded_list_length_in_object_offset() !=
1646 Field::kUnknownLengthOffset); 1670 Field::kUnknownLengthOffset);
1647 1671
1648 __ cmpl(FieldAddress(value_reg, 1672 __ cmpl(
1649 field().guarded_list_length_in_object_offset()), 1673 FieldAddress(value_reg, field().guarded_list_length_in_object_offset()),
1650 Immediate(Smi::RawValue(field().guarded_list_length()))); 1674 Immediate(Smi::RawValue(field().guarded_list_length())));
1651 __ j(NOT_EQUAL, deopt); 1675 __ j(NOT_EQUAL, deopt);
1652 } 1676 }
1653 } 1677 }
1654 1678
1655 1679
1656 class BoxAllocationSlowPath : public SlowPathCode { 1680 class BoxAllocationSlowPath : public SlowPathCode {
1657 public: 1681 public:
1658 BoxAllocationSlowPath(Instruction* instruction, 1682 BoxAllocationSlowPath(Instruction* instruction,
1659 const Class& cls, 1683 const Class& cls,
1660 Register result) 1684 Register result)
1661 : instruction_(instruction), 1685 : instruction_(instruction), cls_(cls), result_(result) {}
1662 cls_(cls),
1663 result_(result) { }
1664 1686
1665 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 1687 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
1666 if (Assembler::EmittingComments()) { 1688 if (Assembler::EmittingComments()) {
1667 __ Comment("%s slow path allocation of %s", 1689 __ Comment("%s slow path allocation of %s", instruction_->DebugName(),
1668 instruction_->DebugName(),
1669 String::Handle(cls_.ScrubbedName()).ToCString()); 1690 String::Handle(cls_.ScrubbedName()).ToCString());
1670 } 1691 }
1671 __ Bind(entry_label()); 1692 __ Bind(entry_label());
1672 const Code& stub = Code::ZoneHandle( 1693 const Code& stub = Code::ZoneHandle(
1673 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); 1694 compiler->zone(), StubCode::GetAllocationStubForClass(cls_));
1674 const StubEntry stub_entry(stub); 1695 const StubEntry stub_entry(stub);
1675 1696
1676 LocationSummary* locs = instruction_->locs(); 1697 LocationSummary* locs = instruction_->locs();
1677 1698
1678 locs->live_registers()->Remove(Location::RegisterLocation(result_)); 1699 locs->live_registers()->Remove(Location::RegisterLocation(result_));
1679 1700
1680 compiler->SaveLiveRegisters(locs); 1701 compiler->SaveLiveRegisters(locs);
1681 compiler->GenerateCall(TokenPosition::kNoSource, 1702 compiler->GenerateCall(TokenPosition::kNoSource, stub_entry,
1682 stub_entry, 1703 RawPcDescriptors::kOther, locs);
1683 RawPcDescriptors::kOther,
1684 locs);
1685 compiler->AddStubCallTarget(stub); 1704 compiler->AddStubCallTarget(stub);
1686 __ MoveRegister(result_, EAX); 1705 __ MoveRegister(result_, EAX);
1687 compiler->RestoreLiveRegisters(locs); 1706 compiler->RestoreLiveRegisters(locs);
1688 __ jmp(exit_label()); 1707 __ jmp(exit_label());
1689 } 1708 }
1690 1709
1691 static void Allocate(FlowGraphCompiler* compiler, 1710 static void Allocate(FlowGraphCompiler* compiler,
1692 Instruction* instruction, 1711 Instruction* instruction,
1693 const Class& cls, 1712 const Class& cls,
1694 Register result, 1713 Register result,
1695 Register temp) { 1714 Register temp) {
1696 if (compiler->intrinsic_mode()) { 1715 if (compiler->intrinsic_mode()) {
1697 __ TryAllocate(cls, 1716 __ TryAllocate(cls, compiler->intrinsic_slow_path_label(),
1698 compiler->intrinsic_slow_path_label(), 1717 Assembler::kFarJump, result, temp);
1699 Assembler::kFarJump,
1700 result,
1701 temp);
1702 } else { 1718 } else {
1703 BoxAllocationSlowPath* slow_path = 1719 BoxAllocationSlowPath* slow_path =
1704 new BoxAllocationSlowPath(instruction, cls, result); 1720 new BoxAllocationSlowPath(instruction, cls, result);
1705 compiler->AddSlowPathCode(slow_path); 1721 compiler->AddSlowPathCode(slow_path);
1706 1722
1707 __ TryAllocate(cls, 1723 __ TryAllocate(cls, slow_path->entry_label(), Assembler::kFarJump, result,
1708 slow_path->entry_label(),
1709 Assembler::kFarJump,
1710 result,
1711 temp); 1724 temp);
1712 __ Bind(slow_path->exit_label()); 1725 __ Bind(slow_path->exit_label());
1713 } 1726 }
1714 } 1727 }
1715 1728
1716 private: 1729 private:
1717 Instruction* instruction_; 1730 Instruction* instruction_;
1718 const Class& cls_; 1731 const Class& cls_;
1719 const Register result_; 1732 const Register result_;
1720 }; 1733 };
1721 1734
1722 1735
1723 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, 1736 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone,
1724 bool opt) const { 1737 bool opt) const {
1725 const intptr_t kNumInputs = 2; 1738 const intptr_t kNumInputs = 2;
1726 const intptr_t kNumTemps = 1739 const intptr_t kNumTemps =
1727 (IsUnboxedStore() && opt) ? 2 : 1740 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0);
1728 ((IsPotentialUnboxedStore()) ? 3 : 0); 1741 LocationSummary* summary = new (zone)
1729 LocationSummary* summary = new(zone) LocationSummary( 1742 LocationSummary(zone, kNumInputs, kNumTemps,
1730 zone, kNumInputs, kNumTemps, 1743 ((IsUnboxedStore() && opt && is_initialization()) ||
1731 ((IsUnboxedStore() && opt && is_initialization()) || 1744 IsPotentialUnboxedStore())
1732 IsPotentialUnboxedStore()) 1745 ? LocationSummary::kCallOnSlowPath
1733 ? LocationSummary::kCallOnSlowPath 1746 : LocationSummary::kNoCall);
1734 : LocationSummary::kNoCall);
1735 1747
1736 summary->set_in(0, Location::RequiresRegister()); 1748 summary->set_in(0, Location::RequiresRegister());
1737 if (IsUnboxedStore() && opt) { 1749 if (IsUnboxedStore() && opt) {
1738 summary->set_in(1, Location::RequiresFpuRegister()); 1750 summary->set_in(1, Location::RequiresFpuRegister());
1739 summary->set_temp(0, Location::RequiresRegister()); 1751 summary->set_temp(0, Location::RequiresRegister());
1740 summary->set_temp(1, Location::RequiresRegister()); 1752 summary->set_temp(1, Location::RequiresRegister());
1741 } else if (IsPotentialUnboxedStore()) { 1753 } else if (IsPotentialUnboxedStore()) {
1742 summary->set_in(1, ShouldEmitStoreBarrier() 1754 summary->set_in(1, ShouldEmitStoreBarrier() ? Location::WritableRegister()
1743 ? Location::WritableRegister() 1755 : Location::RequiresRegister());
1744 : Location::RequiresRegister());
1745 summary->set_temp(0, Location::RequiresRegister()); 1756 summary->set_temp(0, Location::RequiresRegister());
1746 summary->set_temp(1, Location::RequiresRegister()); 1757 summary->set_temp(1, Location::RequiresRegister());
1747 summary->set_temp(2, opt ? Location::RequiresFpuRegister() 1758 summary->set_temp(2, opt ? Location::RequiresFpuRegister()
1748 : Location::FpuRegisterLocation(XMM1)); 1759 : Location::FpuRegisterLocation(XMM1));
1749 } else { 1760 } else {
1750 summary->set_in(1, ShouldEmitStoreBarrier() 1761 summary->set_in(1, ShouldEmitStoreBarrier()
1751 ? Location::WritableRegister() 1762 ? Location::WritableRegister()
1752 : Location::RegisterOrConstant(value())); 1763 : Location::RegisterOrConstant(value()));
1753 } 1764 }
1754 return summary; 1765 return summary;
1755 } 1766 }
1756 1767
1757 1768
1758 static void EnsureMutableBox(FlowGraphCompiler* compiler, 1769 static void EnsureMutableBox(FlowGraphCompiler* compiler,
1759 StoreInstanceFieldInstr* instruction, 1770 StoreInstanceFieldInstr* instruction,
1760 Register box_reg, 1771 Register box_reg,
1761 const Class& cls, 1772 const Class& cls,
1762 Register instance_reg, 1773 Register instance_reg,
1763 intptr_t offset, 1774 intptr_t offset,
1764 Register temp) { 1775 Register temp) {
1765 Label done; 1776 Label done;
1766 const Immediate& raw_null = 1777 const Immediate& raw_null =
1767 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1778 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1768 __ movl(box_reg, FieldAddress(instance_reg, offset)); 1779 __ movl(box_reg, FieldAddress(instance_reg, offset));
1769 __ cmpl(box_reg, raw_null); 1780 __ cmpl(box_reg, raw_null);
1770 __ j(NOT_EQUAL, &done); 1781 __ j(NOT_EQUAL, &done);
1771 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); 1782 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp);
1772 __ movl(temp, box_reg); 1783 __ movl(temp, box_reg);
1773 __ StoreIntoObject(instance_reg, 1784 __ StoreIntoObject(instance_reg, FieldAddress(instance_reg, offset), temp);
1774 FieldAddress(instance_reg, offset),
1775 temp);
1776 1785
1777 __ Bind(&done); 1786 __ Bind(&done);
1778 } 1787 }
1779 1788
1780 1789
1781 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1790 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1782 ASSERT(sizeof(classid_t) == kInt16Size); 1791 ASSERT(sizeof(classid_t) == kInt16Size);
1783 Label skip_store; 1792 Label skip_store;
1784 1793
1785 Register instance_reg = locs()->in(0).reg(); 1794 Register instance_reg = locs()->in(0).reg();
(...skipping 16 matching lines...) Expand all
1802 case kFloat64x2Cid: 1811 case kFloat64x2Cid:
1803 cls = &compiler->float64x2_class(); 1812 cls = &compiler->float64x2_class();
1804 break; 1813 break;
1805 default: 1814 default:
1806 UNREACHABLE(); 1815 UNREACHABLE();
1807 } 1816 }
1808 1817
1809 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2); 1818 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2);
1810 __ movl(temp2, temp); 1819 __ movl(temp2, temp);
1811 __ StoreIntoObject(instance_reg, 1820 __ StoreIntoObject(instance_reg,
1812 FieldAddress(instance_reg, offset_in_bytes_), 1821 FieldAddress(instance_reg, offset_in_bytes_), temp2);
1813 temp2);
1814 } else { 1822 } else {
1815 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes_)); 1823 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes_));
1816 } 1824 }
1817 switch (cid) { 1825 switch (cid) {
1818 case kDoubleCid: 1826 case kDoubleCid:
1819 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); 1827 __ Comment("UnboxedDoubleStoreInstanceFieldInstr");
1820 __ movsd(FieldAddress(temp, Double::value_offset()), value); 1828 __ movsd(FieldAddress(temp, Double::value_offset()), value);
1821 break; 1829 break;
1822 case kFloat32x4Cid: 1830 case kFloat32x4Cid:
1823 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr"); 1831 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr");
1824 __ movups(FieldAddress(temp, Float32x4::value_offset()), value); 1832 __ movups(FieldAddress(temp, Float32x4::value_offset()), value);
1825 break; 1833 break;
1826 case kFloat64x2Cid: 1834 case kFloat64x2Cid:
1827 __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr"); 1835 __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr");
1828 __ movups(FieldAddress(temp, Float64x2::value_offset()), value); 1836 __ movups(FieldAddress(temp, Float64x2::value_offset()), value);
1829 break; 1837 break;
1830 default: 1838 default:
1831 UNREACHABLE(); 1839 UNREACHABLE();
1832 } 1840 }
1833 return; 1841 return;
1834 } 1842 }
1835 1843
1836 if (IsPotentialUnboxedStore()) { 1844 if (IsPotentialUnboxedStore()) {
1837 __ Comment("PotentialUnboxedStore"); 1845 __ Comment("PotentialUnboxedStore");
1838 Register value_reg = locs()->in(1).reg(); 1846 Register value_reg = locs()->in(1).reg();
1839 Register temp = locs()->temp(0).reg(); 1847 Register temp = locs()->temp(0).reg();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1877 __ jmp(&store_pointer); 1885 __ jmp(&store_pointer);
1878 1886
1879 1887
1880 if (!compiler->is_optimizing()) { 1888 if (!compiler->is_optimizing()) {
1881 locs()->live_registers()->Add(locs()->in(0)); 1889 locs()->live_registers()->Add(locs()->in(0));
1882 locs()->live_registers()->Add(locs()->in(1)); 1890 locs()->live_registers()->Add(locs()->in(1));
1883 } 1891 }
1884 1892
1885 { 1893 {
1886 __ Bind(&store_double); 1894 __ Bind(&store_double);
1887 EnsureMutableBox(compiler, 1895 EnsureMutableBox(compiler, this, temp, compiler->double_class(),
1888 this, 1896 instance_reg, offset_in_bytes_, temp2);
1889 temp,
1890 compiler->double_class(),
1891 instance_reg,
1892 offset_in_bytes_,
1893 temp2);
1894 __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset())); 1897 __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset()));
1895 __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp); 1898 __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp);
1896 __ jmp(&skip_store); 1899 __ jmp(&skip_store);
1897 } 1900 }
1898 1901
1899 { 1902 {
1900 __ Bind(&store_float32x4); 1903 __ Bind(&store_float32x4);
1901 EnsureMutableBox(compiler, 1904 EnsureMutableBox(compiler, this, temp, compiler->float32x4_class(),
1902 this, 1905 instance_reg, offset_in_bytes_, temp2);
1903 temp,
1904 compiler->float32x4_class(),
1905 instance_reg,
1906 offset_in_bytes_,
1907 temp2);
1908 __ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset())); 1906 __ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset()));
1909 __ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp); 1907 __ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp);
1910 __ jmp(&skip_store); 1908 __ jmp(&skip_store);
1911 } 1909 }
1912 1910
1913 { 1911 {
1914 __ Bind(&store_float64x2); 1912 __ Bind(&store_float64x2);
1915 EnsureMutableBox(compiler, 1913 EnsureMutableBox(compiler, this, temp, compiler->float64x2_class(),
1916 this, 1914 instance_reg, offset_in_bytes_, temp2);
1917 temp,
1918 compiler->float64x2_class(),
1919 instance_reg,
1920 offset_in_bytes_,
1921 temp2);
1922 __ movups(fpu_temp, FieldAddress(value_reg, Float64x2::value_offset())); 1915 __ movups(fpu_temp, FieldAddress(value_reg, Float64x2::value_offset()));
1923 __ movups(FieldAddress(temp, Float64x2::value_offset()), fpu_temp); 1916 __ movups(FieldAddress(temp, Float64x2::value_offset()), fpu_temp);
1924 __ jmp(&skip_store); 1917 __ jmp(&skip_store);
1925 } 1918 }
1926 1919
1927 __ Bind(&store_pointer); 1920 __ Bind(&store_pointer);
1928 } 1921 }
1929 1922
1930 if (ShouldEmitStoreBarrier()) { 1923 if (ShouldEmitStoreBarrier()) {
1931 Register value_reg = locs()->in(1).reg(); 1924 Register value_reg = locs()->in(1).reg();
1932 __ StoreIntoObject(instance_reg, 1925 __ StoreIntoObject(instance_reg,
1933 FieldAddress(instance_reg, offset_in_bytes_), 1926 FieldAddress(instance_reg, offset_in_bytes_), value_reg,
1934 value_reg,
1935 CanValueBeSmi()); 1927 CanValueBeSmi());
1936 } else { 1928 } else {
1937 if (locs()->in(1).IsConstant()) { 1929 if (locs()->in(1).IsConstant()) {
1938 __ StoreIntoObjectNoBarrier( 1930 __ StoreIntoObjectNoBarrier(instance_reg,
1939 instance_reg, 1931 FieldAddress(instance_reg, offset_in_bytes_),
1940 FieldAddress(instance_reg, offset_in_bytes_), 1932 locs()->in(1).constant());
1941 locs()->in(1).constant());
1942 } else { 1933 } else {
1943 Register value_reg = locs()->in(1).reg(); 1934 Register value_reg = locs()->in(1).reg();
1944 __ StoreIntoObjectNoBarrier(instance_reg, 1935 __ StoreIntoObjectNoBarrier(instance_reg,
1945 FieldAddress(instance_reg, offset_in_bytes_), 1936 FieldAddress(instance_reg, offset_in_bytes_),
1946 value_reg); 1937 value_reg);
1947 } 1938 }
1948 } 1939 }
1949 __ Bind(&skip_store); 1940 __ Bind(&skip_store);
1950 } 1941 }
1951 1942
1952 1943
1953 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, 1944 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone,
1954 bool opt) const { 1945 bool opt) const {
1955 const intptr_t kNumInputs = 1; 1946 const intptr_t kNumInputs = 1;
1956 const intptr_t kNumTemps = 0; 1947 const intptr_t kNumTemps = 0;
1957 LocationSummary* summary = new(zone) LocationSummary( 1948 LocationSummary* summary = new (zone)
1958 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 1949 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
1959 summary->set_in(0, Location::RequiresRegister()); 1950 summary->set_in(0, Location::RequiresRegister());
1960 // By specifying same register as input, our simple register allocator can 1951 // By specifying same register as input, our simple register allocator can
1961 // generate better code. 1952 // generate better code.
1962 summary->set_out(0, Location::SameAsFirstInput()); 1953 summary->set_out(0, Location::SameAsFirstInput());
1963 return summary; 1954 return summary;
1964 } 1955 }
1965 1956
1966 1957
1967 // When the parser is building an implicit static getter for optimization, 1958 // When the parser is building an implicit static getter for optimization,
1968 // it can generate a function body where deoptimization ids do not line up 1959 // it can generate a function body where deoptimization ids do not line up
1969 // with the unoptimized code. 1960 // with the unoptimized code.
1970 // 1961 //
1971 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. 1962 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize.
1972 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1963 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1973 Register field = locs()->in(0).reg(); 1964 Register field = locs()->in(0).reg();
1974 Register result = locs()->out(0).reg(); 1965 Register result = locs()->out(0).reg();
1975 __ movl(result, FieldAddress(field, Field::static_value_offset())); 1966 __ movl(result, FieldAddress(field, Field::static_value_offset()));
1976 } 1967 }
1977 1968
1978 1969
1979 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, 1970 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone,
1980 bool opt) const { 1971 bool opt) const {
1981 LocationSummary* locs = new(zone) LocationSummary( 1972 LocationSummary* locs =
1982 zone, 1, 1, LocationSummary::kNoCall); 1973 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall);
1983 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() 1974 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister()
1984 : Location::RequiresRegister()); 1975 : Location::RequiresRegister());
1985 locs->set_temp(0, Location::RequiresRegister()); 1976 locs->set_temp(0, Location::RequiresRegister());
1986 return locs; 1977 return locs;
1987 } 1978 }
1988 1979
1989 1980
1990 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1981 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1991 Register value = locs()->in(0).reg(); 1982 Register value = locs()->in(0).reg();
1992 Register temp = locs()->temp(0).reg(); 1983 Register temp = locs()->temp(0).reg();
1993 1984
1994 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); 1985 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original()));
1995 if (this->value()->NeedsStoreBuffer()) { 1986 if (this->value()->NeedsStoreBuffer()) {
1996 __ StoreIntoObject(temp, 1987 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()),
1997 FieldAddress(temp, Field::static_value_offset()), 1988 value, CanValueBeSmi());
1998 value,
1999 CanValueBeSmi());
2000 } else { 1989 } else {
2001 __ StoreIntoObjectNoBarrier( 1990 __ StoreIntoObjectNoBarrier(
2002 temp, FieldAddress(temp, Field::static_value_offset()), value); 1991 temp, FieldAddress(temp, Field::static_value_offset()), value);
2003 } 1992 }
2004 } 1993 }
2005 1994
2006 1995
2007 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, 1996 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
2008 bool opt) const { 1997 bool opt) const {
2009 const intptr_t kNumInputs = 2; 1998 const intptr_t kNumInputs = 2;
2010 const intptr_t kNumTemps = 0; 1999 const intptr_t kNumTemps = 0;
2011 LocationSummary* summary = new(zone) LocationSummary( 2000 LocationSummary* summary = new (zone)
2012 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 2001 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2013 summary->set_in(0, Location::RegisterLocation(EAX)); 2002 summary->set_in(0, Location::RegisterLocation(EAX));
2014 summary->set_in(1, Location::RegisterLocation(EDX)); 2003 summary->set_in(1, Location::RegisterLocation(EDX));
2015 summary->set_out(0, Location::RegisterLocation(EAX)); 2004 summary->set_out(0, Location::RegisterLocation(EAX));
2016 return summary; 2005 return summary;
2017 } 2006 }
2018 2007
2019 2008
2020 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2009 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2021 ASSERT(locs()->in(0).reg() == EAX); // Value. 2010 ASSERT(locs()->in(0).reg() == EAX); // Value.
2022 ASSERT(locs()->in(1).reg() == EDX); // Instantiator type arguments. 2011 ASSERT(locs()->in(1).reg() == EDX); // Instantiator type arguments.
2023 2012
2024 compiler->GenerateInstanceOf(token_pos(), 2013 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), negate_result(),
2025 deopt_id(),
2026 type(),
2027 negate_result(),
2028 locs()); 2014 locs());
2029 ASSERT(locs()->out(0).reg() == EAX); 2015 ASSERT(locs()->out(0).reg() == EAX);
2030 } 2016 }
2031 2017
2032 2018
2033 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and 2019 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and
2034 // use slow path stub. 2020 // use slow path stub.
2035 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, 2021 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone,
2036 bool opt) const { 2022 bool opt) const {
2037 const intptr_t kNumInputs = 2; 2023 const intptr_t kNumInputs = 2;
2038 const intptr_t kNumTemps = 0; 2024 const intptr_t kNumTemps = 0;
2039 LocationSummary* locs = new(zone) LocationSummary( 2025 LocationSummary* locs = new (zone)
2040 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 2026 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2041 locs->set_in(0, Location::RegisterLocation(ECX)); 2027 locs->set_in(0, Location::RegisterLocation(ECX));
2042 locs->set_in(1, Location::RegisterLocation(EDX)); 2028 locs->set_in(1, Location::RegisterLocation(EDX));
2043 locs->set_out(0, Location::RegisterLocation(EAX)); 2029 locs->set_out(0, Location::RegisterLocation(EAX));
2044 return locs; 2030 return locs;
2045 } 2031 }
2046 2032
2047 2033
2048 // Inlines array allocation for known constant values. 2034 // Inlines array allocation for known constant values.
2049 static void InlineArrayAllocation(FlowGraphCompiler* compiler, 2035 static void InlineArrayAllocation(FlowGraphCompiler* compiler,
2050 intptr_t num_elements, 2036 intptr_t num_elements,
2051 Label* slow_path, 2037 Label* slow_path,
2052 Label* done) { 2038 Label* done) {
2053 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. 2039 const int kInlineArraySize = 12; // Same as kInlineInstanceSize.
2054 const Register kLengthReg = EDX; 2040 const Register kLengthReg = EDX;
2055 const Register kElemTypeReg = ECX; 2041 const Register kElemTypeReg = ECX;
2056 const intptr_t instance_size = Array::InstanceSize(num_elements); 2042 const intptr_t instance_size = Array::InstanceSize(num_elements);
2057 2043
2058 // Instance in EAX. 2044 // Instance in EAX.
2059 // Object end address in EBX. 2045 // Object end address in EBX.
2060 __ TryAllocateArray(kArrayCid, instance_size, slow_path, Assembler::kFarJump, 2046 __ TryAllocateArray(kArrayCid, instance_size, slow_path, Assembler::kFarJump,
2061 EAX, // instance 2047 EAX, // instance
2062 EBX, // end address 2048 EBX, // end address
2063 EDI); // temp 2049 EDI); // temp
2064 2050
2065 // Store the type argument field. 2051 // Store the type argument field.
2066 __ StoreIntoObjectNoBarrier(EAX, 2052 __ StoreIntoObjectNoBarrier(
2067 FieldAddress(EAX, Array::type_arguments_offset()), 2053 EAX, FieldAddress(EAX, Array::type_arguments_offset()), kElemTypeReg);
2068 kElemTypeReg);
2069 2054
2070 // Set the length field. 2055 // Set the length field.
2071 __ StoreIntoObjectNoBarrier(EAX, 2056 __ StoreIntoObjectNoBarrier(EAX, FieldAddress(EAX, Array::length_offset()),
2072 FieldAddress(EAX, Array::length_offset()),
2073 kLengthReg); 2057 kLengthReg);
2074 2058
2075 // Initialize all array elements to raw_null. 2059 // Initialize all array elements to raw_null.
2076 // EAX: new object start as a tagged pointer. 2060 // EAX: new object start as a tagged pointer.
2077 // EBX: new object end address. 2061 // EBX: new object end address.
2078 // EDI: iterator which initially points to the start of the variable 2062 // EDI: iterator which initially points to the start of the variable
2079 // data area to be initialized. 2063 // data area to be initialized.
2080 if (num_elements > 0) { 2064 if (num_elements > 0) {
2081 const intptr_t array_size = instance_size - sizeof(RawArray); 2065 const intptr_t array_size = instance_size - sizeof(RawArray);
2082 const Immediate& raw_null = 2066 const Immediate& raw_null =
(...skipping 21 matching lines...) Expand all
2104 2088
2105 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2089 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2106 // Allocate the array. EDX = length, ECX = element type. 2090 // Allocate the array. EDX = length, ECX = element type.
2107 const Register kLengthReg = EDX; 2091 const Register kLengthReg = EDX;
2108 const Register kElemTypeReg = ECX; 2092 const Register kElemTypeReg = ECX;
2109 const Register kResultReg = EAX; 2093 const Register kResultReg = EAX;
2110 ASSERT(locs()->in(0).reg() == kElemTypeReg); 2094 ASSERT(locs()->in(0).reg() == kElemTypeReg);
2111 ASSERT(locs()->in(1).reg() == kLengthReg); 2095 ASSERT(locs()->in(1).reg() == kLengthReg);
2112 2096
2113 Label slow_path, done; 2097 Label slow_path, done;
2114 if (compiler->is_optimizing() && 2098 if (compiler->is_optimizing() && num_elements()->BindsToConstant() &&
2115 num_elements()->BindsToConstant() &&
2116 num_elements()->BoundConstant().IsSmi()) { 2099 num_elements()->BoundConstant().IsSmi()) {
2117 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); 2100 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value();
2118 if ((length >= 0) && (length <= Array::kMaxElements)) { 2101 if ((length >= 0) && (length <= Array::kMaxElements)) {
2119 Label slow_path, done; 2102 Label slow_path, done;
2120 InlineArrayAllocation(compiler, length, &slow_path, &done); 2103 InlineArrayAllocation(compiler, length, &slow_path, &done);
2121 __ Bind(&slow_path); 2104 __ Bind(&slow_path);
2122 __ PushObject(Object::null_object()); // Make room for the result. 2105 __ PushObject(Object::null_object()); // Make room for the result.
2123 __ pushl(kLengthReg); 2106 __ pushl(kLengthReg);
2124 __ pushl(kElemTypeReg); 2107 __ pushl(kElemTypeReg);
2125 compiler->GenerateRuntimeCall(token_pos(), 2108 compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
2126 deopt_id(), 2109 kAllocateArrayRuntimeEntry, 2, locs());
2127 kAllocateArrayRuntimeEntry,
2128 2,
2129 locs());
2130 __ Drop(2); 2110 __ Drop(2);
2131 __ popl(kResultReg); 2111 __ popl(kResultReg);
2132 __ Bind(&done); 2112 __ Bind(&done);
2133 return; 2113 return;
2134 } 2114 }
2135 } 2115 }
2136 2116
2137 __ Bind(&slow_path); 2117 __ Bind(&slow_path);
2138 const Code& stub = Code::ZoneHandle(compiler->zone(), 2118 const Code& stub = Code::ZoneHandle(compiler->zone(),
2139 StubCode::AllocateArray_entry()->code()); 2119 StubCode::AllocateArray_entry()->code());
2140 compiler->AddStubCallTarget(stub); 2120 compiler->AddStubCallTarget(stub);
2141 compiler->GenerateCall(token_pos(), 2121 compiler->GenerateCall(token_pos(), *StubCode::AllocateArray_entry(),
2142 *StubCode::AllocateArray_entry(), 2122 RawPcDescriptors::kOther, locs());
2143 RawPcDescriptors::kOther,
2144 locs());
2145 __ Bind(&done); 2123 __ Bind(&done);
2146 ASSERT(locs()->out(0).reg() == kResultReg); 2124 ASSERT(locs()->out(0).reg() == kResultReg);
2147 } 2125 }
2148 2126
2149 2127
2150 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, 2128 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone,
2151 bool opt) const { 2129 bool opt) const {
2152 const intptr_t kNumInputs = 1; 2130 const intptr_t kNumInputs = 1;
2153 const intptr_t kNumTemps = 2131 const intptr_t kNumTemps =
2154 (IsUnboxedLoad() && opt) ? 1 : 2132 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0);
2155 ((IsPotentialUnboxedLoad()) ? 2 : 0);
2156 2133
2157 LocationSummary* locs = new(zone) LocationSummary( 2134 LocationSummary* locs = new (zone) LocationSummary(
2158 zone, kNumInputs, kNumTemps, 2135 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad())
2159 (opt && !IsPotentialUnboxedLoad()) 2136 ? LocationSummary::kNoCall
2160 ? LocationSummary::kNoCall 2137 : LocationSummary::kCallOnSlowPath);
2161 : LocationSummary::kCallOnSlowPath);
2162 2138
2163 locs->set_in(0, Location::RequiresRegister()); 2139 locs->set_in(0, Location::RequiresRegister());
2164 2140
2165 if (IsUnboxedLoad() && opt) { 2141 if (IsUnboxedLoad() && opt) {
2166 locs->set_temp(0, Location::RequiresRegister()); 2142 locs->set_temp(0, Location::RequiresRegister());
2167 } else if (IsPotentialUnboxedLoad()) { 2143 } else if (IsPotentialUnboxedLoad()) {
2168 locs->set_temp(0, opt ? Location::RequiresFpuRegister() 2144 locs->set_temp(0, opt ? Location::RequiresFpuRegister()
2169 : Location::FpuRegisterLocation(XMM1)); 2145 : Location::FpuRegisterLocation(XMM1));
2170 locs->set_temp(1, Location::RequiresRegister()); 2146 locs->set_temp(1, Location::RequiresRegister());
2171 } 2147 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2233 2209
2234 // Fall through. 2210 // Fall through.
2235 __ jmp(&load_pointer); 2211 __ jmp(&load_pointer);
2236 2212
2237 if (!compiler->is_optimizing()) { 2213 if (!compiler->is_optimizing()) {
2238 locs()->live_registers()->Add(locs()->in(0)); 2214 locs()->live_registers()->Add(locs()->in(0));
2239 } 2215 }
2240 2216
2241 { 2217 {
2242 __ Bind(&load_double); 2218 __ Bind(&load_double);
2243 BoxAllocationSlowPath::Allocate( 2219 BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(),
2244 compiler, this, compiler->double_class(), result, temp); 2220 result, temp);
2245 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes())); 2221 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes()));
2246 __ movsd(value, FieldAddress(temp, Double::value_offset())); 2222 __ movsd(value, FieldAddress(temp, Double::value_offset()));
2247 __ movsd(FieldAddress(result, Double::value_offset()), value); 2223 __ movsd(FieldAddress(result, Double::value_offset()), value);
2248 __ jmp(&done); 2224 __ jmp(&done);
2249 } 2225 }
2250 2226
2251 { 2227 {
2252 __ Bind(&load_float32x4); 2228 __ Bind(&load_float32x4);
2253 BoxAllocationSlowPath::Allocate( 2229 BoxAllocationSlowPath::Allocate(
2254 compiler, this, compiler->float32x4_class(), result, temp); 2230 compiler, this, compiler->float32x4_class(), result, temp);
(...skipping 17 matching lines...) Expand all
2272 } 2248 }
2273 __ movl(result, FieldAddress(instance_reg, offset_in_bytes())); 2249 __ movl(result, FieldAddress(instance_reg, offset_in_bytes()));
2274 __ Bind(&done); 2250 __ Bind(&done);
2275 } 2251 }
2276 2252
2277 2253
2278 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, 2254 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
2279 bool opt) const { 2255 bool opt) const {
2280 const intptr_t kNumInputs = 1; 2256 const intptr_t kNumInputs = 1;
2281 const intptr_t kNumTemps = 0; 2257 const intptr_t kNumTemps = 0;
2282 LocationSummary* locs = new(zone) LocationSummary( 2258 LocationSummary* locs = new (zone)
2283 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 2259 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2284 locs->set_in(0, Location::RegisterLocation(EAX)); 2260 locs->set_in(0, Location::RegisterLocation(EAX));
2285 locs->set_out(0, Location::RegisterLocation(EAX)); 2261 locs->set_out(0, Location::RegisterLocation(EAX));
2286 return locs; 2262 return locs;
2287 } 2263 }
2288 2264
2289 2265
2290 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2266 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2291 Register instantiator_reg = locs()->in(0).reg(); 2267 Register instantiator_reg = locs()->in(0).reg();
2292 Register result_reg = locs()->out(0).reg(); 2268 Register result_reg = locs()->out(0).reg();
2293 2269
2294 // 'instantiator_reg' is the instantiator TypeArguments object (or null). 2270 // 'instantiator_reg' is the instantiator TypeArguments object (or null).
2295 // A runtime call to instantiate the type is required. 2271 // A runtime call to instantiate the type is required.
2296 __ PushObject(Object::null_object()); // Make room for the result. 2272 __ PushObject(Object::null_object()); // Make room for the result.
2297 __ PushObject(type()); 2273 __ PushObject(type());
2298 __ pushl(instantiator_reg); // Push instantiator type arguments. 2274 __ pushl(instantiator_reg); // Push instantiator type arguments.
2299 compiler->GenerateRuntimeCall(token_pos(), 2275 compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
2300 deopt_id(), 2276 kInstantiateTypeRuntimeEntry, 2, locs());
2301 kInstantiateTypeRuntimeEntry, 2277 __ Drop(2); // Drop instantiator and uninstantiated type.
2302 2,
2303 locs());
2304 __ Drop(2); // Drop instantiator and uninstantiated type.
2305 __ popl(result_reg); // Pop instantiated type. 2278 __ popl(result_reg); // Pop instantiated type.
2306 ASSERT(instantiator_reg == result_reg); 2279 ASSERT(instantiator_reg == result_reg);
2307 } 2280 }
2308 2281
2309 2282
2310 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( 2283 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
2311 Zone* zone, bool opt) const { 2284 Zone* zone,
2285 bool opt) const {
2312 const intptr_t kNumInputs = 1; 2286 const intptr_t kNumInputs = 1;
2313 const intptr_t kNumTemps = 0; 2287 const intptr_t kNumTemps = 0;
2314 LocationSummary* locs = new(zone) LocationSummary( 2288 LocationSummary* locs = new (zone)
2315 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 2289 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2316 locs->set_in(0, Location::RegisterLocation(EAX)); 2290 locs->set_in(0, Location::RegisterLocation(EAX));
2317 locs->set_out(0, Location::RegisterLocation(EAX)); 2291 locs->set_out(0, Location::RegisterLocation(EAX));
2318 return locs; 2292 return locs;
2319 } 2293 }
2320 2294
2321 2295
2322 void InstantiateTypeArgumentsInstr::EmitNativeCode( 2296 void InstantiateTypeArgumentsInstr::EmitNativeCode(
2323 FlowGraphCompiler* compiler) { 2297 FlowGraphCompiler* compiler) {
2324 Register instantiator_reg = locs()->in(0).reg(); 2298 Register instantiator_reg = locs()->in(0).reg();
2325 Register result_reg = locs()->out(0).reg(); 2299 Register result_reg = locs()->out(0).reg();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2361 __ Bind(&found); 2335 __ Bind(&found);
2362 __ movl(EAX, Address(EDI, 1 * kWordSize)); // Cached instantiated args. 2336 __ movl(EAX, Address(EDI, 1 * kWordSize)); // Cached instantiated args.
2363 __ jmp(&type_arguments_instantiated, Assembler::kNearJump); 2337 __ jmp(&type_arguments_instantiated, Assembler::kNearJump);
2364 2338
2365 __ Bind(&slow_case); 2339 __ Bind(&slow_case);
2366 // Instantiate non-null type arguments. 2340 // Instantiate non-null type arguments.
2367 // A runtime call to instantiate the type arguments is required. 2341 // A runtime call to instantiate the type arguments is required.
2368 __ PushObject(Object::null_object()); // Make room for the result. 2342 __ PushObject(Object::null_object()); // Make room for the result.
2369 __ PushObject(type_arguments()); 2343 __ PushObject(type_arguments());
2370 __ pushl(instantiator_reg); // Push instantiator type arguments. 2344 __ pushl(instantiator_reg); // Push instantiator type arguments.
2371 compiler->GenerateRuntimeCall(token_pos(), 2345 compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
2372 deopt_id(), 2346 kInstantiateTypeArgumentsRuntimeEntry, 2,
2373 kInstantiateTypeArgumentsRuntimeEntry,
2374 2,
2375 locs()); 2347 locs());
2376 __ Drop(2); // Drop instantiator and uninstantiated type arguments. 2348 __ Drop(2); // Drop instantiator and uninstantiated type arguments.
2377 __ popl(result_reg); // Pop instantiated type arguments. 2349 __ popl(result_reg); // Pop instantiated type arguments.
2378 __ Bind(&type_arguments_instantiated); 2350 __ Bind(&type_arguments_instantiated);
2379 } 2351 }
2380 2352
2381 2353
2382 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( 2354 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary(
2383 Zone* zone, 2355 Zone* zone,
2384 bool opt) const { 2356 bool opt) const {
2385 ASSERT(opt); 2357 ASSERT(opt);
2386 const intptr_t kNumInputs = 0; 2358 const intptr_t kNumInputs = 0;
2387 const intptr_t kNumTemps = 2; 2359 const intptr_t kNumTemps = 2;
2388 LocationSummary* locs = new(zone) LocationSummary( 2360 LocationSummary* locs = new (zone) LocationSummary(
2389 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); 2361 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
2390 locs->set_temp(0, Location::RegisterLocation(ECX)); 2362 locs->set_temp(0, Location::RegisterLocation(ECX));
2391 locs->set_temp(1, Location::RegisterLocation(EDI)); 2363 locs->set_temp(1, Location::RegisterLocation(EDI));
2392 locs->set_out(0, Location::RegisterLocation(EAX)); 2364 locs->set_out(0, Location::RegisterLocation(EAX));
2393 return locs; 2365 return locs;
2394 } 2366 }
2395 2367
2396 2368
2397 class AllocateContextSlowPath : public SlowPathCode { 2369 class AllocateContextSlowPath : public SlowPathCode {
2398 public: 2370 public:
2399 explicit AllocateContextSlowPath( 2371 explicit AllocateContextSlowPath(
2400 AllocateUninitializedContextInstr* instruction) 2372 AllocateUninitializedContextInstr* instruction)
2401 : instruction_(instruction) { } 2373 : instruction_(instruction) {}
2402 2374
2403 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 2375 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
2404 __ Comment("AllocateContextSlowPath"); 2376 __ Comment("AllocateContextSlowPath");
2405 __ Bind(entry_label()); 2377 __ Bind(entry_label());
2406 2378
2407 LocationSummary* locs = instruction_->locs(); 2379 LocationSummary* locs = instruction_->locs();
2408 ASSERT(!locs->live_registers()->Contains(locs->out(0))); 2380 ASSERT(!locs->live_registers()->Contains(locs->out(0)));
2409 2381
2410 compiler->SaveLiveRegisters(locs); 2382 compiler->SaveLiveRegisters(locs);
2411 2383
2412 __ movl(EDX, Immediate(instruction_->num_context_variables())); 2384 __ movl(EDX, Immediate(instruction_->num_context_variables()));
2413 const Code& stub = Code::ZoneHandle( 2385 const Code& stub = Code::ZoneHandle(
2414 compiler->zone(), StubCode::AllocateContext_entry()->code()); 2386 compiler->zone(), StubCode::AllocateContext_entry()->code());
2415 compiler->AddStubCallTarget(stub); 2387 compiler->AddStubCallTarget(stub);
2416 compiler->GenerateCall(instruction_->token_pos(), 2388 compiler->GenerateCall(instruction_->token_pos(),
2417 *StubCode::AllocateContext_entry(), 2389 *StubCode::AllocateContext_entry(),
2418 RawPcDescriptors::kOther, 2390 RawPcDescriptors::kOther, locs);
2419 locs);
2420 ASSERT(instruction_->locs()->out(0).reg() == EAX); 2391 ASSERT(instruction_->locs()->out(0).reg() == EAX);
2421 compiler->RestoreLiveRegisters(instruction_->locs()); 2392 compiler->RestoreLiveRegisters(instruction_->locs());
2422 __ jmp(exit_label()); 2393 __ jmp(exit_label());
2423 } 2394 }
2424 2395
2425 private: 2396 private:
2426 AllocateUninitializedContextInstr* instruction_; 2397 AllocateUninitializedContextInstr* instruction_;
2427 }; 2398 };
2428 2399
2429 2400
2430 void AllocateUninitializedContextInstr::EmitNativeCode( 2401 void AllocateUninitializedContextInstr::EmitNativeCode(
2431 FlowGraphCompiler* compiler) { 2402 FlowGraphCompiler* compiler) {
2432 ASSERT(compiler->is_optimizing()); 2403 ASSERT(compiler->is_optimizing());
2433 Register temp = locs()->temp(0).reg(); 2404 Register temp = locs()->temp(0).reg();
2434 Register temp2 = locs()->temp(1).reg(); 2405 Register temp2 = locs()->temp(1).reg();
2435 Register result = locs()->out(0).reg(); 2406 Register result = locs()->out(0).reg();
2436 // Try allocate the object. 2407 // Try allocate the object.
2437 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); 2408 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this);
2438 compiler->AddSlowPathCode(slow_path); 2409 compiler->AddSlowPathCode(slow_path);
2439 intptr_t instance_size = Context::InstanceSize(num_context_variables()); 2410 intptr_t instance_size = Context::InstanceSize(num_context_variables());
2440 2411
2441 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), 2412 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(),
2442 Assembler::kFarJump, 2413 Assembler::kFarJump,
2443 result, // instance 2414 result, // instance
2444 temp, // end address 2415 temp, // end address
2445 temp2); // temp 2416 temp2); // temp
2446 2417
2447 // Setup up number of context variables field. 2418 // Setup up number of context variables field.
2448 __ movl(FieldAddress(result, Context::num_variables_offset()), 2419 __ movl(FieldAddress(result, Context::num_variables_offset()),
2449 Immediate(num_context_variables())); 2420 Immediate(num_context_variables()));
2450 2421
2451 __ Bind(slow_path->exit_label()); 2422 __ Bind(slow_path->exit_label());
2452 } 2423 }
2453 2424
2454 2425
2455 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, 2426 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone,
2456 bool opt) const { 2427 bool opt) const {
2457 const intptr_t kNumInputs = 0; 2428 const intptr_t kNumInputs = 0;
2458 const intptr_t kNumTemps = 1; 2429 const intptr_t kNumTemps = 1;
2459 LocationSummary* locs = new(zone) LocationSummary( 2430 LocationSummary* locs = new (zone)
2460 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 2431 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2461 locs->set_temp(0, Location::RegisterLocation(EDX)); 2432 locs->set_temp(0, Location::RegisterLocation(EDX));
2462 locs->set_out(0, Location::RegisterLocation(EAX)); 2433 locs->set_out(0, Location::RegisterLocation(EAX));
2463 return locs; 2434 return locs;
2464 } 2435 }
2465 2436
2466 2437
2467 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2438 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2468 ASSERT(locs()->temp(0).reg() == EDX); 2439 ASSERT(locs()->temp(0).reg() == EDX);
2469 ASSERT(locs()->out(0).reg() == EAX); 2440 ASSERT(locs()->out(0).reg() == EAX);
2470 2441
2471 __ movl(EDX, Immediate(num_context_variables())); 2442 __ movl(EDX, Immediate(num_context_variables()));
2472 compiler->GenerateCall(token_pos(), 2443 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(),
2473 *StubCode::AllocateContext_entry(), 2444 RawPcDescriptors::kOther, locs());
2474 RawPcDescriptors::kOther,
2475 locs());
2476 } 2445 }
2477 2446
2478 2447
2479 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, 2448 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone,
2480 bool opt) const { 2449 bool opt) const {
2481 const intptr_t kNumInputs = 1; 2450 const intptr_t kNumInputs = 1;
2482 const intptr_t kNumTemps = 1; 2451 const intptr_t kNumTemps = 1;
2483 LocationSummary* locs = new(zone) LocationSummary( 2452 LocationSummary* locs = new (zone)
2484 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 2453 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2485 locs->set_in(0, Location::RegisterLocation(EAX)); 2454 locs->set_in(0, Location::RegisterLocation(EAX));
2486 locs->set_temp(0, Location::RegisterLocation(ECX)); 2455 locs->set_temp(0, Location::RegisterLocation(ECX));
2487 return locs; 2456 return locs;
2488 } 2457 }
2489 2458
2490 2459
2491 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2460 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2492 Register field = locs()->in(0).reg(); 2461 Register field = locs()->in(0).reg();
2493 Register temp = locs()->temp(0).reg(); 2462 Register temp = locs()->temp(0).reg();
2494 2463
2495 Label call_runtime, no_call; 2464 Label call_runtime, no_call;
2496 2465
2497 __ movl(temp, FieldAddress(field, Field::static_value_offset())); 2466 __ movl(temp, FieldAddress(field, Field::static_value_offset()));
2498 __ CompareObject(temp, Object::sentinel()); 2467 __ CompareObject(temp, Object::sentinel());
2499 __ j(EQUAL, &call_runtime); 2468 __ j(EQUAL, &call_runtime);
2500 2469
2501 __ CompareObject(temp, Object::transition_sentinel()); 2470 __ CompareObject(temp, Object::transition_sentinel());
2502 __ j(NOT_EQUAL, &no_call); 2471 __ j(NOT_EQUAL, &no_call);
2503 2472
2504 __ Bind(&call_runtime); 2473 __ Bind(&call_runtime);
2505 __ PushObject(Object::null_object()); // Make room for (unused) result. 2474 __ PushObject(Object::null_object()); // Make room for (unused) result.
2506 __ pushl(field); 2475 __ pushl(field);
2507 compiler->GenerateRuntimeCall(token_pos(), 2476 compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
2508 deopt_id(), 2477 kInitStaticFieldRuntimeEntry, 1, locs());
2509 kInitStaticFieldRuntimeEntry,
2510 1,
2511 locs());
2512 __ Drop(2); // Remove argument and unused result. 2478 __ Drop(2); // Remove argument and unused result.
2513 __ Bind(&no_call); 2479 __ Bind(&no_call);
2514 } 2480 }
2515 2481
2516 2482
2517 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, 2483 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone,
2518 bool opt) const { 2484 bool opt) const {
2519 const intptr_t kNumInputs = 1; 2485 const intptr_t kNumInputs = 1;
2520 const intptr_t kNumTemps = 0; 2486 const intptr_t kNumTemps = 0;
2521 LocationSummary* locs = new(zone) LocationSummary( 2487 LocationSummary* locs = new (zone)
2522 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 2488 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2523 locs->set_in(0, Location::RegisterLocation(EAX)); 2489 locs->set_in(0, Location::RegisterLocation(EAX));
2524 locs->set_out(0, Location::RegisterLocation(EAX)); 2490 locs->set_out(0, Location::RegisterLocation(EAX));
2525 return locs; 2491 return locs;
2526 } 2492 }
2527 2493
2528 2494
2529 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2495 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2530 Register context_value = locs()->in(0).reg(); 2496 Register context_value = locs()->in(0).reg();
2531 Register result = locs()->out(0).reg(); 2497 Register result = locs()->out(0).reg();
2532 2498
2533 __ PushObject(Object::null_object()); // Make room for the result. 2499 __ PushObject(Object::null_object()); // Make room for the result.
2534 __ pushl(context_value); 2500 __ pushl(context_value);
2535 compiler->GenerateRuntimeCall(token_pos(), 2501 compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
2536 deopt_id(), 2502 kCloneContextRuntimeEntry, 1, locs());
2537 kCloneContextRuntimeEntry,
2538 1,
2539 locs());
2540 __ popl(result); // Remove argument. 2503 __ popl(result); // Remove argument.
2541 __ popl(result); // Get result (cloned context). 2504 __ popl(result); // Get result (cloned context).
2542 } 2505 }
2543 2506
2544 2507
2545 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, 2508 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone,
2546 bool opt) const { 2509 bool opt) const {
2547 UNREACHABLE(); 2510 UNREACHABLE();
2548 return NULL; 2511 return NULL;
2549 } 2512 }
2550 2513
2551 2514
2552 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2515 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2553 __ Bind(compiler->GetJumpLabel(this)); 2516 __ Bind(compiler->GetJumpLabel(this));
2554 compiler->AddExceptionHandler(catch_try_index(), 2517 compiler->AddExceptionHandler(catch_try_index(), try_index(),
2555 try_index(),
2556 compiler->assembler()->CodeSize(), 2518 compiler->assembler()->CodeSize(),
2557 catch_handler_types_, 2519 catch_handler_types_, needs_stacktrace());
2558 needs_stacktrace());
2559 // On lazy deoptimization we patch the optimized code here to enter the 2520 // On lazy deoptimization we patch the optimized code here to enter the
2560 // deoptimization stub. 2521 // deoptimization stub.
2561 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); 2522 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId());
2562 if (compiler->is_optimizing()) { 2523 if (compiler->is_optimizing()) {
2563 compiler->AddDeoptIndexAtCall(deopt_id); 2524 compiler->AddDeoptIndexAtCall(deopt_id);
2564 } else { 2525 } else {
2565 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, 2526 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id,
2566 deopt_id,
2567 TokenPosition::kNoSource); 2527 TokenPosition::kNoSource);
2568 } 2528 }
2569 if (HasParallelMove()) { 2529 if (HasParallelMove()) {
2570 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); 2530 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
2571 } 2531 }
2572 2532
2573 // Restore ESP from EBP as we are coming from a throw and the code for 2533 // Restore ESP from EBP as we are coming from a throw and the code for
2574 // popping arguments has not been run. 2534 // popping arguments has not been run.
2575 const intptr_t fp_sp_dist = 2535 const intptr_t fp_sp_dist =
2576 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; 2536 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize;
2577 ASSERT(fp_sp_dist <= 0); 2537 ASSERT(fp_sp_dist <= 0);
2578 __ leal(ESP, Address(EBP, fp_sp_dist)); 2538 __ leal(ESP, Address(EBP, fp_sp_dist));
2579 2539
2580 // Restore stack and initialize the two exception variables: 2540 // Restore stack and initialize the two exception variables:
2581 // exception and stack trace variables. 2541 // exception and stack trace variables.
2582 __ movl(Address(EBP, exception_var().index() * kWordSize), 2542 __ movl(Address(EBP, exception_var().index() * kWordSize),
2583 kExceptionObjectReg); 2543 kExceptionObjectReg);
2584 __ movl(Address(EBP, stacktrace_var().index() * kWordSize), 2544 __ movl(Address(EBP, stacktrace_var().index() * kWordSize),
2585 kStackTraceObjectReg); 2545 kStackTraceObjectReg);
2586 } 2546 }
2587 2547
2588 2548
2589 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, 2549 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone,
2590 bool opt) const { 2550 bool opt) const {
2591 const intptr_t kNumInputs = 0; 2551 const intptr_t kNumInputs = 0;
2592 const intptr_t kNumTemps = opt ? 0 : 1; 2552 const intptr_t kNumTemps = opt ? 0 : 1;
2593 LocationSummary* summary = new(zone) LocationSummary( 2553 LocationSummary* summary = new (zone) LocationSummary(
2594 zone, kNumInputs, 2554 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
2595 kNumTemps,
2596 LocationSummary::kCallOnSlowPath);
2597 if (!opt) { 2555 if (!opt) {
2598 summary->set_temp(0, Location::RequiresRegister()); 2556 summary->set_temp(0, Location::RequiresRegister());
2599 } 2557 }
2600 return summary; 2558 return summary;
2601 } 2559 }
2602 2560
2603 2561
2604 class CheckStackOverflowSlowPath : public SlowPathCode { 2562 class CheckStackOverflowSlowPath : public SlowPathCode {
2605 public: 2563 public:
2606 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) 2564 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction)
2607 : instruction_(instruction) { } 2565 : instruction_(instruction) {}
2608 2566
2609 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 2567 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
2610 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { 2568 if (FLAG_use_osr && osr_entry_label()->IsLinked()) {
2611 __ Comment("CheckStackOverflowSlowPathOsr"); 2569 __ Comment("CheckStackOverflowSlowPathOsr");
2612 __ Bind(osr_entry_label()); 2570 __ Bind(osr_entry_label());
2613 __ movl(Address(THR, Thread::stack_overflow_flags_offset()), 2571 __ movl(Address(THR, Thread::stack_overflow_flags_offset()),
2614 Immediate(Thread::kOsrRequest)); 2572 Immediate(Thread::kOsrRequest));
2615 } 2573 }
2616 __ Comment("CheckStackOverflowSlowPath"); 2574 __ Comment("CheckStackOverflowSlowPath");
2617 __ Bind(entry_label()); 2575 __ Bind(entry_label());
2618 compiler->SaveLiveRegisters(instruction_->locs()); 2576 compiler->SaveLiveRegisters(instruction_->locs());
2619 // pending_deoptimization_env_ is needed to generate a runtime call that 2577 // pending_deoptimization_env_ is needed to generate a runtime call that
2620 // may throw an exception. 2578 // may throw an exception.
2621 ASSERT(compiler->pending_deoptimization_env_ == NULL); 2579 ASSERT(compiler->pending_deoptimization_env_ == NULL);
2622 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); 2580 Environment* env = compiler->SlowPathEnvironmentFor(instruction_);
2623 compiler->pending_deoptimization_env_ = env; 2581 compiler->pending_deoptimization_env_ = env;
2624 compiler->GenerateRuntimeCall(instruction_->token_pos(), 2582 compiler->GenerateRuntimeCall(
2625 instruction_->deopt_id(), 2583 instruction_->token_pos(), instruction_->deopt_id(),
2626 kStackOverflowRuntimeEntry, 2584 kStackOverflowRuntimeEntry, 0, instruction_->locs());
2627 0,
2628 instruction_->locs());
2629 2585
2630 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { 2586 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) {
2631 // In unoptimized code, record loop stack checks as possible OSR entries. 2587 // In unoptimized code, record loop stack checks as possible OSR entries.
2632 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, 2588 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry,
2633 instruction_->deopt_id(), 2589 instruction_->deopt_id(),
2634 TokenPosition::kNoSource); 2590 TokenPosition::kNoSource);
2635 } 2591 }
2636 compiler->pending_deoptimization_env_ = NULL; 2592 compiler->pending_deoptimization_env_ = NULL;
2637 compiler->RestoreLiveRegisters(instruction_->locs()); 2593 compiler->RestoreLiveRegisters(instruction_->locs());
2638 __ jmp(exit_label()); 2594 __ jmp(exit_label());
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2674 __ Bind(slow_path->exit_label()); 2630 __ Bind(slow_path->exit_label());
2675 } 2631 }
2676 2632
2677 2633
2678 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, 2634 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
2679 BinarySmiOpInstr* shift_left) { 2635 BinarySmiOpInstr* shift_left) {
2680 const LocationSummary& locs = *shift_left->locs(); 2636 const LocationSummary& locs = *shift_left->locs();
2681 Register left = locs.in(0).reg(); 2637 Register left = locs.in(0).reg();
2682 Register result = locs.out(0).reg(); 2638 Register result = locs.out(0).reg();
2683 ASSERT(left == result); 2639 ASSERT(left == result);
2684 Label* deopt = shift_left->CanDeoptimize() ? 2640 Label* deopt = shift_left->CanDeoptimize()
2685 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) 2641 ? compiler->AddDeoptStub(shift_left->deopt_id(),
2686 : NULL; 2642 ICData::kDeoptBinarySmiOp)
2643 : NULL;
2687 if (locs.in(1).IsConstant()) { 2644 if (locs.in(1).IsConstant()) {
2688 const Object& constant = locs.in(1).constant(); 2645 const Object& constant = locs.in(1).constant();
2689 ASSERT(constant.IsSmi()); 2646 ASSERT(constant.IsSmi());
2690 // shll operation masks the count to 5 bits. 2647 // shll operation masks the count to 5 bits.
2691 const intptr_t kCountLimit = 0x1F; 2648 const intptr_t kCountLimit = 0x1F;
2692 const intptr_t value = Smi::Cast(constant).Value(); 2649 const intptr_t value = Smi::Cast(constant).Value();
2693 ASSERT((0 < value) && (value < kCountLimit)); 2650 ASSERT((0 < value) && (value < kCountLimit));
2694 if (shift_left->can_overflow()) { 2651 if (shift_left->can_overflow()) {
2695 if (value == 1) { 2652 if (value == 1) {
2696 // Use overflow flag. 2653 // Use overflow flag.
(...skipping 26 matching lines...) Expand all
2723 if (left_int == 0) { 2680 if (left_int == 0) {
2724 __ cmpl(right, Immediate(0)); 2681 __ cmpl(right, Immediate(0));
2725 __ j(NEGATIVE, deopt); 2682 __ j(NEGATIVE, deopt);
2726 return; 2683 return;
2727 } 2684 }
2728 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); 2685 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
2729 const bool right_needs_check = 2686 const bool right_needs_check =
2730 !RangeUtils::IsWithin(right_range, 0, max_right - 1); 2687 !RangeUtils::IsWithin(right_range, 0, max_right - 1);
2731 if (right_needs_check) { 2688 if (right_needs_check) {
2732 __ cmpl(right, 2689 __ cmpl(right,
2733 Immediate(reinterpret_cast<int32_t>(Smi::New(max_right)))); 2690 Immediate(reinterpret_cast<int32_t>(Smi::New(max_right))));
2734 __ j(ABOVE_EQUAL, deopt); 2691 __ j(ABOVE_EQUAL, deopt);
2735 } 2692 }
2736 __ SmiUntag(right); 2693 __ SmiUntag(right);
2737 __ shll(left, right); 2694 __ shll(left, right);
2738 } 2695 }
2739 return; 2696 return;
2740 } 2697 }
2741 2698
2742 const bool right_needs_check = 2699 const bool right_needs_check =
2743 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); 2700 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1));
2744 ASSERT(right == ECX); // Count must be in ECX 2701 ASSERT(right == ECX); // Count must be in ECX
2745 if (!shift_left->can_overflow()) { 2702 if (!shift_left->can_overflow()) {
2746 if (right_needs_check) { 2703 if (right_needs_check) {
2747 const bool right_may_be_negative = 2704 const bool right_may_be_negative =
2748 (right_range == NULL) || !right_range->IsPositive(); 2705 (right_range == NULL) || !right_range->IsPositive();
2749 if (right_may_be_negative) { 2706 if (right_may_be_negative) {
2750 ASSERT(shift_left->CanDeoptimize()); 2707 ASSERT(shift_left->CanDeoptimize());
2751 __ cmpl(right, Immediate(0)); 2708 __ cmpl(right, Immediate(0));
2752 __ j(NEGATIVE, deopt); 2709 __ j(NEGATIVE, deopt);
2753 } 2710 }
2754 Label done, is_not_zero; 2711 Label done, is_not_zero;
2755 __ cmpl(right, 2712 __ cmpl(right,
2756 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); 2713 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
2757 __ j(BELOW, &is_not_zero, Assembler::kNearJump); 2714 __ j(BELOW, &is_not_zero, Assembler::kNearJump);
2758 __ xorl(left, left); 2715 __ xorl(left, left);
2759 __ jmp(&done, Assembler::kNearJump); 2716 __ jmp(&done, Assembler::kNearJump);
2760 __ Bind(&is_not_zero); 2717 __ Bind(&is_not_zero);
2761 __ SmiUntag(right); 2718 __ SmiUntag(right);
2762 __ shll(left, right); 2719 __ shll(left, right);
2763 __ Bind(&done); 2720 __ Bind(&done);
2764 } else { 2721 } else {
2765 __ SmiUntag(right); 2722 __ SmiUntag(right);
2766 __ shll(left, right); 2723 __ shll(left, right);
2767 } 2724 }
2768 } else { 2725 } else {
2769 if (right_needs_check) { 2726 if (right_needs_check) {
2770 ASSERT(shift_left->CanDeoptimize()); 2727 ASSERT(shift_left->CanDeoptimize());
2771 __ cmpl(right, 2728 __ cmpl(right,
2772 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); 2729 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
2773 __ j(ABOVE_EQUAL, deopt); 2730 __ j(ABOVE_EQUAL, deopt);
2774 } 2731 }
2775 // Left is not a constant. 2732 // Left is not a constant.
2776 Register temp = locs.temp(0).reg(); 2733 Register temp = locs.temp(0).reg();
2777 // Check if count too large for handling it inlined. 2734 // Check if count too large for handling it inlined.
2778 __ movl(temp, left); 2735 __ movl(temp, left);
2779 __ SmiUntag(right); 2736 __ SmiUntag(right);
2780 // Overflow test (preserve temp and right); 2737 // Overflow test (preserve temp and right);
2781 __ shll(left, right); 2738 __ shll(left, right);
2782 __ sarl(left, right); 2739 __ sarl(left, right);
(...skipping 13 matching lines...) Expand all
2796 } 2753 }
2797 2754
2798 2755
2799 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2756 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2800 // Only for precompiled code, not on ia32 currently. 2757 // Only for precompiled code, not on ia32 currently.
2801 UNIMPLEMENTED(); 2758 UNIMPLEMENTED();
2802 } 2759 }
2803 2760
2804 2761
2805 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( 2762 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary(
2806 Zone* zone, bool opt) const { 2763 Zone* zone,
2764 bool opt) const {
2807 // Only for precompiled code, not on ia32 currently. 2765 // Only for precompiled code, not on ia32 currently.
2808 UNIMPLEMENTED(); 2766 UNIMPLEMENTED();
2809 return NULL; 2767 return NULL;
2810 } 2768 }
2811 2769
2812 2770
2813 Condition CheckedSmiComparisonInstr::EmitComparisonCode( 2771 Condition CheckedSmiComparisonInstr::EmitComparisonCode(
2814 FlowGraphCompiler* compiler, BranchLabels labels) { 2772 FlowGraphCompiler* compiler,
2773 BranchLabels labels) {
2815 // Only for precompiled code, not on ia32 currently. 2774 // Only for precompiled code, not on ia32 currently.
2816 UNIMPLEMENTED(); 2775 UNIMPLEMENTED();
2817 return ZERO; 2776 return ZERO;
2818 } 2777 }
2819 2778
2820 2779
2821 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, 2780 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
2822 BranchInstr* instr) { 2781 BranchInstr* instr) {
2823 // Only for precompiled code, not on ia32 currently. 2782 // Only for precompiled code, not on ia32 currently.
2824 UNIMPLEMENTED(); 2783 UNIMPLEMENTED();
2825 } 2784 }
2826 2785
2827 2786
2828 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2787 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2829 // Only for precompiled code, not on ia32 currently. 2788 // Only for precompiled code, not on ia32 currently.
2830 UNIMPLEMENTED(); 2789 UNIMPLEMENTED();
2831 } 2790 }
2832 2791
2833 2792
2834 static bool IsSmiValue(const Object& constant, intptr_t value) { 2793 static bool IsSmiValue(const Object& constant, intptr_t value) {
2835 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); 2794 return constant.IsSmi() && (Smi::Cast(constant).Value() == value);
2836 } 2795 }
2837 2796
2838 2797
2839 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, 2798 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone,
2840 bool opt) const { 2799 bool opt) const {
2841 const intptr_t kNumInputs = 2; 2800 const intptr_t kNumInputs = 2;
2842 if (op_kind() == Token::kTRUNCDIV) { 2801 if (op_kind() == Token::kTRUNCDIV) {
2843 const intptr_t kNumTemps = 1; 2802 const intptr_t kNumTemps = 1;
2844 LocationSummary* summary = new(zone) LocationSummary( 2803 LocationSummary* summary = new (zone)
2845 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 2804 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
2846 if (RightIsPowerOfTwoConstant()) { 2805 if (RightIsPowerOfTwoConstant()) {
2847 summary->set_in(0, Location::RequiresRegister()); 2806 summary->set_in(0, Location::RequiresRegister());
2848 ConstantInstr* right_constant = right()->definition()->AsConstant(); 2807 ConstantInstr* right_constant = right()->definition()->AsConstant();
2849 // The programmer only controls one bit, so the constant is safe. 2808 // The programmer only controls one bit, so the constant is safe.
2850 summary->set_in(1, Location::Constant(right_constant)); 2809 summary->set_in(1, Location::Constant(right_constant));
2851 summary->set_temp(0, Location::RequiresRegister()); 2810 summary->set_temp(0, Location::RequiresRegister());
2852 summary->set_out(0, Location::SameAsFirstInput()); 2811 summary->set_out(0, Location::SameAsFirstInput());
2853 } else { 2812 } else {
2854 // Both inputs must be writable because they will be untagged. 2813 // Both inputs must be writable because they will be untagged.
2855 summary->set_in(0, Location::RegisterLocation(EAX)); 2814 summary->set_in(0, Location::RegisterLocation(EAX));
2856 summary->set_in(1, Location::WritableRegister()); 2815 summary->set_in(1, Location::WritableRegister());
2857 summary->set_out(0, Location::SameAsFirstInput()); 2816 summary->set_out(0, Location::SameAsFirstInput());
2858 // Will be used for sign extension and division. 2817 // Will be used for sign extension and division.
2859 summary->set_temp(0, Location::RegisterLocation(EDX)); 2818 summary->set_temp(0, Location::RegisterLocation(EDX));
2860 } 2819 }
2861 return summary; 2820 return summary;
2862 } else if (op_kind() == Token::kMOD) { 2821 } else if (op_kind() == Token::kMOD) {
2863 const intptr_t kNumTemps = 1; 2822 const intptr_t kNumTemps = 1;
2864 LocationSummary* summary = new(zone) LocationSummary( 2823 LocationSummary* summary = new (zone)
2865 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 2824 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
2866 // Both inputs must be writable because they will be untagged. 2825 // Both inputs must be writable because they will be untagged.
2867 summary->set_in(0, Location::RegisterLocation(EDX)); 2826 summary->set_in(0, Location::RegisterLocation(EDX));
2868 summary->set_in(1, Location::WritableRegister()); 2827 summary->set_in(1, Location::WritableRegister());
2869 summary->set_out(0, Location::SameAsFirstInput()); 2828 summary->set_out(0, Location::SameAsFirstInput());
2870 // Will be used for sign extension and division. 2829 // Will be used for sign extension and division.
2871 summary->set_temp(0, Location::RegisterLocation(EAX)); 2830 summary->set_temp(0, Location::RegisterLocation(EAX));
2872 return summary; 2831 return summary;
2873 } else if (op_kind() == Token::kSHR) { 2832 } else if (op_kind() == Token::kSHR) {
2874 const intptr_t kNumTemps = 0; 2833 const intptr_t kNumTemps = 0;
2875 LocationSummary* summary = new(zone) LocationSummary( 2834 LocationSummary* summary = new (zone)
2876 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 2835 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
2877 summary->set_in(0, Location::RequiresRegister()); 2836 summary->set_in(0, Location::RequiresRegister());
2878 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); 2837 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
2879 summary->set_out(0, Location::SameAsFirstInput()); 2838 summary->set_out(0, Location::SameAsFirstInput());
2880 return summary; 2839 return summary;
2881 } else if (op_kind() == Token::kSHL) { 2840 } else if (op_kind() == Token::kSHL) {
2882 ConstantInstr* right_constant = right()->definition()->AsConstant(); 2841 ConstantInstr* right_constant = right()->definition()->AsConstant();
2883 // Shift-by-1 overflow checking can use flags, otherwise we need a temp. 2842 // Shift-by-1 overflow checking can use flags, otherwise we need a temp.
2884 const bool shiftBy1 = 2843 const bool shiftBy1 =
2885 (right_constant != NULL) && IsSmiValue(right_constant->value(), 1); 2844 (right_constant != NULL) && IsSmiValue(right_constant->value(), 1);
2886 const intptr_t kNumTemps = (can_overflow() && !shiftBy1) ? 1 : 0; 2845 const intptr_t kNumTemps = (can_overflow() && !shiftBy1) ? 1 : 0;
2887 LocationSummary* summary = new(zone) LocationSummary( 2846 LocationSummary* summary = new (zone)
2888 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 2847 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
2889 summary->set_in(0, Location::RequiresRegister()); 2848 summary->set_in(0, Location::RequiresRegister());
2890 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); 2849 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
2891 if (kNumTemps == 1) { 2850 if (kNumTemps == 1) {
2892 summary->set_temp(0, Location::RequiresRegister()); 2851 summary->set_temp(0, Location::RequiresRegister());
2893 } 2852 }
2894 summary->set_out(0, Location::SameAsFirstInput()); 2853 summary->set_out(0, Location::SameAsFirstInput());
2895 return summary; 2854 return summary;
2896 } else { 2855 } else {
2897 const intptr_t kNumTemps = 0; 2856 const intptr_t kNumTemps = 0;
2898 LocationSummary* summary = new(zone) LocationSummary( 2857 LocationSummary* summary = new (zone)
2899 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 2858 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
2900 summary->set_in(0, Location::RequiresRegister()); 2859 summary->set_in(0, Location::RequiresRegister());
2901 ConstantInstr* constant = right()->definition()->AsConstant(); 2860 ConstantInstr* constant = right()->definition()->AsConstant();
2902 if (constant != NULL) { 2861 if (constant != NULL) {
2903 summary->set_in(1, Location::RegisterOrSmiConstant(right())); 2862 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
2904 } else { 2863 } else {
2905 summary->set_in(1, Location::PrefersRegister()); 2864 summary->set_in(1, Location::PrefersRegister());
2906 } 2865 }
2907 summary->set_out(0, Location::SameAsFirstInput()); 2866 summary->set_out(0, Location::SameAsFirstInput());
2908 return summary; 2867 return summary;
2909 } 2868 }
2910 } 2869 }
2911 2870
2912 2871
2913 template<typename OperandType> 2872 template <typename OperandType>
2914 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, 2873 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler,
2915 Token::Kind op_kind, 2874 Token::Kind op_kind,
2916 Register left, 2875 Register left,
2917 const OperandType& right, 2876 const OperandType& right,
2918 Label* deopt) { 2877 Label* deopt) {
2919 switch (op_kind) { 2878 switch (op_kind) {
2920 case Token::kADD: 2879 case Token::kADD:
2921 __ addl(left, right); 2880 __ addl(left, right);
2922 break; 2881 break;
2923 case Token::kSUB: 2882 case Token::kSUB:
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2960 const Object& constant = locs()->in(1).constant(); 2919 const Object& constant = locs()->in(1).constant();
2961 ASSERT(constant.IsSmi()); 2920 ASSERT(constant.IsSmi());
2962 const intptr_t value = Smi::Cast(constant).Value(); 2921 const intptr_t value = Smi::Cast(constant).Value();
2963 switch (op_kind()) { 2922 switch (op_kind()) {
2964 case Token::kADD: 2923 case Token::kADD:
2965 case Token::kSUB: 2924 case Token::kSUB:
2966 case Token::kBIT_AND: 2925 case Token::kBIT_AND:
2967 case Token::kBIT_OR: 2926 case Token::kBIT_OR:
2968 case Token::kBIT_XOR: 2927 case Token::kBIT_XOR:
2969 case Token::kMUL: { 2928 case Token::kMUL: {
2970 const intptr_t imm = (op_kind() == Token::kMUL) ? value 2929 const intptr_t imm =
2971 : Smi::RawValue(value); 2930 (op_kind() == Token::kMUL) ? value : Smi::RawValue(value);
2972 EmitIntegerArithmetic(compiler, 2931 EmitIntegerArithmetic(compiler, op_kind(), left, Immediate(imm), deopt);
2973 op_kind(),
2974 left,
2975 Immediate(imm),
2976 deopt);
2977 break; 2932 break;
2978 } 2933 }
2979 2934
2980 case Token::kTRUNCDIV: { 2935 case Token::kTRUNCDIV: {
2981 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); 2936 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value)));
2982 const intptr_t shift_count = 2937 const intptr_t shift_count =
2983 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; 2938 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
2984 ASSERT(kSmiTagSize == 1); 2939 ASSERT(kSmiTagSize == 1);
2985 Register temp = locs()->temp(0).reg(); 2940 Register temp = locs()->temp(0).reg();
2986 __ movl(temp, left); 2941 __ movl(temp, left);
2987 __ sarl(temp, Immediate(31)); 2942 __ sarl(temp, Immediate(31));
2988 ASSERT(shift_count > 1); // 1, -1 case handled above. 2943 ASSERT(shift_count > 1); // 1, -1 case handled above.
2989 __ shrl(temp, Immediate(32 - shift_count)); 2944 __ shrl(temp, Immediate(32 - shift_count));
2990 __ addl(left, temp); 2945 __ addl(left, temp);
2991 ASSERT(shift_count > 0); 2946 ASSERT(shift_count > 0);
2992 __ sarl(left, Immediate(shift_count)); 2947 __ sarl(left, Immediate(shift_count));
2993 if (value < 0) { 2948 if (value < 0) {
2994 __ negl(left); 2949 __ negl(left);
2995 } 2950 }
2996 __ SmiTag(left); 2951 __ SmiTag(left);
2997 break; 2952 break;
2998 } 2953 }
2999 2954
3000 case Token::kSHR: { 2955 case Token::kSHR: {
3001 // sarl operation masks the count to 5 bits. 2956 // sarl operation masks the count to 5 bits.
3002 const intptr_t kCountLimit = 0x1F; 2957 const intptr_t kCountLimit = 0x1F;
3003 __ sarl(left, Immediate( 2958 __ sarl(left,
3004 Utils::Minimum(value + kSmiTagSize, kCountLimit))); 2959 Immediate(Utils::Minimum(value + kSmiTagSize, kCountLimit)));
3005 __ SmiTag(left); 2960 __ SmiTag(left);
3006 break; 2961 break;
3007 } 2962 }
3008 2963
3009 default: 2964 default:
3010 UNREACHABLE(); 2965 UNREACHABLE();
3011 break; 2966 break;
3012 } 2967 }
3013 return; 2968 return;
3014 } // if locs()->in(1).IsConstant() 2969 } // if locs()->in(1).IsConstant()
(...skipping 29 matching lines...) Expand all
3044 // Handle divide by zero in runtime. 2999 // Handle divide by zero in runtime.
3045 __ testl(right, right); 3000 __ testl(right, right);
3046 __ j(ZERO, deopt); 3001 __ j(ZERO, deopt);
3047 } 3002 }
3048 ASSERT(left == EAX); 3003 ASSERT(left == EAX);
3049 ASSERT((right != EDX) && (right != EAX)); 3004 ASSERT((right != EDX) && (right != EAX));
3050 ASSERT(locs()->temp(0).reg() == EDX); 3005 ASSERT(locs()->temp(0).reg() == EDX);
3051 ASSERT(result == EAX); 3006 ASSERT(result == EAX);
3052 __ SmiUntag(left); 3007 __ SmiUntag(left);
3053 __ SmiUntag(right); 3008 __ SmiUntag(right);
3054 __ cdq(); // Sign extend EAX -> EDX:EAX. 3009 __ cdq(); // Sign extend EAX -> EDX:EAX.
3055 __ idivl(right); // EAX: quotient, EDX: remainder. 3010 __ idivl(right); // EAX: quotient, EDX: remainder.
3056 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 3011 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
3057 // case we cannot tag the result. 3012 // case we cannot tag the result.
3058 __ cmpl(result, Immediate(0x40000000)); 3013 __ cmpl(result, Immediate(0x40000000));
3059 __ j(EQUAL, deopt); 3014 __ j(EQUAL, deopt);
3060 __ SmiTag(result); 3015 __ SmiTag(result);
3061 break; 3016 break;
3062 } 3017 }
3063 case Token::kMOD: { 3018 case Token::kMOD: {
3064 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 3019 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
3065 // Handle divide by zero in runtime. 3020 // Handle divide by zero in runtime.
3066 __ testl(right, right); 3021 __ testl(right, right);
3067 __ j(ZERO, deopt); 3022 __ j(ZERO, deopt);
3068 } 3023 }
3069 ASSERT(left == EDX); 3024 ASSERT(left == EDX);
3070 ASSERT((right != EDX) && (right != EAX)); 3025 ASSERT((right != EDX) && (right != EAX));
3071 ASSERT(locs()->temp(0).reg() == EAX); 3026 ASSERT(locs()->temp(0).reg() == EAX);
3072 ASSERT(result == EDX); 3027 ASSERT(result == EDX);
3073 __ SmiUntag(left); 3028 __ SmiUntag(left);
3074 __ SmiUntag(right); 3029 __ SmiUntag(right);
3075 __ movl(EAX, EDX); 3030 __ movl(EAX, EDX);
3076 __ cdq(); // Sign extend EAX -> EDX:EAX. 3031 __ cdq(); // Sign extend EAX -> EDX:EAX.
3077 __ idivl(right); // EAX: quotient, EDX: remainder. 3032 __ idivl(right); // EAX: quotient, EDX: remainder.
3078 // res = left % right; 3033 // res = left % right;
3079 // if (res < 0) { 3034 // if (res < 0) {
3080 // if (right < 0) { 3035 // if (right < 0) {
3081 // res = res - right; 3036 // res = res - right;
3082 // } else { 3037 // } else {
3083 // res = res + right; 3038 // res = res + right;
3084 // } 3039 // }
3085 // } 3040 // }
3086 Label done; 3041 Label done;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
3149 } 3104 }
3150 3105
3151 3106
3152 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone, 3107 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone,
3153 bool opt) const { 3108 bool opt) const {
3154 const intptr_t kNumInputs = 2; 3109 const intptr_t kNumInputs = 2;
3155 if (op_kind() == Token::kTRUNCDIV) { 3110 if (op_kind() == Token::kTRUNCDIV) {
3156 UNREACHABLE(); 3111 UNREACHABLE();
3157 return NULL; 3112 return NULL;
3158 } else if (op_kind() == Token::kMOD) { 3113 } else if (op_kind() == Token::kMOD) {
3159 UNREACHABLE(); 3114 UNREACHABLE();
3160 return NULL; 3115 return NULL;
3161 } else if (op_kind() == Token::kSHR) { 3116 } else if (op_kind() == Token::kSHR) {
3162 const intptr_t kNumTemps = 0; 3117 const intptr_t kNumTemps = 0;
3163 LocationSummary* summary = new(zone) LocationSummary( 3118 LocationSummary* summary = new (zone)
3164 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3119 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3165 summary->set_in(0, Location::RequiresRegister()); 3120 summary->set_in(0, Location::RequiresRegister());
3166 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); 3121 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
3167 summary->set_out(0, Location::SameAsFirstInput()); 3122 summary->set_out(0, Location::SameAsFirstInput());
3168 return summary; 3123 return summary;
3169 } else if (op_kind() == Token::kSHL) { 3124 } else if (op_kind() == Token::kSHL) {
3170 const intptr_t kNumTemps = can_overflow() ? 1 : 0; 3125 const intptr_t kNumTemps = can_overflow() ? 1 : 0;
3171 LocationSummary* summary = new(zone) LocationSummary( 3126 LocationSummary* summary = new (zone)
3172 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3127 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3173 summary->set_in(0, Location::RequiresRegister()); 3128 summary->set_in(0, Location::RequiresRegister());
3174 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); 3129 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
3175 if (can_overflow()) { 3130 if (can_overflow()) {
3176 summary->set_temp(0, Location::RequiresRegister()); 3131 summary->set_temp(0, Location::RequiresRegister());
3177 } 3132 }
3178 summary->set_out(0, Location::SameAsFirstInput()); 3133 summary->set_out(0, Location::SameAsFirstInput());
3179 return summary; 3134 return summary;
3180 } else { 3135 } else {
3181 const intptr_t kNumTemps = 0; 3136 const intptr_t kNumTemps = 0;
3182 LocationSummary* summary = new(zone) LocationSummary( 3137 LocationSummary* summary = new (zone)
3183 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3138 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3184 summary->set_in(0, Location::RequiresRegister()); 3139 summary->set_in(0, Location::RequiresRegister());
3185 ConstantInstr* constant = right()->definition()->AsConstant(); 3140 ConstantInstr* constant = right()->definition()->AsConstant();
3186 if (constant != NULL) { 3141 if (constant != NULL) {
3187 summary->set_in(1, Location::RegisterOrSmiConstant(right())); 3142 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
3188 } else { 3143 } else {
3189 summary->set_in(1, Location::PrefersRegister()); 3144 summary->set_in(1, Location::PrefersRegister());
3190 } 3145 }
3191 summary->set_out(0, Location::SameAsFirstInput()); 3146 summary->set_out(0, Location::SameAsFirstInput());
3192 return summary; 3147 return summary;
3193 } 3148 }
3194 } 3149 }
3195 3150
3196 3151
3197 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler, 3152 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler,
3198 BinaryInt32OpInstr* shift_left) { 3153 BinaryInt32OpInstr* shift_left) {
3199 const LocationSummary& locs = *shift_left->locs(); 3154 const LocationSummary& locs = *shift_left->locs();
3200 Register left = locs.in(0).reg(); 3155 Register left = locs.in(0).reg();
3201 Register result = locs.out(0).reg(); 3156 Register result = locs.out(0).reg();
3202 ASSERT(left == result); 3157 ASSERT(left == result);
3203 Label* deopt = shift_left->CanDeoptimize() ? 3158 Label* deopt = shift_left->CanDeoptimize()
3204 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) 3159 ? compiler->AddDeoptStub(shift_left->deopt_id(),
3205 : NULL; 3160 ICData::kDeoptBinarySmiOp)
3161 : NULL;
3206 ASSERT(locs.in(1).IsConstant()); 3162 ASSERT(locs.in(1).IsConstant());
3207 3163
3208 const Object& constant = locs.in(1).constant(); 3164 const Object& constant = locs.in(1).constant();
3209 ASSERT(constant.IsSmi()); 3165 ASSERT(constant.IsSmi());
3210 // shll operation masks the count to 5 bits. 3166 // shll operation masks the count to 5 bits.
3211 const intptr_t kCountLimit = 0x1F; 3167 const intptr_t kCountLimit = 0x1F;
3212 const intptr_t value = Smi::Cast(constant).Value(); 3168 const intptr_t value = Smi::Cast(constant).Value();
3213 ASSERT((0 < value) && (value < kCountLimit)); 3169 ASSERT((0 < value) && (value < kCountLimit));
3214 if (shift_left->can_overflow()) { 3170 if (shift_left->can_overflow()) {
3215 // Check for overflow. 3171 // Check for overflow.
(...skipping 13 matching lines...) Expand all
3229 if (op_kind() == Token::kSHL) { 3185 if (op_kind() == Token::kSHL) {
3230 EmitInt32ShiftLeft(compiler, this); 3186 EmitInt32ShiftLeft(compiler, this);
3231 return; 3187 return;
3232 } 3188 }
3233 3189
3234 Register left = locs()->in(0).reg(); 3190 Register left = locs()->in(0).reg();
3235 Register result = locs()->out(0).reg(); 3191 Register result = locs()->out(0).reg();
3236 ASSERT(left == result); 3192 ASSERT(left == result);
3237 Label* deopt = NULL; 3193 Label* deopt = NULL;
3238 if (CanDeoptimize()) { 3194 if (CanDeoptimize()) {
3239 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); 3195 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
3240 } 3196 }
3241 3197
3242 if (locs()->in(1).IsConstant()) { 3198 if (locs()->in(1).IsConstant()) {
3243 const Object& constant = locs()->in(1).constant(); 3199 const Object& constant = locs()->in(1).constant();
3244 ASSERT(constant.IsSmi()); 3200 ASSERT(constant.IsSmi());
3245 const intptr_t value = Smi::Cast(constant).Value(); 3201 const intptr_t value = Smi::Cast(constant).Value();
3246 switch (op_kind()) { 3202 switch (op_kind()) {
3247 case Token::kADD: 3203 case Token::kADD:
3248 case Token::kSUB: 3204 case Token::kSUB:
3249 case Token::kMUL: 3205 case Token::kMUL:
3250 case Token::kBIT_AND: 3206 case Token::kBIT_AND:
3251 case Token::kBIT_OR: 3207 case Token::kBIT_OR:
3252 case Token::kBIT_XOR: 3208 case Token::kBIT_XOR:
3253 EmitIntegerArithmetic(compiler, 3209 EmitIntegerArithmetic(compiler, op_kind(), left, Immediate(value),
3254 op_kind(),
3255 left,
3256 Immediate(value),
3257 deopt); 3210 deopt);
3258 break; 3211 break;
3259 3212
3260 3213
3261
3262 case Token::kTRUNCDIV: { 3214 case Token::kTRUNCDIV: {
3263 UNREACHABLE(); 3215 UNREACHABLE();
3264 break; 3216 break;
3265 } 3217 }
3266 3218
3267 case Token::kSHR: { 3219 case Token::kSHR: {
3268 // sarl operation masks the count to 5 bits. 3220 // sarl operation masks the count to 5 bits.
3269 const intptr_t kCountLimit = 0x1F; 3221 const intptr_t kCountLimit = 0x1F;
3270 __ sarl(left, Immediate(Utils::Minimum(value, kCountLimit))); 3222 __ sarl(left, Immediate(Utils::Minimum(value, kCountLimit)));
3271 break; 3223 break;
3272 } 3224 }
3273 3225
3274 default: 3226 default:
3275 UNREACHABLE(); 3227 UNREACHABLE();
3276 break; 3228 break;
3277 } 3229 }
3278 return; 3230 return;
3279 } // if locs()->in(1).IsConstant() 3231 } // if locs()->in(1).IsConstant()
3280 3232
3281 if (locs()->in(1).IsStackSlot()) { 3233 if (locs()->in(1).IsStackSlot()) {
3282 const Address& right = locs()->in(1).ToStackSlotAddress(); 3234 const Address& right = locs()->in(1).ToStackSlotAddress();
3283 EmitIntegerArithmetic(compiler, 3235 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt);
3284 op_kind(),
3285 left,
3286 right,
3287 deopt);
3288 return; 3236 return;
3289 } // if locs()->in(1).IsStackSlot. 3237 } // if locs()->in(1).IsStackSlot.
3290 3238
3291 // if locs()->in(1).IsRegister. 3239 // if locs()->in(1).IsRegister.
3292 Register right = locs()->in(1).reg(); 3240 Register right = locs()->in(1).reg();
3293 switch (op_kind()) { 3241 switch (op_kind()) {
3294 case Token::kADD: 3242 case Token::kADD:
3295 case Token::kSUB: 3243 case Token::kSUB:
3296 case Token::kMUL: 3244 case Token::kMUL:
3297 case Token::kBIT_AND: 3245 case Token::kBIT_AND:
3298 case Token::kBIT_OR: 3246 case Token::kBIT_OR:
3299 case Token::kBIT_XOR: 3247 case Token::kBIT_XOR:
3300 EmitIntegerArithmetic(compiler, 3248 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt);
3301 op_kind(),
3302 left,
3303 right,
3304 deopt);
3305 break; 3249 break;
3306 3250
3307 default: 3251 default:
3308 UNREACHABLE(); 3252 UNREACHABLE();
3309 break; 3253 break;
3310 } 3254 }
3311 } 3255 }
3312 3256
3313 3257
3314 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, 3258 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone,
3315 bool opt) const { 3259 bool opt) const {
3316 const intptr_t kNumInputs = 2; 3260 const intptr_t kNumInputs = 2;
3317 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; 3261 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0;
3318 LocationSummary* summary = new(zone) LocationSummary( 3262 LocationSummary* summary = new (zone)
3319 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3263 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3320 if (op_kind() == Token::kMUL) { 3264 if (op_kind() == Token::kMUL) {
3321 summary->set_in(0, Location::RegisterLocation(EAX)); 3265 summary->set_in(0, Location::RegisterLocation(EAX));
3322 summary->set_temp(0, Location::RegisterLocation(EDX)); 3266 summary->set_temp(0, Location::RegisterLocation(EDX));
3323 } else { 3267 } else {
3324 summary->set_in(0, Location::RequiresRegister()); 3268 summary->set_in(0, Location::RequiresRegister());
3325 } 3269 }
3326 summary->set_in(1, Location::RequiresRegister()); 3270 summary->set_in(1, Location::RequiresRegister());
3327 summary->set_out(0, Location::SameAsFirstInput()); 3271 summary->set_out(0, Location::SameAsFirstInput());
3328 return summary; 3272 return summary;
3329 } 3273 }
(...skipping 23 matching lines...) Expand all
3353 } 3297 }
3354 } 3298 }
3355 3299
3356 3300
3357 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, 3301 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone,
3358 bool opt) const { 3302 bool opt) const {
3359 intptr_t left_cid = left()->Type()->ToCid(); 3303 intptr_t left_cid = left()->Type()->ToCid();
3360 intptr_t right_cid = right()->Type()->ToCid(); 3304 intptr_t right_cid = right()->Type()->ToCid();
3361 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); 3305 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
3362 const intptr_t kNumInputs = 2; 3306 const intptr_t kNumInputs = 2;
3363 const bool need_temp = (left()->definition() != right()->definition()) 3307 const bool need_temp = (left()->definition() != right()->definition()) &&
3364 && (left_cid != kSmiCid) 3308 (left_cid != kSmiCid) && (right_cid != kSmiCid);
3365 && (right_cid != kSmiCid);
3366 const intptr_t kNumTemps = need_temp ? 1 : 0; 3309 const intptr_t kNumTemps = need_temp ? 1 : 0;
3367 LocationSummary* summary = new(zone) LocationSummary( 3310 LocationSummary* summary = new (zone)
3368 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3311 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3369 summary->set_in(0, Location::RequiresRegister()); 3312 summary->set_in(0, Location::RequiresRegister());
3370 summary->set_in(1, Location::RequiresRegister()); 3313 summary->set_in(1, Location::RequiresRegister());
3371 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); 3314 if (need_temp) summary->set_temp(0, Location::RequiresRegister());
3372 return summary; 3315 return summary;
3373 } 3316 }
3374 3317
3375 3318
3376 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3319 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3377 Label* deopt = compiler->AddDeoptStub(deopt_id(), 3320 Label* deopt =
3378 ICData::kDeoptBinaryDoubleOp, 3321 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp,
3379 licm_hoisted_ ? ICData::kHoisted : 0); 3322 licm_hoisted_ ? ICData::kHoisted : 0);
3380 intptr_t left_cid = left()->Type()->ToCid(); 3323 intptr_t left_cid = left()->Type()->ToCid();
3381 intptr_t right_cid = right()->Type()->ToCid(); 3324 intptr_t right_cid = right()->Type()->ToCid();
3382 Register left = locs()->in(0).reg(); 3325 Register left = locs()->in(0).reg();
3383 Register right = locs()->in(1).reg(); 3326 Register right = locs()->in(1).reg();
3384 if (this->left()->definition() == this->right()->definition()) { 3327 if (this->left()->definition() == this->right()->definition()) {
3385 __ testl(left, Immediate(kSmiTagMask)); 3328 __ testl(left, Immediate(kSmiTagMask));
3386 } else if (left_cid == kSmiCid) { 3329 } else if (left_cid == kSmiCid) {
3387 __ testl(right, Immediate(kSmiTagMask)); 3330 __ testl(right, Immediate(kSmiTagMask));
3388 } else if (right_cid == kSmiCid) { 3331 } else if (right_cid == kSmiCid) {
3389 __ testl(left, Immediate(kSmiTagMask)); 3332 __ testl(left, Immediate(kSmiTagMask));
3390 } else { 3333 } else {
3391 Register temp = locs()->temp(0).reg(); 3334 Register temp = locs()->temp(0).reg();
3392 __ movl(temp, left); 3335 __ movl(temp, left);
3393 __ orl(temp, right); 3336 __ orl(temp, right);
3394 __ testl(temp, Immediate(kSmiTagMask)); 3337 __ testl(temp, Immediate(kSmiTagMask));
3395 } 3338 }
3396 __ j(ZERO, deopt); 3339 __ j(ZERO, deopt);
3397 } 3340 }
3398 3341
3399 3342
3400 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, 3343 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const {
3401 bool opt) const {
3402 const intptr_t kNumInputs = 1; 3344 const intptr_t kNumInputs = 1;
3403 const intptr_t kNumTemps = 1; 3345 const intptr_t kNumTemps = 1;
3404 LocationSummary* summary = new(zone) LocationSummary( 3346 LocationSummary* summary = new (zone) LocationSummary(
3405 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); 3347 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
3406 summary->set_in(0, Location::RequiresFpuRegister()); 3348 summary->set_in(0, Location::RequiresFpuRegister());
3407 summary->set_temp(0, Location::RequiresRegister()); 3349 summary->set_temp(0, Location::RequiresRegister());
3408 summary->set_out(0, Location::RequiresRegister()); 3350 summary->set_out(0, Location::RequiresRegister());
3409 return summary; 3351 return summary;
3410 } 3352 }
3411 3353
3412 3354
3413 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3355 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3414 Register out_reg = locs()->out(0).reg(); 3356 Register out_reg = locs()->out(0).reg();
3415 XmmRegister value = locs()->in(0).fpu_reg(); 3357 XmmRegister value = locs()->in(0).fpu_reg();
3416 3358
3417 BoxAllocationSlowPath::Allocate( 3359 BoxAllocationSlowPath::Allocate(compiler, this,
3418 compiler, 3360 compiler->BoxClassFor(from_representation()),
3419 this, 3361 out_reg, locs()->temp(0).reg());
3420 compiler->BoxClassFor(from_representation()),
3421 out_reg,
3422 locs()->temp(0).reg());
3423 3362
3424 switch (from_representation()) { 3363 switch (from_representation()) {
3425 case kUnboxedDouble: 3364 case kUnboxedDouble:
3426 __ movsd(FieldAddress(out_reg, ValueOffset()), value); 3365 __ movsd(FieldAddress(out_reg, ValueOffset()), value);
3427 break; 3366 break;
3428 case kUnboxedFloat32x4: 3367 case kUnboxedFloat32x4:
3429 case kUnboxedFloat64x2: 3368 case kUnboxedFloat64x2:
3430 case kUnboxedInt32x4: 3369 case kUnboxedInt32x4:
3431 __ movups(FieldAddress(out_reg, ValueOffset()), value); 3370 __ movups(FieldAddress(out_reg, ValueOffset()), value);
3432 break; 3371 break;
3433 default: 3372 default:
3434 UNREACHABLE(); 3373 UNREACHABLE();
3435 break; 3374 break;
3436 } 3375 }
3437 } 3376 }
3438 3377
3439 3378
3440 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, 3379 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const {
3441 bool opt) const { 3380 const bool needs_temp =
3442 const bool needs_temp = CanDeoptimize() || 3381 CanDeoptimize() ||
3443 (CanConvertSmi() && (value()->Type()->ToCid() == kSmiCid)); 3382 (CanConvertSmi() && (value()->Type()->ToCid() == kSmiCid));
3444 3383
3445 const intptr_t kNumInputs = 1; 3384 const intptr_t kNumInputs = 1;
3446 const intptr_t kNumTemps = needs_temp ? 1 : 0; 3385 const intptr_t kNumTemps = needs_temp ? 1 : 0;
3447 LocationSummary* summary = new(zone) LocationSummary( 3386 LocationSummary* summary = new (zone)
3448 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3387 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3449 summary->set_in(0, Location::RequiresRegister()); 3388 summary->set_in(0, Location::RequiresRegister());
3450 if (needs_temp) { 3389 if (needs_temp) {
3451 summary->set_temp(0, Location::RequiresRegister()); 3390 summary->set_temp(0, Location::RequiresRegister());
3452 } 3391 }
3453 if (representation() == kUnboxedMint) { 3392 if (representation() == kUnboxedMint) {
3454 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), 3393 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
3455 Location::RegisterLocation(EDX))); 3394 Location::RegisterLocation(EDX)));
3456 } else { 3395 } else {
3457 summary->set_out(0, Location::RequiresFpuRegister()); 3396 summary->set_out(0, Location::RequiresFpuRegister());
3458 } 3397 }
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
3527 const intptr_t value_cid = value()->Type()->ToCid(); 3466 const intptr_t value_cid = value()->Type()->ToCid();
3528 const intptr_t box_cid = BoxCid(); 3467 const intptr_t box_cid = BoxCid();
3529 3468
3530 if (value_cid == box_cid) { 3469 if (value_cid == box_cid) {
3531 EmitLoadFromBox(compiler); 3470 EmitLoadFromBox(compiler);
3532 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { 3471 } else if (CanConvertSmi() && (value_cid == kSmiCid)) {
3533 EmitSmiConversion(compiler); 3472 EmitSmiConversion(compiler);
3534 } else { 3473 } else {
3535 const Register box = locs()->in(0).reg(); 3474 const Register box = locs()->in(0).reg();
3536 const Register temp = locs()->temp(0).reg(); 3475 const Register temp = locs()->temp(0).reg();
3537 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), 3476 Label* deopt =
3538 ICData::kDeoptCheckClass); 3477 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass);
3539 Label is_smi; 3478 Label is_smi;
3540 3479
3541 if ((value()->Type()->ToNullableCid() == box_cid) && 3480 if ((value()->Type()->ToNullableCid() == box_cid) &&
3542 value()->Type()->is_nullable()) { 3481 value()->Type()->is_nullable()) {
3543 const Immediate& raw_null = 3482 const Immediate& raw_null =
3544 Immediate(reinterpret_cast<intptr_t>(Object::null())); 3483 Immediate(reinterpret_cast<intptr_t>(Object::null()));
3545 __ cmpl(box, raw_null); 3484 __ cmpl(box, raw_null);
3546 __ j(EQUAL, deopt); 3485 __ j(EQUAL, deopt);
3547 } else { 3486 } else {
3548 __ testl(box, Immediate(kSmiTagMask)); 3487 __ testl(box, Immediate(kSmiTagMask));
(...skipping 12 matching lines...) Expand all
3561 __ Bind(&done); 3500 __ Bind(&done);
3562 } 3501 }
3563 } 3502 }
3564 } 3503 }
3565 3504
3566 3505
3567 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, 3506 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone,
3568 bool opt) const { 3507 bool opt) const {
3569 const intptr_t kNumInputs = 1; 3508 const intptr_t kNumInputs = 1;
3570 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; 3509 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
3571 LocationSummary* summary = new(zone) LocationSummary( 3510 LocationSummary* summary = new (zone)
3572 zone, kNumInputs, kNumTemps, 3511 LocationSummary(zone, kNumInputs, kNumTemps,
3573 ValueFitsSmi() ? LocationSummary::kNoCall 3512 ValueFitsSmi() ? LocationSummary::kNoCall
3574 : LocationSummary::kCallOnSlowPath); 3513 : LocationSummary::kCallOnSlowPath);
3575 const bool needs_writable_input = ValueFitsSmi() || 3514 const bool needs_writable_input =
3576 (from_representation() == kUnboxedUint32); 3515 ValueFitsSmi() || (from_representation() == kUnboxedUint32);
3577 summary->set_in(0, needs_writable_input ? Location::RequiresRegister() 3516 summary->set_in(0, needs_writable_input ? Location::RequiresRegister()
3578 : Location::WritableRegister()); 3517 : Location::WritableRegister());
3579 if (!ValueFitsSmi()) { 3518 if (!ValueFitsSmi()) {
3580 summary->set_temp(0, Location::RequiresRegister()); 3519 summary->set_temp(0, Location::RequiresRegister());
3581 } 3520 }
3582 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput() 3521 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput()
3583 : Location::RequiresRegister()); 3522 : Location::RequiresRegister());
3584 return summary; 3523 return summary;
3585 } 3524 }
3586 3525
(...skipping 11 matching lines...) Expand all
3598 __ j(NO_OVERFLOW, &done); 3537 __ j(NO_OVERFLOW, &done);
3599 } else { 3538 } else {
3600 __ testl(value, Immediate(0xC0000000)); 3539 __ testl(value, Immediate(0xC0000000));
3601 __ j(ZERO, &done); 3540 __ j(ZERO, &done);
3602 } 3541 }
3603 3542
3604 // Allocate a mint. 3543 // Allocate a mint.
3605 // Value input is writable register and has to be manually preserved 3544 // Value input is writable register and has to be manually preserved
3606 // on the slow path. 3545 // on the slow path.
3607 locs()->live_registers()->Add(locs()->in(0), kUnboxedInt32); 3546 locs()->live_registers()->Add(locs()->in(0), kUnboxedInt32);
3608 BoxAllocationSlowPath::Allocate( 3547 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
3609 compiler, this, compiler->mint_class(), out, locs()->temp(0).reg()); 3548 locs()->temp(0).reg());
3610 __ movl(FieldAddress(out, Mint::value_offset()), value); 3549 __ movl(FieldAddress(out, Mint::value_offset()), value);
3611 if (from_representation() == kUnboxedInt32) { 3550 if (from_representation() == kUnboxedInt32) {
3612 __ sarl(value, Immediate(31)); // Sign extend. 3551 __ sarl(value, Immediate(31)); // Sign extend.
3613 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value); 3552 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value);
3614 } else { 3553 } else {
3615 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), 3554 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize),
3616 Immediate(0)); 3555 Immediate(0));
3617 } 3556 }
3618 __ Bind(&done); 3557 __ Bind(&done);
3619 } 3558 }
3620 } 3559 }
3621 3560
3622 3561
3623 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, 3562 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
3624 bool opt) const { 3563 bool opt) const {
3625 const intptr_t kNumInputs = 1; 3564 const intptr_t kNumInputs = 1;
3626 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; 3565 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
3627 LocationSummary* summary = new(zone) LocationSummary( 3566 LocationSummary* summary = new (zone)
3628 zone, kNumInputs, 3567 LocationSummary(zone, kNumInputs, kNumTemps,
3629 kNumTemps, 3568 ValueFitsSmi() ? LocationSummary::kNoCall
3630 ValueFitsSmi() 3569 : LocationSummary::kCallOnSlowPath);
3631 ? LocationSummary::kNoCall
3632 : LocationSummary::kCallOnSlowPath);
3633 summary->set_in(0, Location::Pair(Location::RequiresRegister(), 3570 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
3634 Location::RequiresRegister())); 3571 Location::RequiresRegister()));
3635 if (!ValueFitsSmi()) { 3572 if (!ValueFitsSmi()) {
3636 summary->set_temp(0, Location::RequiresRegister()); 3573 summary->set_temp(0, Location::RequiresRegister());
3637 } 3574 }
3638 summary->set_out(0, Location::RequiresRegister()); 3575 summary->set_out(0, Location::RequiresRegister());
3639 return summary; 3576 return summary;
3640 } 3577 }
3641 3578
3642 3579
(...skipping 30 matching lines...) Expand all
3673 __ j(ABOVE_EQUAL, &not_smi); 3610 __ j(ABOVE_EQUAL, &not_smi);
3674 // 3. Restore lower half if result is a smi. 3611 // 3. Restore lower half if result is a smi.
3675 __ subl(value_lo, Immediate(0x40000000)); 3612 __ subl(value_lo, Immediate(0x40000000));
3676 __ movl(out_reg, value_lo); 3613 __ movl(out_reg, value_lo);
3677 __ SmiTag(out_reg); 3614 __ SmiTag(out_reg);
3678 __ jmp(&done); 3615 __ jmp(&done);
3679 __ Bind(&not_smi); 3616 __ Bind(&not_smi);
3680 // 3. Restore lower half of input before using it. 3617 // 3. Restore lower half of input before using it.
3681 __ subl(value_lo, Immediate(0x40000000)); 3618 __ subl(value_lo, Immediate(0x40000000));
3682 3619
3683 BoxAllocationSlowPath::Allocate( 3620 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(),
3684 compiler, this, compiler->mint_class(), out_reg, locs()->temp(0).reg()); 3621 out_reg, locs()->temp(0).reg());
3685 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo); 3622 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo);
3686 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi); 3623 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi);
3687 __ Bind(&done); 3624 __ Bind(&done);
3688 } 3625 }
3689 3626
3690 3627
3691 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, 3628 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone,
3692 bool opt) const { 3629 bool opt) const {
3693 const intptr_t value_cid = value()->Type()->ToCid(); 3630 const intptr_t value_cid = value()->Type()->ToCid();
3694 const intptr_t kNumInputs = 1; 3631 const intptr_t kNumInputs = 1;
3695 intptr_t kNumTemps = 0; 3632 intptr_t kNumTemps = 0;
3696 3633
3697 if (CanDeoptimize()) { 3634 if (CanDeoptimize()) {
3698 if ((value_cid != kSmiCid) && 3635 if ((value_cid != kSmiCid) && (value_cid != kMintCid) && !is_truncating()) {
3699 (value_cid != kMintCid) &&
3700 !is_truncating()) {
3701 kNumTemps = 2; 3636 kNumTemps = 2;
3702 } else { 3637 } else {
3703 kNumTemps = 1; 3638 kNumTemps = 1;
3704 } 3639 }
3705 } 3640 }
3706 3641
3707 LocationSummary* summary = new(zone) LocationSummary( 3642 LocationSummary* summary = new (zone)
3708 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3643 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3709 summary->set_in(0, Location::RequiresRegister()); 3644 summary->set_in(0, Location::RequiresRegister());
3710 for (int i = 0; i < kNumTemps; i++) { 3645 for (int i = 0; i < kNumTemps; i++) {
3711 summary->set_temp(i, Location::RequiresRegister()); 3646 summary->set_temp(i, Location::RequiresRegister());
3712 } 3647 }
3713 summary->set_out(0, ((value_cid == kSmiCid) || (value_cid != kMintCid)) ? 3648 summary->set_out(0, ((value_cid == kSmiCid) || (value_cid != kMintCid))
3714 Location::SameAsFirstInput() : Location::RequiresRegister()); 3649 ? Location::SameAsFirstInput()
3650 : Location::RequiresRegister());
3715 return summary; 3651 return summary;
3716 } 3652 }
3717 3653
3718 3654
3719 static void LoadInt32FromMint(FlowGraphCompiler* compiler, 3655 static void LoadInt32FromMint(FlowGraphCompiler* compiler,
3720 Register result, 3656 Register result,
3721 const Address& lo, 3657 const Address& lo,
3722 const Address& hi, 3658 const Address& hi,
3723 Register temp, 3659 Register temp,
3724 Label* deopt) { 3660 Label* deopt) {
3725 __ movl(result, lo); 3661 __ movl(result, lo);
3726 if (deopt != NULL) { 3662 if (deopt != NULL) {
3727 ASSERT(temp != result); 3663 ASSERT(temp != result);
3728 __ movl(temp, result); 3664 __ movl(temp, result);
3729 __ sarl(temp, Immediate(31)); 3665 __ sarl(temp, Immediate(31));
3730 __ cmpl(temp, hi); 3666 __ cmpl(temp, hi);
3731 __ j(NOT_EQUAL, deopt); 3667 __ j(NOT_EQUAL, deopt);
3732 } 3668 }
3733 } 3669 }
3734 3670
3735 3671
3736 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 3672 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3737 const intptr_t value_cid = value()->Type()->ToCid(); 3673 const intptr_t value_cid = value()->Type()->ToCid();
3738 Register value = locs()->in(0).reg(); 3674 Register value = locs()->in(0).reg();
3739 const Register result = locs()->out(0).reg(); 3675 const Register result = locs()->out(0).reg();
3740 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; 3676 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister;
3741 Label* deopt = CanDeoptimize() ? 3677 Label* deopt =
3742 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL; 3678 CanDeoptimize()
3679 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger)
3680 : NULL;
3743 Label* out_of_range = !is_truncating() ? deopt : NULL; 3681 Label* out_of_range = !is_truncating() ? deopt : NULL;
3744 3682
3745 const intptr_t lo_offset = Mint::value_offset(); 3683 const intptr_t lo_offset = Mint::value_offset();
3746 const intptr_t hi_offset = Mint::value_offset() + kWordSize; 3684 const intptr_t hi_offset = Mint::value_offset() + kWordSize;
3747 3685
3748 if (value_cid == kSmiCid) { 3686 if (value_cid == kSmiCid) {
3749 ASSERT(value == result); 3687 ASSERT(value == result);
3750 __ SmiUntag(value); 3688 __ SmiUntag(value);
3751 } else if (value_cid == kMintCid) { 3689 } else if (value_cid == kMintCid) {
3752 ASSERT((value != result) || (out_of_range == NULL)); 3690 ASSERT((value != result) || (out_of_range == NULL));
3753 LoadInt32FromMint(compiler, 3691 LoadInt32FromMint(compiler, result, FieldAddress(value, lo_offset),
3754 result, 3692 FieldAddress(value, hi_offset), temp, out_of_range);
3755 FieldAddress(value, lo_offset),
3756 FieldAddress(value, hi_offset),
3757 temp,
3758 out_of_range);
3759 } else if (!CanDeoptimize()) { 3693 } else if (!CanDeoptimize()) {
3760 ASSERT(value == result); 3694 ASSERT(value == result);
3761 Label done; 3695 Label done;
3762 __ SmiUntag(value); 3696 __ SmiUntag(value);
3763 __ j(NOT_CARRY, &done); 3697 __ j(NOT_CARRY, &done);
3764 __ movl(value, Address(value, TIMES_2, lo_offset)); 3698 __ movl(value, Address(value, TIMES_2, lo_offset));
3765 __ Bind(&done); 3699 __ Bind(&done);
3766 } else { 3700 } else {
3767 ASSERT(value == result); 3701 ASSERT(value == result);
3768 Label done; 3702 Label done;
3769 __ SmiUntagOrCheckClass(value, kMintCid, temp, &done); 3703 __ SmiUntagOrCheckClass(value, kMintCid, temp, &done);
3770 __ j(NOT_EQUAL, deopt); 3704 __ j(NOT_EQUAL, deopt);
3771 if (out_of_range != NULL) { 3705 if (out_of_range != NULL) {
3772 Register value_temp = locs()->temp(1).reg(); 3706 Register value_temp = locs()->temp(1).reg();
3773 __ movl(value_temp, value); 3707 __ movl(value_temp, value);
3774 value = value_temp; 3708 value = value_temp;
3775 } 3709 }
3776 LoadInt32FromMint(compiler, 3710 LoadInt32FromMint(compiler, result, Address(value, TIMES_2, lo_offset),
3777 result, 3711 Address(value, TIMES_2, hi_offset), temp, out_of_range);
3778 Address(value, TIMES_2, lo_offset),
3779 Address(value, TIMES_2, hi_offset),
3780 temp,
3781 out_of_range);
3782 __ Bind(&done); 3712 __ Bind(&done);
3783 } 3713 }
3784 } 3714 }
3785 3715
3786 3716
3787 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, 3717 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone,
3788 bool opt) const { 3718 bool opt) const {
3789 const bool might_box = (representation() == kTagged) && !can_pack_into_smi(); 3719 const bool might_box = (representation() == kTagged) && !can_pack_into_smi();
3790 const intptr_t kNumInputs = 2; 3720 const intptr_t kNumInputs = 2;
3791 const intptr_t kNumTemps = might_box ? 2 : 0; 3721 const intptr_t kNumTemps = might_box ? 2 : 0;
3792 LocationSummary* summary = new(zone) LocationSummary( 3722 LocationSummary* summary = new (zone) LocationSummary(
3793 zone, kNumInputs, kNumTemps, 3723 zone, kNumInputs, kNumTemps,
3794 might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall); 3724 might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall);
3795 summary->set_in(0, Location::RequiresRegister()); 3725 summary->set_in(0, Location::RequiresRegister());
3796 // The smi index is either untagged (element size == 1), or it is left smi 3726 // The smi index is either untagged (element size == 1), or it is left smi
3797 // tagged (for all element sizes > 1). 3727 // tagged (for all element sizes > 1).
3798 summary->set_in(1, (index_scale() == 1) ? Location::WritableRegister() 3728 summary->set_in(1, (index_scale() == 1) ? Location::WritableRegister()
3799 : Location::RequiresRegister()); 3729 : Location::RequiresRegister());
3800 if (might_box) { 3730 if (might_box) {
3801 summary->set_temp(0, Location::RequiresRegister()); 3731 summary->set_temp(0, Location::RequiresRegister());
3802 summary->set_temp(1, Location::RequiresRegister()); 3732 summary->set_temp(1, Location::RequiresRegister());
(...skipping 10 matching lines...) Expand all
3813 return summary; 3743 return summary;
3814 } 3744 }
3815 3745
3816 3746
3817 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3747 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3818 // The string register points to the backing store for external strings. 3748 // The string register points to the backing store for external strings.
3819 const Register str = locs()->in(0).reg(); 3749 const Register str = locs()->in(0).reg();
3820 const Location index = locs()->in(1); 3750 const Location index = locs()->in(1);
3821 3751
3822 Address element_address = Assembler::ElementAddressForRegIndex( 3752 Address element_address = Assembler::ElementAddressForRegIndex(
3823 IsExternal(), class_id(), index_scale(), str, index.reg()); 3753 IsExternal(), class_id(), index_scale(), str, index.reg());
3824 3754
3825 if ((index_scale() == 1)) { 3755 if ((index_scale() == 1)) {
3826 __ SmiUntag(index.reg()); 3756 __ SmiUntag(index.reg());
3827 } 3757 }
3828 3758
3829 if (representation() == kUnboxedMint) { 3759 if (representation() == kUnboxedMint) {
3830 ASSERT(compiler->is_optimizing()); 3760 ASSERT(compiler->is_optimizing());
3831 ASSERT(locs()->out(0).IsPairLocation()); 3761 ASSERT(locs()->out(0).IsPairLocation());
3832 PairLocation* result_pair = locs()->out(0).AsPairLocation(); 3762 PairLocation* result_pair = locs()->out(0).AsPairLocation();
3833 Register result1 = result_pair->At(0).reg(); 3763 Register result1 = result_pair->At(0).reg();
(...skipping 15 matching lines...) Expand all
3849 default: 3779 default:
3850 UNREACHABLE(); 3780 UNREACHABLE();
3851 } 3781 }
3852 } else { 3782 } else {
3853 ASSERT(representation() == kTagged); 3783 ASSERT(representation() == kTagged);
3854 Register result = locs()->out(0).reg(); 3784 Register result = locs()->out(0).reg();
3855 switch (class_id()) { 3785 switch (class_id()) {
3856 case kOneByteStringCid: 3786 case kOneByteStringCid:
3857 case kExternalOneByteStringCid: 3787 case kExternalOneByteStringCid:
3858 switch (element_count()) { 3788 switch (element_count()) {
3859 case 1: __ movzxb(result, element_address); break; 3789 case 1:
3860 case 2: __ movzxw(result, element_address); break; 3790 __ movzxb(result, element_address);
3861 case 4: __ movl(result, element_address); break; 3791 break;
3862 default: UNREACHABLE(); 3792 case 2:
3793 __ movzxw(result, element_address);
3794 break;
3795 case 4:
3796 __ movl(result, element_address);
3797 break;
3798 default:
3799 UNREACHABLE();
3863 } 3800 }
3864 break; 3801 break;
3865 case kTwoByteStringCid: 3802 case kTwoByteStringCid:
3866 case kExternalTwoByteStringCid: 3803 case kExternalTwoByteStringCid:
3867 switch (element_count()) { 3804 switch (element_count()) {
3868 case 1: __ movzxw(result, element_address); break; 3805 case 1:
3869 case 2: __ movl(result, element_address); break; 3806 __ movzxw(result, element_address);
3870 default: UNREACHABLE(); 3807 break;
3808 case 2:
3809 __ movl(result, element_address);
3810 break;
3811 default:
3812 UNREACHABLE();
3871 } 3813 }
3872 break; 3814 break;
3873 default: 3815 default:
3874 UNREACHABLE(); 3816 UNREACHABLE();
3875 break; 3817 break;
3876 } 3818 }
3877 if (can_pack_into_smi()) { 3819 if (can_pack_into_smi()) {
3878 __ SmiTag(result); 3820 __ SmiTag(result);
3879 } else { 3821 } else {
3880 // If the value cannot fit in a smi then allocate a mint box for it. 3822 // If the value cannot fit in a smi then allocate a mint box for it.
3881 Register temp = locs()->temp(0).reg(); 3823 Register temp = locs()->temp(0).reg();
3882 Register temp2 = locs()->temp(1).reg(); 3824 Register temp2 = locs()->temp(1).reg();
3883 // Temp register needs to be manually preserved on allocation slow-path. 3825 // Temp register needs to be manually preserved on allocation slow-path.
3884 locs()->live_registers()->Add(locs()->temp(0), kUnboxedInt32); 3826 locs()->live_registers()->Add(locs()->temp(0), kUnboxedInt32);
3885 3827
3886 ASSERT(temp != result); 3828 ASSERT(temp != result);
3887 __ MoveRegister(temp, result); 3829 __ MoveRegister(temp, result);
3888 __ SmiTag(result); 3830 __ SmiTag(result);
3889 3831
3890 Label done; 3832 Label done;
3891 __ testl(temp, Immediate(0xC0000000)); 3833 __ testl(temp, Immediate(0xC0000000));
3892 __ j(ZERO, &done); 3834 __ j(ZERO, &done);
3893 BoxAllocationSlowPath::Allocate( 3835 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(),
3894 compiler, this, compiler->mint_class(), result, temp2); 3836 result, temp2);
3895 __ movl(FieldAddress(result, Mint::value_offset()), temp); 3837 __ movl(FieldAddress(result, Mint::value_offset()), temp);
3896 __ movl(FieldAddress(result, Mint::value_offset() + kWordSize), 3838 __ movl(FieldAddress(result, Mint::value_offset() + kWordSize),
3897 Immediate(0)); 3839 Immediate(0));
3898 __ Bind(&done); 3840 __ Bind(&done);
3899 } 3841 }
3900 } 3842 }
3901 } 3843 }
3902 3844
3903 3845
3904 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, 3846 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone,
3905 bool opt) const { 3847 bool opt) const {
3906 const intptr_t kNumInputs = 2; 3848 const intptr_t kNumInputs = 2;
3907 const intptr_t kNumTemps = 0; 3849 const intptr_t kNumTemps = 0;
3908 LocationSummary* summary = new(zone) LocationSummary( 3850 LocationSummary* summary = new (zone)
3909 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3851 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3910 summary->set_in(0, Location::RequiresFpuRegister()); 3852 summary->set_in(0, Location::RequiresFpuRegister());
3911 summary->set_in(1, Location::RequiresFpuRegister()); 3853 summary->set_in(1, Location::RequiresFpuRegister());
3912 summary->set_out(0, Location::SameAsFirstInput()); 3854 summary->set_out(0, Location::SameAsFirstInput());
3913 return summary; 3855 return summary;
3914 } 3856 }
3915 3857
3916 3858
3917 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3859 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3918 XmmRegister left = locs()->in(0).fpu_reg(); 3860 XmmRegister left = locs()->in(0).fpu_reg();
3919 XmmRegister right = locs()->in(1).fpu_reg(); 3861 XmmRegister right = locs()->in(1).fpu_reg();
3920 3862
3921 ASSERT(locs()->out(0).fpu_reg() == left); 3863 ASSERT(locs()->out(0).fpu_reg() == left);
3922 3864
3923 switch (op_kind()) { 3865 switch (op_kind()) {
3924 case Token::kADD: __ addsd(left, right); break; 3866 case Token::kADD:
3925 case Token::kSUB: __ subsd(left, right); break; 3867 __ addsd(left, right);
3926 case Token::kMUL: __ mulsd(left, right); break; 3868 break;
3927 case Token::kDIV: __ divsd(left, right); break; 3869 case Token::kSUB:
3928 default: UNREACHABLE(); 3870 __ subsd(left, right);
3871 break;
3872 case Token::kMUL:
3873 __ mulsd(left, right);
3874 break;
3875 case Token::kDIV:
3876 __ divsd(left, right);
3877 break;
3878 default:
3879 UNREACHABLE();
3929 } 3880 }
3930 } 3881 }
3931 3882
3932 3883
3933 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, 3884 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone,
3934 bool opt) const { 3885 bool opt) const {
3935 const intptr_t kNumInputs = 1; 3886 const intptr_t kNumInputs = 1;
3936 const intptr_t kNumTemps = 3887 const intptr_t kNumTemps =
3937 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; 3888 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0;
3938 LocationSummary* summary = new(zone) LocationSummary( 3889 LocationSummary* summary = new (zone)
3939 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3890 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3940 summary->set_in(0, Location::RequiresFpuRegister()); 3891 summary->set_in(0, Location::RequiresFpuRegister());
3941 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { 3892 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) {
3942 summary->set_temp(0, Location::RequiresRegister()); 3893 summary->set_temp(0, Location::RequiresRegister());
3943 } 3894 }
3944 summary->set_out(0, Location::RequiresRegister()); 3895 summary->set_out(0, Location::RequiresRegister());
3945 return summary; 3896 return summary;
3946 } 3897 }
3947 3898
3948 3899
3949 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 3900 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
3984 BranchInstr* branch) { 3935 BranchInstr* branch) {
3985 ASSERT(compiler->is_optimizing()); 3936 ASSERT(compiler->is_optimizing());
3986 BranchLabels labels = compiler->CreateBranchLabels(branch); 3937 BranchLabels labels = compiler->CreateBranchLabels(branch);
3987 Condition true_condition = EmitComparisonCode(compiler, labels); 3938 Condition true_condition = EmitComparisonCode(compiler, labels);
3988 EmitBranchOnCondition(compiler, true_condition, labels); 3939 EmitBranchOnCondition(compiler, true_condition, labels);
3989 } 3940 }
3990 3941
3991 3942
3992 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3943 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3993 Label is_true, is_false; 3944 Label is_true, is_false;
3994 BranchLabels labels = { &is_true, &is_false, &is_false }; 3945 BranchLabels labels = {&is_true, &is_false, &is_false};
3995 Condition true_condition = EmitComparisonCode(compiler, labels); 3946 Condition true_condition = EmitComparisonCode(compiler, labels);
3996 EmitBranchOnCondition(compiler, true_condition, labels); 3947 EmitBranchOnCondition(compiler, true_condition, labels);
3997 3948
3998 Register result = locs()->out(0).reg(); 3949 Register result = locs()->out(0).reg();
3999 Label done; 3950 Label done;
4000 __ Bind(&is_false); 3951 __ Bind(&is_false);
4001 __ LoadObject(result, Bool::False()); 3952 __ LoadObject(result, Bool::False());
4002 __ jmp(&done); 3953 __ jmp(&done);
4003 __ Bind(&is_true); 3954 __ Bind(&is_true);
4004 __ LoadObject(result, Bool::True()); 3955 __ LoadObject(result, Bool::True());
4005 __ Bind(&done); 3956 __ Bind(&done);
4006 } 3957 }
4007 3958
4008 3959
4009 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, 3960 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone,
4010 bool opt) const { 3961 bool opt) const {
4011 const intptr_t kNumInputs = 2; 3962 const intptr_t kNumInputs = 2;
4012 const intptr_t kNumTemps = 0; 3963 const intptr_t kNumTemps = 0;
4013 LocationSummary* summary = new(zone) LocationSummary( 3964 LocationSummary* summary = new (zone)
4014 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3965 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4015 summary->set_in(0, Location::RequiresFpuRegister()); 3966 summary->set_in(0, Location::RequiresFpuRegister());
4016 summary->set_in(1, Location::RequiresFpuRegister()); 3967 summary->set_in(1, Location::RequiresFpuRegister());
4017 summary->set_out(0, Location::SameAsFirstInput()); 3968 summary->set_out(0, Location::SameAsFirstInput());
4018 return summary; 3969 return summary;
4019 } 3970 }
4020 3971
4021 3972
4022 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3973 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4023 XmmRegister left = locs()->in(0).fpu_reg(); 3974 XmmRegister left = locs()->in(0).fpu_reg();
4024 XmmRegister right = locs()->in(1).fpu_reg(); 3975 XmmRegister right = locs()->in(1).fpu_reg();
4025 3976
4026 ASSERT(locs()->out(0).fpu_reg() == left); 3977 ASSERT(locs()->out(0).fpu_reg() == left);
4027 3978
4028 switch (op_kind()) { 3979 switch (op_kind()) {
4029 case Token::kADD: __ addps(left, right); break; 3980 case Token::kADD:
4030 case Token::kSUB: __ subps(left, right); break; 3981 __ addps(left, right);
4031 case Token::kMUL: __ mulps(left, right); break; 3982 break;
4032 case Token::kDIV: __ divps(left, right); break; 3983 case Token::kSUB:
4033 default: UNREACHABLE(); 3984 __ subps(left, right);
3985 break;
3986 case Token::kMUL:
3987 __ mulps(left, right);
3988 break;
3989 case Token::kDIV:
3990 __ divps(left, right);
3991 break;
3992 default:
3993 UNREACHABLE();
4034 } 3994 }
4035 } 3995 }
4036 3996
4037 3997
4038 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, 3998 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone,
4039 bool opt) const { 3999 bool opt) const {
4040 const intptr_t kNumInputs = 2; 4000 const intptr_t kNumInputs = 2;
4041 const intptr_t kNumTemps = 0; 4001 const intptr_t kNumTemps = 0;
4042 LocationSummary* summary = new(zone) LocationSummary( 4002 LocationSummary* summary = new (zone)
4043 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4003 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4044 summary->set_in(0, Location::RequiresFpuRegister()); 4004 summary->set_in(0, Location::RequiresFpuRegister());
4045 summary->set_in(1, Location::RequiresFpuRegister()); 4005 summary->set_in(1, Location::RequiresFpuRegister());
4046 summary->set_out(0, Location::SameAsFirstInput()); 4006 summary->set_out(0, Location::SameAsFirstInput());
4047 return summary; 4007 return summary;
4048 } 4008 }
4049 4009
4050 4010
4051 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4011 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4052 XmmRegister left = locs()->in(0).fpu_reg(); 4012 XmmRegister left = locs()->in(0).fpu_reg();
4053 XmmRegister right = locs()->in(1).fpu_reg(); 4013 XmmRegister right = locs()->in(1).fpu_reg();
4054 4014
4055 ASSERT(locs()->out(0).fpu_reg() == left); 4015 ASSERT(locs()->out(0).fpu_reg() == left);
4056 4016
4057 switch (op_kind()) { 4017 switch (op_kind()) {
4058 case Token::kADD: __ addpd(left, right); break; 4018 case Token::kADD:
4059 case Token::kSUB: __ subpd(left, right); break; 4019 __ addpd(left, right);
4060 case Token::kMUL: __ mulpd(left, right); break; 4020 break;
4061 case Token::kDIV: __ divpd(left, right); break; 4021 case Token::kSUB:
4062 default: UNREACHABLE(); 4022 __ subpd(left, right);
4023 break;
4024 case Token::kMUL:
4025 __ mulpd(left, right);
4026 break;
4027 case Token::kDIV:
4028 __ divpd(left, right);
4029 break;
4030 default:
4031 UNREACHABLE();
4063 } 4032 }
4064 } 4033 }
4065 4034
4066 4035
4067 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, 4036 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone,
4068 bool opt) const { 4037 bool opt) const {
4069 const intptr_t kNumInputs = 1; 4038 const intptr_t kNumInputs = 1;
4070 const intptr_t kNumTemps = 0; 4039 const intptr_t kNumTemps = 0;
4071 LocationSummary* summary = new(zone) LocationSummary( 4040 LocationSummary* summary = new (zone)
4072 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4041 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4073 summary->set_in(0, Location::RequiresFpuRegister()); 4042 summary->set_in(0, Location::RequiresFpuRegister());
4074 summary->set_out(0, Location::SameAsFirstInput()); 4043 summary->set_out(0, Location::SameAsFirstInput());
4075 return summary; 4044 return summary;
4076 } 4045 }
4077 4046
4078 4047
4079 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4048 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4080 XmmRegister value = locs()->in(0).fpu_reg(); 4049 XmmRegister value = locs()->in(0).fpu_reg();
4081 4050
4082 ASSERT(locs()->out(0).fpu_reg() == value); 4051 ASSERT(locs()->out(0).fpu_reg() == value);
(...skipping 12 matching lines...) Expand all
4095 __ cvtss2sd(value, value); 4064 __ cvtss2sd(value, value);
4096 break; 4065 break;
4097 case MethodRecognizer::kFloat32x4ShuffleW: 4066 case MethodRecognizer::kFloat32x4ShuffleW:
4098 __ shufps(value, value, Immediate(0xFF)); 4067 __ shufps(value, value, Immediate(0xFF));
4099 __ cvtss2sd(value, value); 4068 __ cvtss2sd(value, value);
4100 break; 4069 break;
4101 case MethodRecognizer::kFloat32x4Shuffle: 4070 case MethodRecognizer::kFloat32x4Shuffle:
4102 case MethodRecognizer::kInt32x4Shuffle: 4071 case MethodRecognizer::kInt32x4Shuffle:
4103 __ shufps(value, value, Immediate(mask_)); 4072 __ shufps(value, value, Immediate(mask_));
4104 break; 4073 break;
4105 default: UNREACHABLE(); 4074 default:
4075 UNREACHABLE();
4106 } 4076 }
4107 } 4077 }
4108 4078
4109 4079
4110 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, 4080 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone,
4111 bool opt) const { 4081 bool opt) const {
4112 const intptr_t kNumInputs = 2; 4082 const intptr_t kNumInputs = 2;
4113 const intptr_t kNumTemps = 0; 4083 const intptr_t kNumTemps = 0;
4114 LocationSummary* summary = new(zone) LocationSummary( 4084 LocationSummary* summary = new (zone)
4115 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4085 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4116 summary->set_in(0, Location::RequiresFpuRegister()); 4086 summary->set_in(0, Location::RequiresFpuRegister());
4117 summary->set_in(1, Location::RequiresFpuRegister()); 4087 summary->set_in(1, Location::RequiresFpuRegister());
4118 summary->set_out(0, Location::SameAsFirstInput()); 4088 summary->set_out(0, Location::SameAsFirstInput());
4119 return summary; 4089 return summary;
4120 } 4090 }
4121 4091
4122 4092
4123 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4093 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4124 XmmRegister left = locs()->in(0).fpu_reg(); 4094 XmmRegister left = locs()->in(0).fpu_reg();
4125 XmmRegister right = locs()->in(1).fpu_reg(); 4095 XmmRegister right = locs()->in(1).fpu_reg();
4126 4096
4127 ASSERT(locs()->out(0).fpu_reg() == left); 4097 ASSERT(locs()->out(0).fpu_reg() == left);
4128 switch (op_kind()) { 4098 switch (op_kind()) {
4129 case MethodRecognizer::kFloat32x4ShuffleMix: 4099 case MethodRecognizer::kFloat32x4ShuffleMix:
4130 case MethodRecognizer::kInt32x4ShuffleMix: 4100 case MethodRecognizer::kInt32x4ShuffleMix:
4131 __ shufps(left, right, Immediate(mask_)); 4101 __ shufps(left, right, Immediate(mask_));
4132 break; 4102 break;
4133 default: UNREACHABLE(); 4103 default:
4104 UNREACHABLE();
4134 } 4105 }
4135 } 4106 }
4136 4107
4137 4108
4138 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, 4109 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone,
4139 bool opt) const { 4110 bool opt) const {
4140 const intptr_t kNumInputs = 1; 4111 const intptr_t kNumInputs = 1;
4141 const intptr_t kNumTemps = 0; 4112 const intptr_t kNumTemps = 0;
4142 LocationSummary* summary = new(zone) LocationSummary( 4113 LocationSummary* summary = new (zone)
4143 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4114 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4144 summary->set_in(0, Location::RequiresFpuRegister()); 4115 summary->set_in(0, Location::RequiresFpuRegister());
4145 summary->set_out(0, Location::RequiresRegister()); 4116 summary->set_out(0, Location::RequiresRegister());
4146 return summary; 4117 return summary;
4147 } 4118 }
4148 4119
4149 4120
4150 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4121 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4151 XmmRegister value = locs()->in(0).fpu_reg(); 4122 XmmRegister value = locs()->in(0).fpu_reg();
4152 Register out = locs()->out(0).reg(); 4123 Register out = locs()->out(0).reg();
4153 4124
4154 __ movmskps(out, value); 4125 __ movmskps(out, value);
4155 __ SmiTag(out); 4126 __ SmiTag(out);
4156 } 4127 }
4157 4128
4158 4129
4159 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( 4130 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary(
4160 Zone* zone, bool opt) const { 4131 Zone* zone,
4132 bool opt) const {
4161 const intptr_t kNumInputs = 4; 4133 const intptr_t kNumInputs = 4;
4162 const intptr_t kNumTemps = 0; 4134 const intptr_t kNumTemps = 0;
4163 LocationSummary* summary = new(zone) LocationSummary( 4135 LocationSummary* summary = new (zone)
4164 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4136 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4165 summary->set_in(0, Location::RequiresFpuRegister()); 4137 summary->set_in(0, Location::RequiresFpuRegister());
4166 summary->set_in(1, Location::RequiresFpuRegister()); 4138 summary->set_in(1, Location::RequiresFpuRegister());
4167 summary->set_in(2, Location::RequiresFpuRegister()); 4139 summary->set_in(2, Location::RequiresFpuRegister());
4168 summary->set_in(3, Location::RequiresFpuRegister()); 4140 summary->set_in(3, Location::RequiresFpuRegister());
4169 summary->set_out(0, Location::SameAsFirstInput()); 4141 summary->set_out(0, Location::SameAsFirstInput());
4170 return summary; 4142 return summary;
4171 } 4143 }
4172 4144
4173 4145
4174 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4146 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 16 matching lines...) Expand all
4191 __ movss(Address(ESP, 12), v0); 4163 __ movss(Address(ESP, 12), v0);
4192 __ movups(v0, Address(ESP, 0)); 4164 __ movups(v0, Address(ESP, 0));
4193 __ addl(ESP, Immediate(16)); 4165 __ addl(ESP, Immediate(16));
4194 } 4166 }
4195 4167
4196 4168
4197 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, 4169 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone,
4198 bool opt) const { 4170 bool opt) const {
4199 const intptr_t kNumInputs = 0; 4171 const intptr_t kNumInputs = 0;
4200 const intptr_t kNumTemps = 0; 4172 const intptr_t kNumTemps = 0;
4201 LocationSummary* summary = new(zone) LocationSummary( 4173 LocationSummary* summary = new (zone)
4202 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4174 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4203 summary->set_out(0, Location::RequiresFpuRegister()); 4175 summary->set_out(0, Location::RequiresFpuRegister());
4204 return summary; 4176 return summary;
4205 } 4177 }
4206 4178
4207 4179
4208 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4180 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4209 XmmRegister value = locs()->out(0).fpu_reg(); 4181 XmmRegister value = locs()->out(0).fpu_reg();
4210 __ xorps(value, value); 4182 __ xorps(value, value);
4211 } 4183 }
4212 4184
4213 4185
4214 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, 4186 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone,
4215 bool opt) const { 4187 bool opt) const {
4216 const intptr_t kNumInputs = 1; 4188 const intptr_t kNumInputs = 1;
4217 const intptr_t kNumTemps = 0; 4189 const intptr_t kNumTemps = 0;
4218 LocationSummary* summary = new(zone) LocationSummary( 4190 LocationSummary* summary = new (zone)
4219 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4191 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4220 summary->set_in(0, Location::RequiresFpuRegister()); 4192 summary->set_in(0, Location::RequiresFpuRegister());
4221 summary->set_out(0, Location::SameAsFirstInput()); 4193 summary->set_out(0, Location::SameAsFirstInput());
4222 return summary; 4194 return summary;
4223 } 4195 }
4224 4196
4225 4197
4226 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4198 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4227 XmmRegister value = locs()->out(0).fpu_reg(); 4199 XmmRegister value = locs()->out(0).fpu_reg();
4228 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); 4200 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg());
4229 // Convert to Float32. 4201 // Convert to Float32.
4230 __ cvtsd2ss(value, value); 4202 __ cvtsd2ss(value, value);
4231 // Splat across all lanes. 4203 // Splat across all lanes.
4232 __ shufps(value, value, Immediate(0x00)); 4204 __ shufps(value, value, Immediate(0x00));
4233 } 4205 }
4234 4206
4235 4207
4236 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, 4208 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone,
4237 bool opt) const { 4209 bool opt) const {
4238 const intptr_t kNumInputs = 2; 4210 const intptr_t kNumInputs = 2;
4239 const intptr_t kNumTemps = 0; 4211 const intptr_t kNumTemps = 0;
4240 LocationSummary* summary = new(zone) LocationSummary( 4212 LocationSummary* summary = new (zone)
4241 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4213 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4242 summary->set_in(0, Location::RequiresFpuRegister()); 4214 summary->set_in(0, Location::RequiresFpuRegister());
4243 summary->set_in(1, Location::RequiresFpuRegister()); 4215 summary->set_in(1, Location::RequiresFpuRegister());
4244 summary->set_out(0, Location::SameAsFirstInput()); 4216 summary->set_out(0, Location::SameAsFirstInput());
4245 return summary; 4217 return summary;
4246 } 4218 }
4247 4219
4248 4220
4249 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4221 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4250 XmmRegister left = locs()->in(0).fpu_reg(); 4222 XmmRegister left = locs()->in(0).fpu_reg();
4251 XmmRegister right = locs()->in(1).fpu_reg(); 4223 XmmRegister right = locs()->in(1).fpu_reg();
(...skipping 13 matching lines...) Expand all
4265 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: 4237 case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
4266 __ cmppsnlt(left, right); 4238 __ cmppsnlt(left, right);
4267 break; 4239 break;
4268 case MethodRecognizer::kFloat32x4LessThan: 4240 case MethodRecognizer::kFloat32x4LessThan:
4269 __ cmppslt(left, right); 4241 __ cmppslt(left, right);
4270 break; 4242 break;
4271 case MethodRecognizer::kFloat32x4LessThanOrEqual: 4243 case MethodRecognizer::kFloat32x4LessThanOrEqual:
4272 __ cmppsle(left, right); 4244 __ cmppsle(left, right);
4273 break; 4245 break;
4274 4246
4275 default: UNREACHABLE(); 4247 default:
4248 UNREACHABLE();
4276 } 4249 }
4277 } 4250 }
4278 4251
4279 4252
4280 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, 4253 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone,
4281 bool opt) const { 4254 bool opt) const {
4282 const intptr_t kNumInputs = 2; 4255 const intptr_t kNumInputs = 2;
4283 const intptr_t kNumTemps = 0; 4256 const intptr_t kNumTemps = 0;
4284 LocationSummary* summary = new(zone) LocationSummary( 4257 LocationSummary* summary = new (zone)
4285 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4258 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4286 summary->set_in(0, Location::RequiresFpuRegister()); 4259 summary->set_in(0, Location::RequiresFpuRegister());
4287 summary->set_in(1, Location::RequiresFpuRegister()); 4260 summary->set_in(1, Location::RequiresFpuRegister());
4288 summary->set_out(0, Location::SameAsFirstInput()); 4261 summary->set_out(0, Location::SameAsFirstInput());
4289 return summary; 4262 return summary;
4290 } 4263 }
4291 4264
4292 4265
4293 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4266 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4294 XmmRegister left = locs()->in(0).fpu_reg(); 4267 XmmRegister left = locs()->in(0).fpu_reg();
4295 XmmRegister right = locs()->in(1).fpu_reg(); 4268 XmmRegister right = locs()->in(1).fpu_reg();
4296 4269
4297 ASSERT(locs()->out(0).fpu_reg() == left); 4270 ASSERT(locs()->out(0).fpu_reg() == left);
4298 4271
4299 switch (op_kind()) { 4272 switch (op_kind()) {
4300 case MethodRecognizer::kFloat32x4Min: 4273 case MethodRecognizer::kFloat32x4Min:
4301 __ minps(left, right); 4274 __ minps(left, right);
4302 break; 4275 break;
4303 case MethodRecognizer::kFloat32x4Max: 4276 case MethodRecognizer::kFloat32x4Max:
4304 __ maxps(left, right); 4277 __ maxps(left, right);
4305 break; 4278 break;
4306 default: UNREACHABLE(); 4279 default:
4280 UNREACHABLE();
4307 } 4281 }
4308 } 4282 }
4309 4283
4310 4284
4311 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, 4285 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone,
4312 bool opt) const { 4286 bool opt) const {
4313 const intptr_t kNumInputs = 2; 4287 const intptr_t kNumInputs = 2;
4314 const intptr_t kNumTemps = 0; 4288 const intptr_t kNumTemps = 0;
4315 LocationSummary* summary = new(zone) LocationSummary( 4289 LocationSummary* summary = new (zone)
4316 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4290 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4317 summary->set_in(0, Location::RequiresFpuRegister()); 4291 summary->set_in(0, Location::RequiresFpuRegister());
4318 summary->set_in(1, Location::RequiresFpuRegister()); 4292 summary->set_in(1, Location::RequiresFpuRegister());
4319 summary->set_out(0, Location::SameAsFirstInput()); 4293 summary->set_out(0, Location::SameAsFirstInput());
4320 return summary; 4294 return summary;
4321 } 4295 }
4322 4296
4323 4297
4324 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4298 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4325 XmmRegister left = locs()->in(0).fpu_reg(); 4299 XmmRegister left = locs()->in(0).fpu_reg();
4326 XmmRegister right = locs()->in(1).fpu_reg(); 4300 XmmRegister right = locs()->in(1).fpu_reg();
4327 4301
4328 ASSERT(locs()->out(0).fpu_reg() == left); 4302 ASSERT(locs()->out(0).fpu_reg() == left);
4329 4303
4330 switch (op_kind()) { 4304 switch (op_kind()) {
4331 case MethodRecognizer::kFloat32x4Scale: 4305 case MethodRecognizer::kFloat32x4Scale:
4332 __ cvtsd2ss(left, left); 4306 __ cvtsd2ss(left, left);
4333 __ shufps(left, left, Immediate(0x00)); 4307 __ shufps(left, left, Immediate(0x00));
4334 __ mulps(left, right); 4308 __ mulps(left, right);
4335 break; 4309 break;
4336 default: UNREACHABLE(); 4310 default:
4311 UNREACHABLE();
4337 } 4312 }
4338 } 4313 }
4339 4314
4340 4315
4341 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, 4316 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone,
4342 bool opt) const { 4317 bool opt) const {
4343 const intptr_t kNumInputs = 1; 4318 const intptr_t kNumInputs = 1;
4344 const intptr_t kNumTemps = 0; 4319 const intptr_t kNumTemps = 0;
4345 LocationSummary* summary = new(zone) LocationSummary( 4320 LocationSummary* summary = new (zone)
4346 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4321 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4347 summary->set_in(0, Location::RequiresFpuRegister()); 4322 summary->set_in(0, Location::RequiresFpuRegister());
4348 summary->set_out(0, Location::SameAsFirstInput()); 4323 summary->set_out(0, Location::SameAsFirstInput());
4349 return summary; 4324 return summary;
4350 } 4325 }
4351 4326
4352 4327
4353 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4328 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4354 XmmRegister left = locs()->in(0).fpu_reg(); 4329 XmmRegister left = locs()->in(0).fpu_reg();
4355 4330
4356 ASSERT(locs()->out(0).fpu_reg() == left); 4331 ASSERT(locs()->out(0).fpu_reg() == left);
4357 4332
4358 switch (op_kind()) { 4333 switch (op_kind()) {
4359 case MethodRecognizer::kFloat32x4Sqrt: 4334 case MethodRecognizer::kFloat32x4Sqrt:
4360 __ sqrtps(left); 4335 __ sqrtps(left);
4361 break; 4336 break;
4362 case MethodRecognizer::kFloat32x4Reciprocal: 4337 case MethodRecognizer::kFloat32x4Reciprocal:
4363 __ reciprocalps(left); 4338 __ reciprocalps(left);
4364 break; 4339 break;
4365 case MethodRecognizer::kFloat32x4ReciprocalSqrt: 4340 case MethodRecognizer::kFloat32x4ReciprocalSqrt:
4366 __ rsqrtps(left); 4341 __ rsqrtps(left);
4367 break; 4342 break;
4368 default: UNREACHABLE(); 4343 default:
4344 UNREACHABLE();
4369 } 4345 }
4370 } 4346 }
4371 4347
4372 4348
4373 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, 4349 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone,
4374 bool opt) const { 4350 bool opt) const {
4375 const intptr_t kNumInputs = 1; 4351 const intptr_t kNumInputs = 1;
4376 const intptr_t kNumTemps = 0; 4352 const intptr_t kNumTemps = 0;
4377 LocationSummary* summary = new(zone) LocationSummary( 4353 LocationSummary* summary = new (zone)
4378 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4354 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4379 summary->set_in(0, Location::RequiresFpuRegister()); 4355 summary->set_in(0, Location::RequiresFpuRegister());
4380 summary->set_out(0, Location::SameAsFirstInput()); 4356 summary->set_out(0, Location::SameAsFirstInput());
4381 return summary; 4357 return summary;
4382 } 4358 }
4383 4359
4384 4360
4385 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4361 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4386 XmmRegister left = locs()->in(0).fpu_reg(); 4362 XmmRegister left = locs()->in(0).fpu_reg();
4387 4363
4388 ASSERT(locs()->out(0).fpu_reg() == left); 4364 ASSERT(locs()->out(0).fpu_reg() == left);
4389 switch (op_kind()) { 4365 switch (op_kind()) {
4390 case MethodRecognizer::kFloat32x4Negate: 4366 case MethodRecognizer::kFloat32x4Negate:
4391 __ negateps(left); 4367 __ negateps(left);
4392 break; 4368 break;
4393 case MethodRecognizer::kFloat32x4Absolute: 4369 case MethodRecognizer::kFloat32x4Absolute:
4394 __ absps(left); 4370 __ absps(left);
4395 break; 4371 break;
4396 default: UNREACHABLE(); 4372 default:
4373 UNREACHABLE();
4397 } 4374 }
4398 } 4375 }
4399 4376
4400 4377
4401 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, 4378 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone,
4402 bool opt) const { 4379 bool opt) const {
4403 const intptr_t kNumInputs = 3; 4380 const intptr_t kNumInputs = 3;
4404 const intptr_t kNumTemps = 0; 4381 const intptr_t kNumTemps = 0;
4405 LocationSummary* summary = new(zone) LocationSummary( 4382 LocationSummary* summary = new (zone)
4406 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4383 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4407 summary->set_in(0, Location::RequiresFpuRegister()); 4384 summary->set_in(0, Location::RequiresFpuRegister());
4408 summary->set_in(1, Location::RequiresFpuRegister()); 4385 summary->set_in(1, Location::RequiresFpuRegister());
4409 summary->set_in(2, Location::RequiresFpuRegister()); 4386 summary->set_in(2, Location::RequiresFpuRegister());
4410 summary->set_out(0, Location::SameAsFirstInput()); 4387 summary->set_out(0, Location::SameAsFirstInput());
4411 return summary; 4388 return summary;
4412 } 4389 }
4413 4390
4414 4391
4415 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4392 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4416 XmmRegister left = locs()->in(0).fpu_reg(); 4393 XmmRegister left = locs()->in(0).fpu_reg();
4417 XmmRegister lower = locs()->in(1).fpu_reg(); 4394 XmmRegister lower = locs()->in(1).fpu_reg();
4418 XmmRegister upper = locs()->in(2).fpu_reg(); 4395 XmmRegister upper = locs()->in(2).fpu_reg();
4419 ASSERT(locs()->out(0).fpu_reg() == left); 4396 ASSERT(locs()->out(0).fpu_reg() == left);
4420 __ minps(left, upper); 4397 __ minps(left, upper);
4421 __ maxps(left, lower); 4398 __ maxps(left, lower);
4422 } 4399 }
4423 4400
4424 4401
4425 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, 4402 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone,
4426 bool opt) const { 4403 bool opt) const {
4427 const intptr_t kNumInputs = 2; 4404 const intptr_t kNumInputs = 2;
4428 const intptr_t kNumTemps = 0; 4405 const intptr_t kNumTemps = 0;
4429 LocationSummary* summary = new(zone) LocationSummary( 4406 LocationSummary* summary = new (zone)
4430 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4407 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4431 summary->set_in(0, Location::RequiresFpuRegister()); 4408 summary->set_in(0, Location::RequiresFpuRegister());
4432 summary->set_in(1, Location::RequiresFpuRegister()); 4409 summary->set_in(1, Location::RequiresFpuRegister());
4433 summary->set_out(0, Location::SameAsFirstInput()); 4410 summary->set_out(0, Location::SameAsFirstInput());
4434 return summary; 4411 return summary;
4435 } 4412 }
4436 4413
4437 4414
4438 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4415 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4439 XmmRegister replacement = locs()->in(0).fpu_reg(); 4416 XmmRegister replacement = locs()->in(0).fpu_reg();
4440 XmmRegister value = locs()->in(1).fpu_reg(); 4417 XmmRegister value = locs()->in(1).fpu_reg();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
4479 __ cvtsd2ss(replacement, replacement); 4456 __ cvtsd2ss(replacement, replacement);
4480 __ subl(ESP, Immediate(16)); 4457 __ subl(ESP, Immediate(16));
4481 // Move value to stack. 4458 // Move value to stack.
4482 __ movups(Address(ESP, 0), value); 4459 __ movups(Address(ESP, 0), value);
4483 // Write over W value. 4460 // Write over W value.
4484 __ movss(Address(ESP, 12), replacement); 4461 __ movss(Address(ESP, 12), replacement);
4485 // Move updated value into output register. 4462 // Move updated value into output register.
4486 __ movups(replacement, Address(ESP, 0)); 4463 __ movups(replacement, Address(ESP, 0));
4487 __ addl(ESP, Immediate(16)); 4464 __ addl(ESP, Immediate(16));
4488 break; 4465 break;
4489 default: UNREACHABLE(); 4466 default:
4467 UNREACHABLE();
4490 } 4468 }
4491 } 4469 }
4492 4470
4493 4471
4494 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, 4472 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone,
4495 bool opt) const { 4473 bool opt) const {
4496 const intptr_t kNumInputs = 1; 4474 const intptr_t kNumInputs = 1;
4497 const intptr_t kNumTemps = 0; 4475 const intptr_t kNumTemps = 0;
4498 LocationSummary* summary = new(zone) LocationSummary( 4476 LocationSummary* summary = new (zone)
4499 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4477 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4500 summary->set_in(0, Location::RequiresFpuRegister()); 4478 summary->set_in(0, Location::RequiresFpuRegister());
4501 summary->set_out(0, Location::SameAsFirstInput()); 4479 summary->set_out(0, Location::SameAsFirstInput());
4502 return summary; 4480 return summary;
4503 } 4481 }
4504 4482
4505 4483
4506 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 4484 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
4507 // NOP. 4485 // NOP.
4508 } 4486 }
4509 4487
4510 4488
4511 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, 4489 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone,
4512 bool opt) const { 4490 bool opt) const {
4513 const intptr_t kNumInputs = 1; 4491 const intptr_t kNumInputs = 1;
4514 const intptr_t kNumTemps = 0; 4492 const intptr_t kNumTemps = 0;
4515 LocationSummary* summary = new(zone) LocationSummary( 4493 LocationSummary* summary = new (zone)
4516 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4494 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4517 summary->set_in(0, Location::RequiresFpuRegister()); 4495 summary->set_in(0, Location::RequiresFpuRegister());
4518 summary->set_out(0, Location::SameAsFirstInput()); 4496 summary->set_out(0, Location::SameAsFirstInput());
4519 return summary; 4497 return summary;
4520 } 4498 }
4521 4499
4522 4500
4523 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4501 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4524 XmmRegister value = locs()->in(0).fpu_reg(); 4502 XmmRegister value = locs()->in(0).fpu_reg();
4525 4503
4526 ASSERT(locs()->out(0).fpu_reg() == value); 4504 ASSERT(locs()->out(0).fpu_reg() == value);
4527 4505
4528 switch (op_kind()) { 4506 switch (op_kind()) {
4529 case MethodRecognizer::kFloat64x2GetX: 4507 case MethodRecognizer::kFloat64x2GetX:
4530 // nop. 4508 // nop.
4531 break; 4509 break;
4532 case MethodRecognizer::kFloat64x2GetY: 4510 case MethodRecognizer::kFloat64x2GetY:
4533 __ shufpd(value, value, Immediate(0x33)); 4511 __ shufpd(value, value, Immediate(0x33));
4534 break; 4512 break;
4535 default: UNREACHABLE(); 4513 default:
4514 UNREACHABLE();
4536 } 4515 }
4537 } 4516 }
4538 4517
4539 4518
4540
4541 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, 4519 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone,
4542 bool opt) const { 4520 bool opt) const {
4543 const intptr_t kNumInputs = 0; 4521 const intptr_t kNumInputs = 0;
4544 const intptr_t kNumTemps = 0; 4522 const intptr_t kNumTemps = 0;
4545 LocationSummary* summary = new(zone) LocationSummary( 4523 LocationSummary* summary = new (zone)
4546 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4524 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4547 summary->set_out(0, Location::RequiresFpuRegister()); 4525 summary->set_out(0, Location::RequiresFpuRegister());
4548 return summary; 4526 return summary;
4549 } 4527 }
4550 4528
4551 4529
4552 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4530 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4553 XmmRegister value = locs()->out(0).fpu_reg(); 4531 XmmRegister value = locs()->out(0).fpu_reg();
4554 __ xorpd(value, value); 4532 __ xorpd(value, value);
4555 } 4533 }
4556 4534
4557 4535
4558 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, 4536 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone,
4559 bool opt) const { 4537 bool opt) const {
4560 const intptr_t kNumInputs = 1; 4538 const intptr_t kNumInputs = 1;
4561 const intptr_t kNumTemps = 0; 4539 const intptr_t kNumTemps = 0;
4562 LocationSummary* summary = new(zone) LocationSummary( 4540 LocationSummary* summary = new (zone)
4563 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4541 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4564 summary->set_in(0, Location::RequiresFpuRegister()); 4542 summary->set_in(0, Location::RequiresFpuRegister());
4565 summary->set_out(0, Location::SameAsFirstInput()); 4543 summary->set_out(0, Location::SameAsFirstInput());
4566 return summary; 4544 return summary;
4567 } 4545 }
4568 4546
4569 4547
4570 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4548 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4571 XmmRegister value = locs()->out(0).fpu_reg(); 4549 XmmRegister value = locs()->out(0).fpu_reg();
4572 __ shufpd(value, value, Immediate(0x0)); 4550 __ shufpd(value, value, Immediate(0x0));
4573 } 4551 }
4574 4552
4575 4553
4576 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( 4554 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary(
4577 Zone* zone, bool opt) const { 4555 Zone* zone,
4556 bool opt) const {
4578 const intptr_t kNumInputs = 2; 4557 const intptr_t kNumInputs = 2;
4579 const intptr_t kNumTemps = 0; 4558 const intptr_t kNumTemps = 0;
4580 LocationSummary* summary = new(zone) LocationSummary( 4559 LocationSummary* summary = new (zone)
4581 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4560 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4582 summary->set_in(0, Location::RequiresFpuRegister()); 4561 summary->set_in(0, Location::RequiresFpuRegister());
4583 summary->set_in(1, Location::RequiresFpuRegister()); 4562 summary->set_in(1, Location::RequiresFpuRegister());
4584 summary->set_out(0, Location::SameAsFirstInput()); 4563 summary->set_out(0, Location::SameAsFirstInput());
4585 return summary; 4564 return summary;
4586 } 4565 }
4587 4566
4588 4567
4589 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4568 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4590 XmmRegister v0 = locs()->in(0).fpu_reg(); 4569 XmmRegister v0 = locs()->in(0).fpu_reg();
4591 XmmRegister v1 = locs()->in(1).fpu_reg(); 4570 XmmRegister v1 = locs()->in(1).fpu_reg();
4592 ASSERT(v0 == locs()->out(0).fpu_reg()); 4571 ASSERT(v0 == locs()->out(0).fpu_reg());
4593 // shufpd mask 0x0 results in: 4572 // shufpd mask 0x0 results in:
4594 // Lower 64-bits of v0 = Lower 64-bits of v0. 4573 // Lower 64-bits of v0 = Lower 64-bits of v0.
4595 // Upper 64-bits of v0 = Lower 64-bits of v1. 4574 // Upper 64-bits of v0 = Lower 64-bits of v1.
4596 __ shufpd(v0, v1, Immediate(0x0)); 4575 __ shufpd(v0, v1, Immediate(0x0));
4597 } 4576 }
4598 4577
4599 4578
4600 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( 4579 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary(
4601 Zone* zone, bool opt) const { 4580 Zone* zone,
4581 bool opt) const {
4602 const intptr_t kNumInputs = 1; 4582 const intptr_t kNumInputs = 1;
4603 const intptr_t kNumTemps = 0; 4583 const intptr_t kNumTemps = 0;
4604 LocationSummary* summary = new(zone) LocationSummary( 4584 LocationSummary* summary = new (zone)
4605 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4585 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4606 summary->set_in(0, Location::RequiresFpuRegister()); 4586 summary->set_in(0, Location::RequiresFpuRegister());
4607 summary->set_out(0, Location::SameAsFirstInput()); 4587 summary->set_out(0, Location::SameAsFirstInput());
4608 return summary; 4588 return summary;
4609 } 4589 }
4610 4590
4611 4591
4612 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 4592 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
4613 XmmRegister value = locs()->out(0).fpu_reg(); 4593 XmmRegister value = locs()->out(0).fpu_reg();
4614 __ cvtpd2ps(value, value); 4594 __ cvtpd2ps(value, value);
4615 } 4595 }
4616 4596
4617 4597
4618 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( 4598 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary(
4619 Zone* zone, bool opt) const { 4599 Zone* zone,
4600 bool opt) const {
4620 const intptr_t kNumInputs = 1; 4601 const intptr_t kNumInputs = 1;
4621 const intptr_t kNumTemps = 0; 4602 const intptr_t kNumTemps = 0;
4622 LocationSummary* summary = new(zone) LocationSummary( 4603 LocationSummary* summary = new (zone)
4623 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4604 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4624 summary->set_in(0, Location::RequiresFpuRegister()); 4605 summary->set_in(0, Location::RequiresFpuRegister());
4625 summary->set_out(0, Location::SameAsFirstInput()); 4606 summary->set_out(0, Location::SameAsFirstInput());
4626 return summary; 4607 return summary;
4627 } 4608 }
4628 4609
4629 4610
4630 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 4611 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
4631 XmmRegister value = locs()->out(0).fpu_reg(); 4612 XmmRegister value = locs()->out(0).fpu_reg();
4632 __ cvtps2pd(value, value); 4613 __ cvtps2pd(value, value);
4633 } 4614 }
4634 4615
4635 4616
4636 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, 4617 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone,
4637 bool opt) const { 4618 bool opt) const {
4638 const intptr_t kNumInputs = 1; 4619 const intptr_t kNumInputs = 1;
4639 const intptr_t kNumTemps = 0; 4620 const intptr_t kNumTemps = 0;
4640 LocationSummary* summary = new(zone) LocationSummary( 4621 LocationSummary* summary = new (zone)
4641 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4622 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4642 summary->set_in(0, Location::RequiresFpuRegister()); 4623 summary->set_in(0, Location::RequiresFpuRegister());
4643 if (representation() == kTagged) { 4624 if (representation() == kTagged) {
4644 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); 4625 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask);
4645 summary->set_out(0, Location::RequiresRegister()); 4626 summary->set_out(0, Location::RequiresRegister());
4646 } else { 4627 } else {
4647 ASSERT(representation() == kUnboxedFloat64x2); 4628 ASSERT(representation() == kUnboxedFloat64x2);
4648 summary->set_out(0, Location::SameAsFirstInput()); 4629 summary->set_out(0, Location::SameAsFirstInput());
4649 } 4630 }
4650 return summary; 4631 return summary;
4651 } 4632 }
(...skipping 12 matching lines...) Expand all
4664 case MethodRecognizer::kFloat64x2Abs: 4645 case MethodRecognizer::kFloat64x2Abs:
4665 __ abspd(left); 4646 __ abspd(left);
4666 break; 4647 break;
4667 case MethodRecognizer::kFloat64x2Sqrt: 4648 case MethodRecognizer::kFloat64x2Sqrt:
4668 __ sqrtpd(left); 4649 __ sqrtpd(left);
4669 break; 4650 break;
4670 case MethodRecognizer::kFloat64x2GetSignMask: 4651 case MethodRecognizer::kFloat64x2GetSignMask:
4671 __ movmskpd(locs()->out(0).reg(), left); 4652 __ movmskpd(locs()->out(0).reg(), left);
4672 __ SmiTag(locs()->out(0).reg()); 4653 __ SmiTag(locs()->out(0).reg());
4673 break; 4654 break;
4674 default: UNREACHABLE(); 4655 default:
4656 UNREACHABLE();
4675 } 4657 }
4676 } 4658 }
4677 4659
4678 4660
4679 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, 4661 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone,
4680 bool opt) const { 4662 bool opt) const {
4681 const intptr_t kNumInputs = 2; 4663 const intptr_t kNumInputs = 2;
4682 const intptr_t kNumTemps = 0; 4664 const intptr_t kNumTemps = 0;
4683 LocationSummary* summary = new(zone) LocationSummary( 4665 LocationSummary* summary = new (zone)
4684 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4685 summary->set_in(0, Location::RequiresFpuRegister()); 4667 summary->set_in(0, Location::RequiresFpuRegister());
4686 summary->set_in(1, Location::RequiresFpuRegister()); 4668 summary->set_in(1, Location::RequiresFpuRegister());
4687 summary->set_out(0, Location::SameAsFirstInput()); 4669 summary->set_out(0, Location::SameAsFirstInput());
4688 return summary; 4670 return summary;
4689 } 4671 }
4690 4672
4691 4673
4692 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4674 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4693 XmmRegister left = locs()->in(0).fpu_reg(); 4675 XmmRegister left = locs()->in(0).fpu_reg();
4694 XmmRegister right = locs()->in(1).fpu_reg(); 4676 XmmRegister right = locs()->in(1).fpu_reg();
(...skipping 23 matching lines...) Expand all
4718 // Move updated value into output register. 4700 // Move updated value into output register.
4719 __ movups(left, Address(ESP, 0)); 4701 __ movups(left, Address(ESP, 0));
4720 __ addl(ESP, Immediate(16)); 4702 __ addl(ESP, Immediate(16));
4721 break; 4703 break;
4722 case MethodRecognizer::kFloat64x2Min: 4704 case MethodRecognizer::kFloat64x2Min:
4723 __ minpd(left, right); 4705 __ minpd(left, right);
4724 break; 4706 break;
4725 case MethodRecognizer::kFloat64x2Max: 4707 case MethodRecognizer::kFloat64x2Max:
4726 __ maxpd(left, right); 4708 __ maxpd(left, right);
4727 break; 4709 break;
4728 default: UNREACHABLE(); 4710 default:
4711 UNREACHABLE();
4729 } 4712 }
4730 } 4713 }
4731 4714
4732 4715
4733 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary( 4716 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone,
4734 Zone* zone, bool opt) const { 4717 bool opt) const {
4735 const intptr_t kNumInputs = 4; 4718 const intptr_t kNumInputs = 4;
4736 const intptr_t kNumTemps = 0; 4719 const intptr_t kNumTemps = 0;
4737 LocationSummary* summary = new(zone) LocationSummary( 4720 LocationSummary* summary = new (zone)
4738 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4721 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4739 summary->set_in(0, Location::RequiresRegister()); 4722 summary->set_in(0, Location::RequiresRegister());
4740 summary->set_in(1, Location::RequiresRegister()); 4723 summary->set_in(1, Location::RequiresRegister());
4741 summary->set_in(2, Location::RequiresRegister()); 4724 summary->set_in(2, Location::RequiresRegister());
4742 summary->set_in(3, Location::RequiresRegister()); 4725 summary->set_in(3, Location::RequiresRegister());
4743 summary->set_out(0, Location::RequiresFpuRegister()); 4726 summary->set_out(0, Location::RequiresFpuRegister());
4744 return summary; 4727 return summary;
4745 } 4728 }
4746 4729
4747 4730
4748 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4731 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4749 Register v0 = locs()->in(0).reg(); 4732 Register v0 = locs()->in(0).reg();
4750 Register v1 = locs()->in(1).reg(); 4733 Register v1 = locs()->in(1).reg();
4751 Register v2 = locs()->in(2).reg(); 4734 Register v2 = locs()->in(2).reg();
4752 Register v3 = locs()->in(3).reg(); 4735 Register v3 = locs()->in(3).reg();
4753 XmmRegister result = locs()->out(0).fpu_reg(); 4736 XmmRegister result = locs()->out(0).fpu_reg();
4754 __ subl(ESP, Immediate(4 * kInt32Size)); 4737 __ subl(ESP, Immediate(4 * kInt32Size));
4755 __ movl(Address(ESP, 0 * kInt32Size), v0); 4738 __ movl(Address(ESP, 0 * kInt32Size), v0);
4756 __ movl(Address(ESP, 1 * kInt32Size), v1); 4739 __ movl(Address(ESP, 1 * kInt32Size), v1);
4757 __ movl(Address(ESP, 2 * kInt32Size), v2); 4740 __ movl(Address(ESP, 2 * kInt32Size), v2);
4758 __ movl(Address(ESP, 3 * kInt32Size), v3); 4741 __ movl(Address(ESP, 3 * kInt32Size), v3);
4759 __ movups(result, Address(ESP, 0)); 4742 __ movups(result, Address(ESP, 0));
4760 __ addl(ESP, Immediate(4 * kInt32Size)); 4743 __ addl(ESP, Immediate(4 * kInt32Size));
4761 } 4744 }
4762 4745
4763 4746
4764 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( 4747 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary(
4765 Zone* zone, bool opt) const { 4748 Zone* zone,
4749 bool opt) const {
4766 const intptr_t kNumInputs = 4; 4750 const intptr_t kNumInputs = 4;
4767 const intptr_t kNumTemps = 0; 4751 const intptr_t kNumTemps = 0;
4768 LocationSummary* summary = new(zone) LocationSummary( 4752 LocationSummary* summary = new (zone)
4769 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4753 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4770 summary->set_in(0, Location::RequiresRegister()); 4754 summary->set_in(0, Location::RequiresRegister());
4771 summary->set_in(1, Location::RequiresRegister()); 4755 summary->set_in(1, Location::RequiresRegister());
4772 summary->set_in(2, Location::RequiresRegister()); 4756 summary->set_in(2, Location::RequiresRegister());
4773 summary->set_in(3, Location::RequiresRegister()); 4757 summary->set_in(3, Location::RequiresRegister());
4774 summary->set_out(0, Location::RequiresFpuRegister()); 4758 summary->set_out(0, Location::RequiresFpuRegister());
4775 return summary; 4759 return summary;
4776 } 4760 }
4777 4761
4778 4762
4779 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4763 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
4821 4805
4822 __ movups(result, Address(ESP, 0)); 4806 __ movups(result, Address(ESP, 0));
4823 __ addl(ESP, Immediate(16)); 4807 __ addl(ESP, Immediate(16));
4824 } 4808 }
4825 4809
4826 4810
4827 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, 4811 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone,
4828 bool opt) const { 4812 bool opt) const {
4829 const intptr_t kNumInputs = 1; 4813 const intptr_t kNumInputs = 1;
4830 const intptr_t kNumTemps = 0; 4814 const intptr_t kNumTemps = 0;
4831 LocationSummary* summary = new(zone) LocationSummary( 4815 LocationSummary* summary = new (zone)
4832 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4816 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4833 summary->set_in(0, Location::RequiresFpuRegister()); 4817 summary->set_in(0, Location::RequiresFpuRegister());
4834 summary->set_out(0, Location::RequiresRegister()); 4818 summary->set_out(0, Location::RequiresRegister());
4835 return summary; 4819 return summary;
4836 } 4820 }
4837 4821
4838 4822
4839 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4823 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4840 XmmRegister value = locs()->in(0).fpu_reg(); 4824 XmmRegister value = locs()->in(0).fpu_reg();
4841 Register result = locs()->out(0).reg(); 4825 Register result = locs()->out(0).reg();
4842 Label done; 4826 Label done;
4843 Label non_zero; 4827 Label non_zero;
4844 __ subl(ESP, Immediate(16)); 4828 __ subl(ESP, Immediate(16));
4845 // Move value to stack. 4829 // Move value to stack.
4846 __ movups(Address(ESP, 0), value); 4830 __ movups(Address(ESP, 0), value);
4847 switch (op_kind()) { 4831 switch (op_kind()) {
4848 case MethodRecognizer::kInt32x4GetFlagX: 4832 case MethodRecognizer::kInt32x4GetFlagX:
4849 __ movl(result, Address(ESP, 0)); 4833 __ movl(result, Address(ESP, 0));
4850 break; 4834 break;
4851 case MethodRecognizer::kInt32x4GetFlagY: 4835 case MethodRecognizer::kInt32x4GetFlagY:
4852 __ movl(result, Address(ESP, 4)); 4836 __ movl(result, Address(ESP, 4));
4853 break; 4837 break;
4854 case MethodRecognizer::kInt32x4GetFlagZ: 4838 case MethodRecognizer::kInt32x4GetFlagZ:
4855 __ movl(result, Address(ESP, 8)); 4839 __ movl(result, Address(ESP, 8));
4856 break; 4840 break;
4857 case MethodRecognizer::kInt32x4GetFlagW: 4841 case MethodRecognizer::kInt32x4GetFlagW:
4858 __ movl(result, Address(ESP, 12)); 4842 __ movl(result, Address(ESP, 12));
4859 break; 4843 break;
4860 default: UNREACHABLE(); 4844 default:
4845 UNREACHABLE();
4861 } 4846 }
4862 __ addl(ESP, Immediate(16)); 4847 __ addl(ESP, Immediate(16));
4863 __ testl(result, result); 4848 __ testl(result, result);
4864 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); 4849 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump);
4865 __ LoadObject(result, Bool::False()); 4850 __ LoadObject(result, Bool::False());
4866 __ jmp(&done); 4851 __ jmp(&done);
4867 __ Bind(&non_zero); 4852 __ Bind(&non_zero);
4868 __ LoadObject(result, Bool::True()); 4853 __ LoadObject(result, Bool::True());
4869 __ Bind(&done); 4854 __ Bind(&done);
4870 } 4855 }
4871 4856
4872 4857
4873 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, 4858 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone,
4874 bool opt) const { 4859 bool opt) const {
4875 const intptr_t kNumInputs = 3; 4860 const intptr_t kNumInputs = 3;
4876 const intptr_t kNumTemps = 1; 4861 const intptr_t kNumTemps = 1;
4877 LocationSummary* summary = new(zone) LocationSummary( 4862 LocationSummary* summary = new (zone)
4878 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4863 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4879 summary->set_in(0, Location::RequiresFpuRegister()); 4864 summary->set_in(0, Location::RequiresFpuRegister());
4880 summary->set_in(1, Location::RequiresFpuRegister()); 4865 summary->set_in(1, Location::RequiresFpuRegister());
4881 summary->set_in(2, Location::RequiresFpuRegister()); 4866 summary->set_in(2, Location::RequiresFpuRegister());
4882 summary->set_temp(0, Location::RequiresFpuRegister()); 4867 summary->set_temp(0, Location::RequiresFpuRegister());
4883 summary->set_out(0, Location::SameAsFirstInput()); 4868 summary->set_out(0, Location::SameAsFirstInput());
4884 return summary; 4869 return summary;
4885 } 4870 }
4886 4871
4887 4872
4888 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4873 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 13 matching lines...) Expand all
4902 __ andps(temp, falseValue); 4887 __ andps(temp, falseValue);
4903 // out = mask | temp. 4888 // out = mask | temp.
4904 __ orps(mask, temp); 4889 __ orps(mask, temp);
4905 } 4890 }
4906 4891
4907 4892
4908 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, 4893 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone,
4909 bool opt) const { 4894 bool opt) const {
4910 const intptr_t kNumInputs = 2; 4895 const intptr_t kNumInputs = 2;
4911 const intptr_t kNumTemps = 0; 4896 const intptr_t kNumTemps = 0;
4912 LocationSummary* summary = new(zone) LocationSummary( 4897 LocationSummary* summary = new (zone)
4913 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4898 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4914 summary->set_in(0, Location::RequiresFpuRegister()); 4899 summary->set_in(0, Location::RequiresFpuRegister());
4915 summary->set_in(1, Location::RequiresRegister()); 4900 summary->set_in(1, Location::RequiresRegister());
4916 summary->set_out(0, Location::SameAsFirstInput()); 4901 summary->set_out(0, Location::SameAsFirstInput());
4917 return summary; 4902 return summary;
4918 } 4903 }
4919 4904
4920 4905
4921 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4906 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4922 XmmRegister mask = locs()->in(0).fpu_reg(); 4907 XmmRegister mask = locs()->in(0).fpu_reg();
4923 Register flag = locs()->in(1).reg(); 4908 Register flag = locs()->in(1).reg();
4924 ASSERT(mask == locs()->out(0).fpu_reg()); 4909 ASSERT(mask == locs()->out(0).fpu_reg());
4925 __ subl(ESP, Immediate(16)); 4910 __ subl(ESP, Immediate(16));
4926 // Copy mask to stack. 4911 // Copy mask to stack.
4927 __ movups(Address(ESP, 0), mask); 4912 __ movups(Address(ESP, 0), mask);
4928 Label falsePath, exitPath; 4913 Label falsePath, exitPath;
4929 __ CompareObject(flag, Bool::True()); 4914 __ CompareObject(flag, Bool::True());
4930 __ j(NOT_EQUAL, &falsePath); 4915 __ j(NOT_EQUAL, &falsePath);
4931 switch (op_kind()) { 4916 switch (op_kind()) {
4932 case MethodRecognizer::kInt32x4WithFlagX: 4917 case MethodRecognizer::kInt32x4WithFlagX:
4933 __ movl(Address(ESP, 0), Immediate(0xFFFFFFFF)); 4918 __ movl(Address(ESP, 0), Immediate(0xFFFFFFFF));
4934 __ jmp(&exitPath); 4919 __ jmp(&exitPath);
4935 __ Bind(&falsePath); 4920 __ Bind(&falsePath);
4936 __ movl(Address(ESP, 0), Immediate(0x0)); 4921 __ movl(Address(ESP, 0), Immediate(0x0));
4937 break; 4922 break;
4938 case MethodRecognizer::kInt32x4WithFlagY: 4923 case MethodRecognizer::kInt32x4WithFlagY:
4939 __ movl(Address(ESP, 4), Immediate(0xFFFFFFFF)); 4924 __ movl(Address(ESP, 4), Immediate(0xFFFFFFFF));
4940 __ jmp(&exitPath); 4925 __ jmp(&exitPath);
4941 __ Bind(&falsePath); 4926 __ Bind(&falsePath);
4942 __ movl(Address(ESP, 4), Immediate(0x0)); 4927 __ movl(Address(ESP, 4), Immediate(0x0));
4943 break; 4928 break;
4944 case MethodRecognizer::kInt32x4WithFlagZ: 4929 case MethodRecognizer::kInt32x4WithFlagZ:
4945 __ movl(Address(ESP, 8), Immediate(0xFFFFFFFF)); 4930 __ movl(Address(ESP, 8), Immediate(0xFFFFFFFF));
4946 __ jmp(&exitPath); 4931 __ jmp(&exitPath);
4947 __ Bind(&falsePath); 4932 __ Bind(&falsePath);
4948 __ movl(Address(ESP, 8), Immediate(0x0)); 4933 __ movl(Address(ESP, 8), Immediate(0x0));
4949 break; 4934 break;
4950 case MethodRecognizer::kInt32x4WithFlagW: 4935 case MethodRecognizer::kInt32x4WithFlagW:
4951 __ movl(Address(ESP, 12), Immediate(0xFFFFFFFF)); 4936 __ movl(Address(ESP, 12), Immediate(0xFFFFFFFF));
4952 __ jmp(&exitPath); 4937 __ jmp(&exitPath);
4953 __ Bind(&falsePath); 4938 __ Bind(&falsePath);
4954 __ movl(Address(ESP, 12), Immediate(0x0)); 4939 __ movl(Address(ESP, 12), Immediate(0x0));
4955 break; 4940 break;
4956 default: UNREACHABLE(); 4941 default:
4942 UNREACHABLE();
4957 } 4943 }
4958 __ Bind(&exitPath); 4944 __ Bind(&exitPath);
4959 // Copy mask back to register. 4945 // Copy mask back to register.
4960 __ movups(mask, Address(ESP, 0)); 4946 __ movups(mask, Address(ESP, 0));
4961 __ addl(ESP, Immediate(16)); 4947 __ addl(ESP, Immediate(16));
4962 } 4948 }
4963 4949
4964 4950
4965 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, 4951 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone,
4966 bool opt) const { 4952 bool opt) const {
4967 const intptr_t kNumInputs = 1; 4953 const intptr_t kNumInputs = 1;
4968 const intptr_t kNumTemps = 0; 4954 const intptr_t kNumTemps = 0;
4969 LocationSummary* summary = new(zone) LocationSummary( 4955 LocationSummary* summary = new (zone)
4970 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4956 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4971 summary->set_in(0, Location::RequiresFpuRegister()); 4957 summary->set_in(0, Location::RequiresFpuRegister());
4972 summary->set_out(0, Location::SameAsFirstInput()); 4958 summary->set_out(0, Location::SameAsFirstInput());
4973 return summary; 4959 return summary;
4974 } 4960 }
4975 4961
4976 4962
4977 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 4963 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
4978 // NOP. 4964 // NOP.
4979 } 4965 }
4980 4966
4981 4967
4982 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, 4968 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone,
4983 bool opt) const { 4969 bool opt) const {
4984 const intptr_t kNumInputs = 2; 4970 const intptr_t kNumInputs = 2;
4985 const intptr_t kNumTemps = 0; 4971 const intptr_t kNumTemps = 0;
4986 LocationSummary* summary = new(zone) LocationSummary( 4972 LocationSummary* summary = new (zone)
4987 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4973 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4988 summary->set_in(0, Location::RequiresFpuRegister()); 4974 summary->set_in(0, Location::RequiresFpuRegister());
4989 summary->set_in(1, Location::RequiresFpuRegister()); 4975 summary->set_in(1, Location::RequiresFpuRegister());
4990 summary->set_out(0, Location::SameAsFirstInput()); 4976 summary->set_out(0, Location::SameAsFirstInput());
4991 return summary; 4977 return summary;
4992 } 4978 }
4993 4979
4994 4980
4995 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4981 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4996 XmmRegister left = locs()->in(0).fpu_reg(); 4982 XmmRegister left = locs()->in(0).fpu_reg();
4997 XmmRegister right = locs()->in(1).fpu_reg(); 4983 XmmRegister right = locs()->in(1).fpu_reg();
(...skipping 10 matching lines...) Expand all
5008 case Token::kBIT_XOR: { 4994 case Token::kBIT_XOR: {
5009 __ xorps(left, right); 4995 __ xorps(left, right);
5010 break; 4996 break;
5011 } 4997 }
5012 case Token::kADD: 4998 case Token::kADD:
5013 __ addpl(left, right); 4999 __ addpl(left, right);
5014 break; 5000 break;
5015 case Token::kSUB: 5001 case Token::kSUB:
5016 __ subpl(left, right); 5002 __ subpl(left, right);
5017 break; 5003 break;
5018 default: UNREACHABLE(); 5004 default:
5005 UNREACHABLE();
5019 } 5006 }
5020 } 5007 }
5021 5008
5022 5009
5023 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, 5010 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone,
5024 bool opt) const { 5011 bool opt) const {
5025 ASSERT((kind() == MathUnaryInstr::kSqrt) || 5012 ASSERT((kind() == MathUnaryInstr::kSqrt) ||
5026 (kind() == MathUnaryInstr::kDoubleSquare)); 5013 (kind() == MathUnaryInstr::kDoubleSquare));
5027 const intptr_t kNumInputs = 1; 5014 const intptr_t kNumInputs = 1;
5028 const intptr_t kNumTemps = 0; 5015 const intptr_t kNumTemps = 0;
5029 LocationSummary* summary = new(zone) LocationSummary( 5016 LocationSummary* summary = new (zone)
5030 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5017 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5031 summary->set_in(0, Location::RequiresFpuRegister()); 5018 summary->set_in(0, Location::RequiresFpuRegister());
5032 if (kind() == MathUnaryInstr::kDoubleSquare) { 5019 if (kind() == MathUnaryInstr::kDoubleSquare) {
5033 summary->set_out(0, Location::SameAsFirstInput()); 5020 summary->set_out(0, Location::SameAsFirstInput());
5034 } else { 5021 } else {
5035 summary->set_out(0, Location::RequiresFpuRegister()); 5022 summary->set_out(0, Location::RequiresFpuRegister());
5036 } 5023 }
5037 return summary; 5024 return summary;
5038 } 5025 }
5039 5026
5040 5027
5041 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5028 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5042 if (kind() == MathUnaryInstr::kSqrt) { 5029 if (kind() == MathUnaryInstr::kSqrt) {
5043 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); 5030 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg());
5044 } else if (kind() == MathUnaryInstr::kDoubleSquare) { 5031 } else if (kind() == MathUnaryInstr::kDoubleSquare) {
5045 XmmRegister value_reg = locs()->in(0).fpu_reg(); 5032 XmmRegister value_reg = locs()->in(0).fpu_reg();
5046 __ mulsd(value_reg, value_reg); 5033 __ mulsd(value_reg, value_reg);
5047 ASSERT(value_reg == locs()->out(0).fpu_reg()); 5034 ASSERT(value_reg == locs()->out(0).fpu_reg());
5048 } else { 5035 } else {
5049 UNREACHABLE(); 5036 UNREACHABLE();
5050 } 5037 }
5051 } 5038 }
5052 5039
5053 5040
5054 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( 5041 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary(
5055 Zone* zone, bool opt) const { 5042 Zone* zone,
5043 bool opt) const {
5056 const intptr_t kNumTemps = 0; 5044 const intptr_t kNumTemps = 0;
5057 LocationSummary* summary = new(zone) LocationSummary( 5045 LocationSummary* summary = new (zone)
5058 zone, InputCount(), kNumTemps, LocationSummary::kCall); 5046 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall);
5059 summary->set_in(0, Location::RegisterLocation(EAX)); 5047 summary->set_in(0, Location::RegisterLocation(EAX));
5060 summary->set_in(1, Location::RegisterLocation(ECX)); 5048 summary->set_in(1, Location::RegisterLocation(ECX));
5061 summary->set_in(2, Location::RegisterLocation(EDX)); 5049 summary->set_in(2, Location::RegisterLocation(EDX));
5062 summary->set_in(3, Location::RegisterLocation(EBX)); 5050 summary->set_in(3, Location::RegisterLocation(EBX));
5063 summary->set_out(0, Location::RegisterLocation(EAX)); 5051 summary->set_out(0, Location::RegisterLocation(EAX));
5064 return summary; 5052 return summary;
5065 } 5053 }
5066 5054
5067 5055
5068 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( 5056 void CaseInsensitiveCompareUC16Instr::EmitNativeCode(
5069 FlowGraphCompiler* compiler) { 5057 FlowGraphCompiler* compiler) {
5070
5071 // Save ESP. EDI is chosen because it is callee saved so we do not need to 5058 // Save ESP. EDI is chosen because it is callee saved so we do not need to
5072 // back it up before calling into the runtime. 5059 // back it up before calling into the runtime.
5073 static const Register kSavedSPReg = EDI; 5060 static const Register kSavedSPReg = EDI;
5074 __ movl(kSavedSPReg, ESP); 5061 __ movl(kSavedSPReg, ESP);
5075 __ ReserveAlignedFrameSpace(kWordSize * TargetFunction().argument_count()); 5062 __ ReserveAlignedFrameSpace(kWordSize * TargetFunction().argument_count());
5076 5063
5077 __ movl(Address(ESP, + 0 * kWordSize), locs()->in(0).reg()); 5064 __ movl(Address(ESP, +0 * kWordSize), locs()->in(0).reg());
5078 __ movl(Address(ESP, + 1 * kWordSize), locs()->in(1).reg()); 5065 __ movl(Address(ESP, +1 * kWordSize), locs()->in(1).reg());
5079 __ movl(Address(ESP, + 2 * kWordSize), locs()->in(2).reg()); 5066 __ movl(Address(ESP, +2 * kWordSize), locs()->in(2).reg());
5080 __ movl(Address(ESP, + 3 * kWordSize), locs()->in(3).reg()); 5067 __ movl(Address(ESP, +3 * kWordSize), locs()->in(3).reg());
5081 5068
5082 // Call the function. 5069 // Call the function.
5083 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); 5070 __ CallRuntime(TargetFunction(), TargetFunction().argument_count());
5084 5071
5085 // Restore ESP. 5072 // Restore ESP.
5086 __ movl(ESP, kSavedSPReg); 5073 __ movl(ESP, kSavedSPReg);
5087 } 5074 }
5088 5075
5089 5076
5090 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, 5077 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone,
5091 bool opt) const { 5078 bool opt) const {
5092 if (result_cid() == kDoubleCid) { 5079 if (result_cid() == kDoubleCid) {
5093 const intptr_t kNumInputs = 2; 5080 const intptr_t kNumInputs = 2;
5094 const intptr_t kNumTemps = 1; 5081 const intptr_t kNumTemps = 1;
5095 LocationSummary* summary = new(zone) LocationSummary( 5082 LocationSummary* summary = new (zone)
5096 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5083 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5097 summary->set_in(0, Location::RequiresFpuRegister()); 5084 summary->set_in(0, Location::RequiresFpuRegister());
5098 summary->set_in(1, Location::RequiresFpuRegister()); 5085 summary->set_in(1, Location::RequiresFpuRegister());
5099 // Reuse the left register so that code can be made shorter. 5086 // Reuse the left register so that code can be made shorter.
5100 summary->set_out(0, Location::SameAsFirstInput()); 5087 summary->set_out(0, Location::SameAsFirstInput());
5101 summary->set_temp(0, Location::RequiresRegister()); 5088 summary->set_temp(0, Location::RequiresRegister());
5102 return summary; 5089 return summary;
5103 } 5090 }
5104 5091
5105 ASSERT(result_cid() == kSmiCid); 5092 ASSERT(result_cid() == kSmiCid);
5106 const intptr_t kNumInputs = 2; 5093 const intptr_t kNumInputs = 2;
5107 const intptr_t kNumTemps = 0; 5094 const intptr_t kNumTemps = 0;
5108 LocationSummary* summary = new(zone) LocationSummary( 5095 LocationSummary* summary = new (zone)
5109 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5096 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5110 summary->set_in(0, Location::RequiresRegister()); 5097 summary->set_in(0, Location::RequiresRegister());
5111 summary->set_in(1, Location::RequiresRegister()); 5098 summary->set_in(1, Location::RequiresRegister());
5112 // Reuse the left register so that code can be made shorter. 5099 // Reuse the left register so that code can be made shorter.
5113 summary->set_out(0, Location::SameAsFirstInput()); 5100 summary->set_out(0, Location::SameAsFirstInput());
5114 return summary; 5101 return summary;
5115 } 5102 }
5116 5103
5117 5104
5118 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5105 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5119 ASSERT((op_kind() == MethodRecognizer::kMathMin) || 5106 ASSERT((op_kind() == MethodRecognizer::kMathMin) ||
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
5172 __ cmovgel(result, right); 5159 __ cmovgel(result, right);
5173 } else { 5160 } else {
5174 __ cmovlessl(result, right); 5161 __ cmovlessl(result, right);
5175 } 5162 }
5176 } 5163 }
5177 5164
5178 5165
5179 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, 5166 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone,
5180 bool opt) const { 5167 bool opt) const {
5181 const intptr_t kNumInputs = 1; 5168 const intptr_t kNumInputs = 1;
5182 return LocationSummary::Make(zone, 5169 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(),
5183 kNumInputs,
5184 Location::SameAsFirstInput(),
5185 LocationSummary::kNoCall); 5170 LocationSummary::kNoCall);
5186 } 5171 }
5187 5172
5188 5173
5189 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5174 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5190 Register value = locs()->in(0).reg(); 5175 Register value = locs()->in(0).reg();
5191 ASSERT(value == locs()->out(0).reg()); 5176 ASSERT(value == locs()->out(0).reg());
5192 switch (op_kind()) { 5177 switch (op_kind()) {
5193 case Token::kNEGATE: { 5178 case Token::kNEGATE: {
5194 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); 5179 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
5195 __ negl(value); 5180 __ negl(value);
5196 __ j(OVERFLOW, deopt); 5181 __ j(OVERFLOW, deopt);
5197 break; 5182 break;
5198 } 5183 }
5199 case Token::kBIT_NOT: 5184 case Token::kBIT_NOT:
5200 __ notl(value); 5185 __ notl(value);
5201 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. 5186 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag.
5202 break; 5187 break;
5203 default: 5188 default:
5204 UNREACHABLE(); 5189 UNREACHABLE();
5205 } 5190 }
5206 } 5191 }
5207 5192
5208 5193
5209 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, 5194 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone,
5210 bool opt) const { 5195 bool opt) const {
5211 const intptr_t kNumInputs = 1; 5196 const intptr_t kNumInputs = 1;
5212 const intptr_t kNumTemps = 0; 5197 const intptr_t kNumTemps = 0;
5213 LocationSummary* summary = new(zone) LocationSummary( 5198 LocationSummary* summary = new (zone)
5214 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5199 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5215 summary->set_in(0, Location::RequiresFpuRegister()); 5200 summary->set_in(0, Location::RequiresFpuRegister());
5216 summary->set_out(0, Location::SameAsFirstInput()); 5201 summary->set_out(0, Location::SameAsFirstInput());
5217 return summary; 5202 return summary;
5218 } 5203 }
5219 5204
5220 5205
5221 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5206 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5222 XmmRegister value = locs()->in(0).fpu_reg(); 5207 XmmRegister value = locs()->in(0).fpu_reg();
5223 ASSERT(locs()->out(0).fpu_reg() == value); 5208 ASSERT(locs()->out(0).fpu_reg() == value);
5224 __ DoubleNegate(value); 5209 __ DoubleNegate(value);
5225 } 5210 }
5226 5211
5227 5212
5228 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, 5213 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone,
5229 bool opt) const { 5214 bool opt) const {
5230 const intptr_t kNumInputs = 1; 5215 const intptr_t kNumInputs = 1;
5231 const intptr_t kNumTemps = 0; 5216 const intptr_t kNumTemps = 0;
5232 LocationSummary* result = new(zone) LocationSummary( 5217 LocationSummary* result = new (zone)
5233 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5218 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5234 result->set_in(0, Location::RequiresRegister()); 5219 result->set_in(0, Location::RequiresRegister());
5235 result->set_out(0, Location::RequiresFpuRegister()); 5220 result->set_out(0, Location::RequiresFpuRegister());
5236 return result; 5221 return result;
5237 } 5222 }
5238 5223
5239 5224
5240 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5225 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5241 Register value = locs()->in(0).reg(); 5226 Register value = locs()->in(0).reg();
5242 FpuRegister result = locs()->out(0).fpu_reg(); 5227 FpuRegister result = locs()->out(0).fpu_reg();
5243 __ cvtsi2sd(result, value); 5228 __ cvtsi2sd(result, value);
5244 } 5229 }
5245 5230
5246 5231
5247 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, 5232 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone,
5248 bool opt) const { 5233 bool opt) const {
5249 const intptr_t kNumInputs = 1; 5234 const intptr_t kNumInputs = 1;
5250 const intptr_t kNumTemps = 0; 5235 const intptr_t kNumTemps = 0;
5251 LocationSummary* result = new(zone) LocationSummary( 5236 LocationSummary* result = new (zone)
5252 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5237 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5253 result->set_in(0, Location::WritableRegister()); 5238 result->set_in(0, Location::WritableRegister());
5254 result->set_out(0, Location::RequiresFpuRegister()); 5239 result->set_out(0, Location::RequiresFpuRegister());
5255 return result; 5240 return result;
5256 } 5241 }
5257 5242
5258 5243
5259 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5244 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5260 Register value = locs()->in(0).reg(); 5245 Register value = locs()->in(0).reg();
5261 FpuRegister result = locs()->out(0).fpu_reg(); 5246 FpuRegister result = locs()->out(0).fpu_reg();
5262 __ SmiUntag(value); 5247 __ SmiUntag(value);
5263 __ cvtsi2sd(result, value); 5248 __ cvtsi2sd(result, value);
5264 } 5249 }
5265 5250
5266 5251
5267 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone, 5252 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone,
5268 bool opt) const { 5253 bool opt) const {
5269 const intptr_t kNumInputs = 1; 5254 const intptr_t kNumInputs = 1;
5270 const intptr_t kNumTemps = 0; 5255 const intptr_t kNumTemps = 0;
5271 LocationSummary* result = new(zone) LocationSummary( 5256 LocationSummary* result = new (zone)
5272 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5257 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5273 result->set_in(0, Location::Pair(Location::RequiresRegister(), 5258 result->set_in(0, Location::Pair(Location::RequiresRegister(),
5274 Location::RequiresRegister())); 5259 Location::RequiresRegister()));
5275 result->set_out(0, Location::RequiresFpuRegister()); 5260 result->set_out(0, Location::RequiresFpuRegister());
5276 return result; 5261 return result;
5277 } 5262 }
5278 5263
5279 5264
5280 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5265 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5281 PairLocation* pair = locs()->in(0).AsPairLocation(); 5266 PairLocation* pair = locs()->in(0).AsPairLocation();
5282 Register in_lo = pair->At(0).reg(); 5267 Register in_lo = pair->At(0).reg();
(...skipping 13 matching lines...) Expand all
5296 __ movsd(result, Address(ESP, 0)); 5281 __ movsd(result, Address(ESP, 0));
5297 // Pop args. 5282 // Pop args.
5298 __ addl(ESP, Immediate(2 * kWordSize)); 5283 __ addl(ESP, Immediate(2 * kWordSize));
5299 } 5284 }
5300 5285
5301 5286
5302 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, 5287 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone,
5303 bool opt) const { 5288 bool opt) const {
5304 const intptr_t kNumInputs = 1; 5289 const intptr_t kNumInputs = 1;
5305 const intptr_t kNumTemps = 0; 5290 const intptr_t kNumTemps = 0;
5306 LocationSummary* result = new(zone) LocationSummary( 5291 LocationSummary* result = new (zone)
5307 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 5292 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
5308 result->set_in(0, Location::RegisterLocation(ECX)); 5293 result->set_in(0, Location::RegisterLocation(ECX));
5309 result->set_out(0, Location::RegisterLocation(EAX)); 5294 result->set_out(0, Location::RegisterLocation(EAX));
5310 return result; 5295 return result;
5311 } 5296 }
5312 5297
5313 5298
5314 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5299 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5315 Register result = locs()->out(0).reg(); 5300 Register result = locs()->out(0).reg();
5316 Register value_obj = locs()->in(0).reg(); 5301 Register value_obj = locs()->in(0).reg();
5317 XmmRegister value_double = XMM0; 5302 XmmRegister value_double = XMM0;
5318 ASSERT(result == EAX); 5303 ASSERT(result == EAX);
5319 ASSERT(result != value_obj); 5304 ASSERT(result != value_obj);
5320 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); 5305 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset()));
5321 __ cvttsd2si(result, value_double); 5306 __ cvttsd2si(result, value_double);
5322 // Overflow is signalled with minint. 5307 // Overflow is signalled with minint.
5323 Label do_call, done; 5308 Label do_call, done;
5324 // Check for overflow and that it fits into Smi. 5309 // Check for overflow and that it fits into Smi.
5325 __ cmpl(result, Immediate(0xC0000000)); 5310 __ cmpl(result, Immediate(0xC0000000));
5326 __ j(NEGATIVE, &do_call, Assembler::kNearJump); 5311 __ j(NEGATIVE, &do_call, Assembler::kNearJump);
5327 __ SmiTag(result); 5312 __ SmiTag(result);
5328 __ jmp(&done); 5313 __ jmp(&done);
5329 __ Bind(&do_call); 5314 __ Bind(&do_call);
5330 __ pushl(value_obj); 5315 __ pushl(value_obj);
5331 ASSERT(instance_call()->HasICData()); 5316 ASSERT(instance_call()->HasICData());
5332 const ICData& ic_data = *instance_call()->ic_data(); 5317 const ICData& ic_data = *instance_call()->ic_data();
5333 ASSERT((ic_data.NumberOfChecks() == 1)); 5318 ASSERT((ic_data.NumberOfChecks() == 1));
5334 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); 5319 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
5335 5320
5336 const intptr_t kNumberOfArguments = 1; 5321 const intptr_t kNumberOfArguments = 1;
5337 compiler->GenerateStaticCall(deopt_id(), 5322 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
5338 instance_call()->token_pos(),
5339 target,
5340 kNumberOfArguments, 5323 kNumberOfArguments,
5341 Object::null_array(), // No argument names. 5324 Object::null_array(), // No argument names.
5342 locs(), 5325 locs(), ICData::Handle());
5343 ICData::Handle());
5344 __ Bind(&done); 5326 __ Bind(&done);
5345 } 5327 }
5346 5328
5347 5329
5348 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, 5330 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone,
5349 bool opt) const { 5331 bool opt) const {
5350 const intptr_t kNumInputs = 1; 5332 const intptr_t kNumInputs = 1;
5351 const intptr_t kNumTemps = 0; 5333 const intptr_t kNumTemps = 0;
5352 LocationSummary* result = new(zone) LocationSummary( 5334 LocationSummary* result = new (zone)
5353 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5335 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5354 result->set_in(0, Location::RequiresFpuRegister()); 5336 result->set_in(0, Location::RequiresFpuRegister());
5355 result->set_out(0, Location::RequiresRegister()); 5337 result->set_out(0, Location::RequiresRegister());
5356 return result; 5338 return result;
5357 } 5339 }
5358 5340
5359 5341
5360 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5342 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5361 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); 5343 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi);
5362 Register result = locs()->out(0).reg(); 5344 Register result = locs()->out(0).reg();
5363 XmmRegister value = locs()->in(0).fpu_reg(); 5345 XmmRegister value = locs()->in(0).fpu_reg();
5364 __ cvttsd2si(result, value); 5346 __ cvttsd2si(result, value);
5365 // Check for overflow and that it fits into Smi. 5347 // Check for overflow and that it fits into Smi.
5366 __ cmpl(result, Immediate(0xC0000000)); 5348 __ cmpl(result, Immediate(0xC0000000));
5367 __ j(NEGATIVE, deopt); 5349 __ j(NEGATIVE, deopt);
5368 __ SmiTag(result); 5350 __ SmiTag(result);
5369 } 5351 }
5370 5352
5371 5353
5372 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, 5354 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
5373 bool opt) const { 5355 bool opt) const {
5374 const intptr_t kNumInputs = 1; 5356 const intptr_t kNumInputs = 1;
5375 const intptr_t kNumTemps = 0; 5357 const intptr_t kNumTemps = 0;
5376 LocationSummary* result = new(zone) LocationSummary( 5358 LocationSummary* result = new (zone)
5377 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5359 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5378 result->set_in(0, Location::RequiresFpuRegister()); 5360 result->set_in(0, Location::RequiresFpuRegister());
5379 result->set_out(0, Location::RequiresFpuRegister()); 5361 result->set_out(0, Location::RequiresFpuRegister());
5380 return result; 5362 return result;
5381 } 5363 }
5382 5364
5383 5365
5384 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5366 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5385 XmmRegister value = locs()->in(0).fpu_reg(); 5367 XmmRegister value = locs()->in(0).fpu_reg();
5386 XmmRegister result = locs()->out(0).fpu_reg(); 5368 XmmRegister result = locs()->out(0).fpu_reg();
5387 switch (recognized_kind()) { 5369 switch (recognized_kind()) {
5388 case MethodRecognizer::kDoubleTruncate: 5370 case MethodRecognizer::kDoubleTruncate:
5389 __ roundsd(result, value, Assembler::kRoundToZero); 5371 __ roundsd(result, value, Assembler::kRoundToZero);
5390 break; 5372 break;
5391 case MethodRecognizer::kDoubleFloor: 5373 case MethodRecognizer::kDoubleFloor:
5392 __ roundsd(result, value, Assembler::kRoundDown); 5374 __ roundsd(result, value, Assembler::kRoundDown);
5393 break; 5375 break;
5394 case MethodRecognizer::kDoubleCeil: 5376 case MethodRecognizer::kDoubleCeil:
5395 __ roundsd(result, value, Assembler::kRoundUp); 5377 __ roundsd(result, value, Assembler::kRoundUp);
5396 break; 5378 break;
5397 default: 5379 default:
5398 UNREACHABLE(); 5380 UNREACHABLE();
5399 } 5381 }
5400 } 5382 }
5401 5383
5402 5384
5403 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, 5385 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone,
5404 bool opt) const { 5386 bool opt) const {
5405 const intptr_t kNumInputs = 1; 5387 const intptr_t kNumInputs = 1;
5406 const intptr_t kNumTemps = 0; 5388 const intptr_t kNumTemps = 0;
5407 LocationSummary* result = new(zone) LocationSummary( 5389 LocationSummary* result = new (zone)
5408 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5390 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5409 result->set_in(0, Location::RequiresFpuRegister()); 5391 result->set_in(0, Location::RequiresFpuRegister());
5410 result->set_out(0, Location::SameAsFirstInput()); 5392 result->set_out(0, Location::SameAsFirstInput());
5411 return result; 5393 return result;
5412 } 5394 }
5413 5395
5414 5396
5415 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5397 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5416 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); 5398 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg());
5417 } 5399 }
5418 5400
5419 5401
5420 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, 5402 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone,
5421 bool opt) const { 5403 bool opt) const {
5422 const intptr_t kNumInputs = 1; 5404 const intptr_t kNumInputs = 1;
5423 const intptr_t kNumTemps = 0; 5405 const intptr_t kNumTemps = 0;
5424 LocationSummary* result = new(zone) LocationSummary( 5406 LocationSummary* result = new (zone)
5425 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5407 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5426 result->set_in(0, Location::RequiresFpuRegister()); 5408 result->set_in(0, Location::RequiresFpuRegister());
5427 result->set_out(0, Location::SameAsFirstInput()); 5409 result->set_out(0, Location::SameAsFirstInput());
5428 return result; 5410 return result;
5429 } 5411 }
5430 5412
5431 5413
5432 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5414 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5433 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); 5415 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg());
5434 } 5416 }
5435 5417
5436 5418
5437 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, 5419 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone,
5438 bool opt) const { 5420 bool opt) const {
5439 ASSERT((InputCount() == 1) || (InputCount() == 2)); 5421 ASSERT((InputCount() == 1) || (InputCount() == 2));
5440 const intptr_t kNumTemps = 5422 const intptr_t kNumTemps =
5441 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; 5423 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1;
5442 LocationSummary* result = new(zone) LocationSummary( 5424 LocationSummary* result = new (zone)
5443 zone, InputCount(), kNumTemps, LocationSummary::kCall); 5425 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall);
5444 // EDI is chosen because it is callee saved so we do not need to back it 5426 // EDI is chosen because it is callee saved so we do not need to back it
5445 // up before calling into the runtime. 5427 // up before calling into the runtime.
5446 result->set_temp(0, Location::RegisterLocation(EDI)); 5428 result->set_temp(0, Location::RegisterLocation(EDI));
5447 result->set_in(0, Location::FpuRegisterLocation(XMM1)); 5429 result->set_in(0, Location::FpuRegisterLocation(XMM1));
5448 if (InputCount() == 2) { 5430 if (InputCount() == 2) {
5449 result->set_in(1, Location::FpuRegisterLocation(XMM2)); 5431 result->set_in(1, Location::FpuRegisterLocation(XMM2));
5450 } 5432 }
5451 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { 5433 if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
5452 // Temp index 1. 5434 // Temp index 1.
5453 result->set_temp(1, Location::RegisterLocation(EAX)); 5435 result->set_temp(1, Location::RegisterLocation(EAX));
(...skipping 27 matching lines...) Expand all
5481 ASSERT(instr->InputCount() == kInputCount); 5463 ASSERT(instr->InputCount() == kInputCount);
5482 LocationSummary* locs = instr->locs(); 5464 LocationSummary* locs = instr->locs();
5483 5465
5484 XmmRegister base = locs->in(0).fpu_reg(); 5466 XmmRegister base = locs->in(0).fpu_reg();
5485 XmmRegister exp = locs->in(1).fpu_reg(); 5467 XmmRegister exp = locs->in(1).fpu_reg();
5486 XmmRegister result = locs->out(0).fpu_reg(); 5468 XmmRegister result = locs->out(0).fpu_reg();
5487 Register temp = locs->temp(InvokeMathCFunctionInstr::kObjectTempIndex).reg(); 5469 Register temp = locs->temp(InvokeMathCFunctionInstr::kObjectTempIndex).reg();
5488 XmmRegister zero_temp = 5470 XmmRegister zero_temp =
5489 locs->temp(InvokeMathCFunctionInstr::kDoubleTempIndex).fpu_reg(); 5471 locs->temp(InvokeMathCFunctionInstr::kDoubleTempIndex).fpu_reg();
5490 5472
5491 __ xorps(zero_temp, zero_temp); // 0.0. 5473 __ xorps(zero_temp, zero_temp); // 0.0.
5492 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1.0))); 5474 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1.0)));
5493 __ movsd(result, FieldAddress(temp, Double::value_offset())); 5475 __ movsd(result, FieldAddress(temp, Double::value_offset()));
5494 5476
5495 Label check_base, skip_call; 5477 Label check_base, skip_call;
5496 // exponent == 0.0 -> return 1.0; 5478 // exponent == 0.0 -> return 1.0;
5497 __ comisd(exp, zero_temp); 5479 __ comisd(exp, zero_temp);
5498 __ j(PARITY_EVEN, &check_base); 5480 __ j(PARITY_EVEN, &check_base);
5499 __ j(EQUAL, &skip_call); // 'result' is 1.0. 5481 __ j(EQUAL, &skip_call); // 'result' is 1.0.
5500 5482
5501 // exponent == 1.0 ? 5483 // exponent == 1.0 ?
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
5610 // Restore ESP. 5592 // Restore ESP.
5611 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); 5593 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg());
5612 } 5594 }
5613 5595
5614 5596
5615 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, 5597 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone,
5616 bool opt) const { 5598 bool opt) const {
5617 // Only use this instruction in optimized code. 5599 // Only use this instruction in optimized code.
5618 ASSERT(opt); 5600 ASSERT(opt);
5619 const intptr_t kNumInputs = 1; 5601 const intptr_t kNumInputs = 1;
5620 LocationSummary* summary = new(zone) LocationSummary( 5602 LocationSummary* summary =
5621 zone, kNumInputs, 0, LocationSummary::kNoCall); 5603 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall);
5622 if (representation() == kUnboxedDouble) { 5604 if (representation() == kUnboxedDouble) {
5623 if (index() == 0) { 5605 if (index() == 0) {
5624 summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), 5606 summary->set_in(
5625 Location::Any())); 5607 0, Location::Pair(Location::RequiresFpuRegister(), Location::Any()));
5626 } else { 5608 } else {
5627 ASSERT(index() == 1); 5609 ASSERT(index() == 1);
5628 summary->set_in(0, Location::Pair(Location::Any(), 5610 summary->set_in(
5629 Location::RequiresFpuRegister())); 5611 0, Location::Pair(Location::Any(), Location::RequiresFpuRegister()));
5630 } 5612 }
5631 summary->set_out(0, Location::RequiresFpuRegister()); 5613 summary->set_out(0, Location::RequiresFpuRegister());
5632 } else { 5614 } else {
5633 ASSERT(representation() == kTagged); 5615 ASSERT(representation() == kTagged);
5634 if (index() == 0) { 5616 if (index() == 0) {
5635 summary->set_in(0, Location::Pair(Location::RequiresRegister(), 5617 summary->set_in(
5636 Location::Any())); 5618 0, Location::Pair(Location::RequiresRegister(), Location::Any()));
5637 } else { 5619 } else {
5638 ASSERT(index() == 1); 5620 ASSERT(index() == 1);
5639 summary->set_in(0, Location::Pair(Location::Any(), 5621 summary->set_in(
5640 Location::RequiresRegister())); 5622 0, Location::Pair(Location::Any(), Location::RequiresRegister()));
5641 } 5623 }
5642 summary->set_out(0, Location::RequiresRegister()); 5624 summary->set_out(0, Location::RequiresRegister());
5643 } 5625 }
5644 return summary; 5626 return summary;
5645 } 5627 }
5646 5628
5647 5629
5648 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5630 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5649 ASSERT(locs()->in(0).IsPairLocation()); 5631 ASSERT(locs()->in(0).IsPairLocation());
5650 PairLocation* pair = locs()->in(0).AsPairLocation(); 5632 PairLocation* pair = locs()->in(0).AsPairLocation();
5651 Location in_loc = pair->At(index()); 5633 Location in_loc = pair->At(index());
5652 if (representation() == kUnboxedDouble) { 5634 if (representation() == kUnboxedDouble) {
5653 XmmRegister out = locs()->out(0).fpu_reg(); 5635 XmmRegister out = locs()->out(0).fpu_reg();
5654 XmmRegister in = in_loc.fpu_reg(); 5636 XmmRegister in = in_loc.fpu_reg();
5655 __ movaps(out, in); 5637 __ movaps(out, in);
5656 } else { 5638 } else {
5657 ASSERT(representation() == kTagged); 5639 ASSERT(representation() == kTagged);
5658 Register out = locs()->out(0).reg(); 5640 Register out = locs()->out(0).reg();
5659 Register in = in_loc.reg(); 5641 Register in = in_loc.reg();
5660 __ movl(out, in); 5642 __ movl(out, in);
5661 } 5643 }
5662 } 5644 }
5663 5645
5664 5646
5665 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, 5647 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone,
5666 bool opt) const { 5648 bool opt) const {
5667 if (kind() == MergedMathInstr::kTruncDivMod) { 5649 if (kind() == MergedMathInstr::kTruncDivMod) {
5668 const intptr_t kNumInputs = 2; 5650 const intptr_t kNumInputs = 2;
5669 const intptr_t kNumTemps = 0; 5651 const intptr_t kNumTemps = 0;
5670 LocationSummary* summary = new(zone) LocationSummary( 5652 LocationSummary* summary = new (zone)
5671 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5653 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5672 // Both inputs must be writable because they will be untagged. 5654 // Both inputs must be writable because they will be untagged.
5673 summary->set_in(0, Location::RegisterLocation(EAX)); 5655 summary->set_in(0, Location::RegisterLocation(EAX));
5674 summary->set_in(1, Location::WritableRegister()); 5656 summary->set_in(1, Location::WritableRegister());
5675 // Output is a pair of registers. 5657 // Output is a pair of registers.
5676 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), 5658 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
5677 Location::RegisterLocation(EDX))); 5659 Location::RegisterLocation(EDX)));
5678 return summary; 5660 return summary;
5679 } 5661 }
5680 if (kind() == MergedMathInstr::kSinCos) { 5662 if (kind() == MergedMathInstr::kSinCos) {
5681 const intptr_t kNumInputs = 1; 5663 const intptr_t kNumInputs = 1;
5682 const intptr_t kNumTemps = 2; 5664 const intptr_t kNumTemps = 2;
5683 LocationSummary* summary = new(zone) LocationSummary( 5665 LocationSummary* summary = new (zone)
5684 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 5666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
5685 // Because we always call into the runtime (LocationSummary::kCall) we 5667 // Because we always call into the runtime (LocationSummary::kCall) we
5686 // must specify each input, temp, and output register explicitly. 5668 // must specify each input, temp, and output register explicitly.
5687 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); 5669 summary->set_in(0, Location::FpuRegisterLocation(XMM1));
5688 // EDI is chosen because it is callee saved so we do not need to back it 5670 // EDI is chosen because it is callee saved so we do not need to back it
5689 // up before calling into the runtime. 5671 // up before calling into the runtime.
5690 summary->set_temp(0, Location::RegisterLocation(EDI)); 5672 summary->set_temp(0, Location::RegisterLocation(EDI));
5691 summary->set_temp(1, Location::RegisterLocation(EBX)); 5673 summary->set_temp(1, Location::RegisterLocation(EBX));
5692 summary->set_out(0, Location::Pair(Location::FpuRegisterLocation(XMM2), 5674 summary->set_out(0, Location::Pair(Location::FpuRegisterLocation(XMM2),
5693 Location::FpuRegisterLocation(XMM3))); 5675 Location::FpuRegisterLocation(XMM3)));
5694 return summary; 5676 return summary;
5695 } 5677 }
5696 UNIMPLEMENTED(); 5678 UNIMPLEMENTED();
5697 return NULL; 5679 return NULL;
5698 } 5680 }
5699 5681
5700 5682
5701 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); 5683 typedef void (*SinCosCFunction)(double x, double* res_sin, double* res_cos);
5702 5684
5703 extern const RuntimeEntry kSinCosRuntimeEntry( 5685 extern const RuntimeEntry kSinCosRuntimeEntry(
5704 "libc_sincos", reinterpret_cast<RuntimeFunction>( 5686 "libc_sincos",
5705 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); 5687 reinterpret_cast<RuntimeFunction>(static_cast<SinCosCFunction>(&SinCos)),
5688 1,
5689 true,
5690 true);
5706 5691
5707 5692
5708 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5693 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5709 Label* deopt = NULL; 5694 Label* deopt = NULL;
5710 if (CanDeoptimize()) { 5695 if (CanDeoptimize()) {
5711 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); 5696 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
5712 } 5697 }
5713 5698
5714 if (kind() == MergedMathInstr::kTruncDivMod) { 5699 if (kind() == MergedMathInstr::kTruncDivMod) {
5715 Register left = locs()->in(0).reg(); 5700 Register left = locs()->in(0).reg();
5716 Register right = locs()->in(1).reg(); 5701 Register right = locs()->in(1).reg();
5717 ASSERT(locs()->out(0).IsPairLocation()); 5702 ASSERT(locs()->out(0).IsPairLocation());
5718 PairLocation* pair = locs()->out(0).AsPairLocation(); 5703 PairLocation* pair = locs()->out(0).AsPairLocation();
5719 Register result1 = pair->At(0).reg(); 5704 Register result1 = pair->At(0).reg();
5720 Register result2 = pair->At(1).reg(); 5705 Register result2 = pair->At(1).reg();
5721 Range* right_range = InputAt(1)->definition()->range(); 5706 Range* right_range = InputAt(1)->definition()->range();
5722 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 5707 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
5723 // Handle divide by zero in runtime. 5708 // Handle divide by zero in runtime.
5724 __ testl(right, right); 5709 __ testl(right, right);
5725 __ j(ZERO, deopt); 5710 __ j(ZERO, deopt);
5726 } 5711 }
5727 ASSERT(left == EAX); 5712 ASSERT(left == EAX);
5728 ASSERT((right != EDX) && (right != EAX)); 5713 ASSERT((right != EDX) && (right != EAX));
5729 ASSERT(result1 == EAX); 5714 ASSERT(result1 == EAX);
5730 ASSERT(result2 == EDX); 5715 ASSERT(result2 == EDX);
5731 __ SmiUntag(left); 5716 __ SmiUntag(left);
5732 __ SmiUntag(right); 5717 __ SmiUntag(right);
5733 __ cdq(); // Sign extend EAX -> EDX:EAX. 5718 __ cdq(); // Sign extend EAX -> EDX:EAX.
5734 __ idivl(right); // EAX: quotient, EDX: remainder. 5719 __ idivl(right); // EAX: quotient, EDX: remainder.
5735 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 5720 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
5736 // case we cannot tag the result. 5721 // case we cannot tag the result.
5737 // TODO(srdjan): We could store instead untagged intermediate results in a 5722 // TODO(srdjan): We could store instead untagged intermediate results in a
5738 // typed array, but then the load indexed instructions would need to be 5723 // typed array, but then the load indexed instructions would need to be
5739 // able to deoptimize. 5724 // able to deoptimize.
5740 __ cmpl(EAX, Immediate(0x40000000)); 5725 __ cmpl(EAX, Immediate(0x40000000));
5741 __ j(EQUAL, deopt); 5726 __ j(EQUAL, deopt);
5742 // Modulo result (EDX) correction: 5727 // Modulo result (EDX) correction:
5743 // res = left % right; 5728 // res = left % right;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
5814 // Restore RSP. 5799 // Restore RSP.
5815 __ movl(ESP, locs()->temp(0).reg()); 5800 __ movl(ESP, locs()->temp(0).reg());
5816 5801
5817 return; 5802 return;
5818 } 5803 }
5819 UNIMPLEMENTED(); 5804 UNIMPLEMENTED();
5820 } 5805 }
5821 5806
5822 5807
5823 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( 5808 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
5824 Zone* zone, bool opt) const { 5809 Zone* zone,
5810 bool opt) const {
5825 return MakeCallSummary(zone); 5811 return MakeCallSummary(zone);
5826 } 5812 }
5827 5813
5828 5814
5829 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, 5815 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const {
5830 bool opt) const {
5831 comparison()->InitializeLocationSummary(zone, opt); 5816 comparison()->InitializeLocationSummary(zone, opt);
5832 // Branches don't produce a result. 5817 // Branches don't produce a result.
5833 comparison()->locs()->set_out(0, Location::NoLocation()); 5818 comparison()->locs()->set_out(0, Location::NoLocation());
5834 return comparison()->locs(); 5819 return comparison()->locs();
5835 } 5820 }
5836 5821
5837 5822
5838 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5823 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5839 comparison()->EmitBranchCode(compiler, this); 5824 comparison()->EmitBranchCode(compiler, this);
5840 } 5825 }
5841 5826
5842 5827
5843 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, 5828 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone,
5844 bool opt) const { 5829 bool opt) const {
5845 const intptr_t kNumInputs = 1; 5830 const intptr_t kNumInputs = 1;
5846 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); 5831 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask());
5847 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; 5832 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0;
5848 LocationSummary* summary = new(zone) LocationSummary( 5833 LocationSummary* summary = new (zone)
5849 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5834 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5850 summary->set_in(0, Location::RequiresRegister()); 5835 summary->set_in(0, Location::RequiresRegister());
5851 if (!IsNullCheck()) { 5836 if (!IsNullCheck()) {
5852 summary->set_temp(0, Location::RequiresRegister()); 5837 summary->set_temp(0, Location::RequiresRegister());
5853 if (need_mask_temp) { 5838 if (need_mask_temp) {
5854 summary->set_temp(1, Location::RequiresRegister()); 5839 summary->set_temp(1, Location::RequiresRegister());
5855 } 5840 }
5856 } 5841 }
5857 return summary; 5842 return summary;
5858 } 5843 }
5859 5844
5860 5845
5861 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5846 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5862 Label* deopt = compiler->AddDeoptStub(deopt_id(), 5847 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass,
5863 ICData::kDeoptCheckClass,
5864 licm_hoisted_ ? ICData::kHoisted : 0); 5848 licm_hoisted_ ? ICData::kHoisted : 0);
5865 if (IsNullCheck()) { 5849 if (IsNullCheck()) {
5866 const Immediate& raw_null = 5850 const Immediate& raw_null =
5867 Immediate(reinterpret_cast<intptr_t>(Object::null())); 5851 Immediate(reinterpret_cast<intptr_t>(Object::null()));
5868 __ cmpl(locs()->in(0).reg(), raw_null); 5852 __ cmpl(locs()->in(0).reg(), raw_null);
5869 ASSERT(DeoptIfNull() || DeoptIfNotNull()); 5853 ASSERT(DeoptIfNull() || DeoptIfNotNull());
5870 Condition cond = DeoptIfNull() ? EQUAL : NOT_EQUAL; 5854 Condition cond = DeoptIfNull() ? EQUAL : NOT_EQUAL;
5871 __ j(cond, deopt); 5855 __ j(cond, deopt);
5872 return; 5856 return;
5873 } 5857 }
(...skipping 22 matching lines...) Expand all
5896 if (!IsDenseMask(mask)) { 5880 if (!IsDenseMask(mask)) {
5897 // Only need mask if there are missing numbers in the range. 5881 // Only need mask if there are missing numbers in the range.
5898 ASSERT(cids_.length() > 2); 5882 ASSERT(cids_.length() > 2);
5899 Register mask_reg = locs()->temp(1).reg(); 5883 Register mask_reg = locs()->temp(1).reg();
5900 __ movl(mask_reg, Immediate(mask)); 5884 __ movl(mask_reg, Immediate(mask));
5901 __ bt(mask_reg, temp); 5885 __ bt(mask_reg, temp);
5902 __ j(NOT_CARRY, deopt); 5886 __ j(NOT_CARRY, deopt);
5903 } 5887 }
5904 } else { 5888 } else {
5905 GrowableArray<CidTarget> sorted_ic_data; 5889 GrowableArray<CidTarget> sorted_ic_data;
5906 FlowGraphCompiler::SortICDataByCount(unary_checks(), 5890 FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data,
5907 &sorted_ic_data,
5908 /* drop_smi = */ true); 5891 /* drop_smi = */ true);
5909 const intptr_t num_checks = sorted_ic_data.length(); 5892 const intptr_t num_checks = sorted_ic_data.length();
5910 const bool use_near_jump = num_checks < 5; 5893 const bool use_near_jump = num_checks < 5;
5911 for (intptr_t i = 0; i < num_checks; i++) { 5894 for (intptr_t i = 0; i < num_checks; i++) {
5912 const intptr_t cid = sorted_ic_data[i].cid; 5895 const intptr_t cid = sorted_ic_data[i].cid;
5913 ASSERT(cid != kSmiCid); 5896 ASSERT(cid != kSmiCid);
5914 __ cmpl(temp, Immediate(cid)); 5897 __ cmpl(temp, Immediate(cid));
5915 if (i == (num_checks - 1)) { 5898 if (i == (num_checks - 1)) {
5916 __ j(NOT_EQUAL, deopt); 5899 __ j(NOT_EQUAL, deopt);
5917 } else { 5900 } else {
5918 if (use_near_jump) { 5901 if (use_near_jump) {
5919 __ j(EQUAL, &is_ok, Assembler::kNearJump); 5902 __ j(EQUAL, &is_ok, Assembler::kNearJump);
5920 } else { 5903 } else {
5921 __ j(EQUAL, &is_ok); 5904 __ j(EQUAL, &is_ok);
5922 } 5905 }
5923 } 5906 }
5924 } 5907 }
5925 } 5908 }
5926 __ Bind(&is_ok); 5909 __ Bind(&is_ok);
5927 } 5910 }
5928 5911
5929 5912
5930 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, 5913 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone,
5931 bool opt) const { 5914 bool opt) const {
5932 const intptr_t kNumInputs = 1; 5915 const intptr_t kNumInputs = 1;
5933 const intptr_t kNumTemps = 0; 5916 const intptr_t kNumTemps = 0;
5934 LocationSummary* summary = new(zone) LocationSummary( 5917 LocationSummary* summary = new (zone)
5935 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5918 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5936 summary->set_in(0, Location::RequiresRegister()); 5919 summary->set_in(0, Location::RequiresRegister());
5937 return summary; 5920 return summary;
5938 } 5921 }
5939 5922
5940 5923
5941 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5924 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5942 Register value = locs()->in(0).reg(); 5925 Register value = locs()->in(0).reg();
5943 Label* deopt = compiler->AddDeoptStub(deopt_id(), 5926 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi,
5944 ICData::kDeoptCheckSmi,
5945 licm_hoisted_ ? ICData::kHoisted : 0); 5927 licm_hoisted_ ? ICData::kHoisted : 0);
5946 __ BranchIfNotSmi(value, deopt); 5928 __ BranchIfNotSmi(value, deopt);
5947 } 5929 }
5948 5930
5949 5931
5950 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, 5932 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
5951 bool opt) const { 5933 bool opt) const {
5952 const intptr_t kNumInputs = 1; 5934 const intptr_t kNumInputs = 1;
5953 const intptr_t kNumTemps = 0; 5935 const intptr_t kNumTemps = 0;
5954 LocationSummary* summary = new(zone) LocationSummary( 5936 LocationSummary* summary = new (zone)
5955 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5937 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5956 summary->set_in(0, Location::RequiresRegister()); 5938 summary->set_in(0, Location::RequiresRegister());
5957 return summary; 5939 return summary;
5958 } 5940 }
5959 5941
5960 5942
5961 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5943 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5962 Register value = locs()->in(0).reg(); 5944 Register value = locs()->in(0).reg();
5963 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); 5945 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass);
5964 __ cmpl(value, Immediate(Smi::RawValue(cid_))); 5946 __ cmpl(value, Immediate(Smi::RawValue(cid_)));
5965 __ j(NOT_ZERO, deopt); 5947 __ j(NOT_ZERO, deopt);
(...skipping 13 matching lines...) Expand all
5979 UNIMPLEMENTED(); 5961 UNIMPLEMENTED();
5980 } 5962 }
5981 5963
5982 5964
5983 // Length: register or constant. 5965 // Length: register or constant.
5984 // Index: register, constant or stack slot. 5966 // Index: register, constant or stack slot.
5985 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, 5967 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone,
5986 bool opt) const { 5968 bool opt) const {
5987 const intptr_t kNumInputs = 2; 5969 const intptr_t kNumInputs = 2;
5988 const intptr_t kNumTemps = 0; 5970 const intptr_t kNumTemps = 0;
5989 LocationSummary* locs = new(zone) LocationSummary( 5971 LocationSummary* locs = new (zone)
5990 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5972 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5991 if (length()->definition()->IsConstant()) { 5973 if (length()->definition()->IsConstant()) {
5992 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); 5974 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length()));
5993 } else { 5975 } else {
5994 locs->set_in(kLengthPos, Location::PrefersRegister()); 5976 locs->set_in(kLengthPos, Location::PrefersRegister());
5995 } 5977 }
5996 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); 5978 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index()));
5997 return locs; 5979 return locs;
5998 } 5980 }
5999 5981
6000 5982
6001 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5983 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6002 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; 5984 uint32_t flags = generalized_ ? ICData::kGeneralized : 0;
6003 flags |= licm_hoisted_ ? ICData::kHoisted : 0; 5985 flags |= licm_hoisted_ ? ICData::kHoisted : 0;
6004 Label* deopt = compiler->AddDeoptStub( 5986 Label* deopt =
6005 deopt_id(), 5987 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags);
6006 ICData::kDeoptCheckArrayBound,
6007 flags);
6008 5988
6009 Location length_loc = locs()->in(kLengthPos); 5989 Location length_loc = locs()->in(kLengthPos);
6010 Location index_loc = locs()->in(kIndexPos); 5990 Location index_loc = locs()->in(kIndexPos);
6011 5991
6012 if (length_loc.IsConstant() && index_loc.IsConstant()) { 5992 if (length_loc.IsConstant() && index_loc.IsConstant()) {
6013 ASSERT((Smi::Cast(length_loc.constant()).Value() <= 5993 ASSERT((Smi::Cast(length_loc.constant()).Value() <=
6014 Smi::Cast(index_loc.constant()).Value()) || 5994 Smi::Cast(index_loc.constant()).Value()) ||
6015 (Smi::Cast(index_loc.constant()).Value() < 0)); 5995 (Smi::Cast(index_loc.constant()).Value() < 0));
6016 // Unconditionally deoptimize for constant bounds checks because they 5996 // Unconditionally deoptimize for constant bounds checks because they
6017 // only occur only when index is out-of-bounds. 5997 // only occur only when index is out-of-bounds.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
6067 bool opt) const { 6047 bool opt) const {
6068 const intptr_t kNumInputs = 2; 6048 const intptr_t kNumInputs = 2;
6069 switch (op_kind()) { 6049 switch (op_kind()) {
6070 case Token::kBIT_AND: 6050 case Token::kBIT_AND:
6071 case Token::kBIT_OR: 6051 case Token::kBIT_OR:
6072 case Token::kBIT_XOR: 6052 case Token::kBIT_XOR:
6073 case Token::kADD: 6053 case Token::kADD:
6074 case Token::kSUB: 6054 case Token::kSUB:
6075 case Token::kMUL: { 6055 case Token::kMUL: {
6076 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; 6056 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0;
6077 LocationSummary* summary = new(zone) LocationSummary( 6057 LocationSummary* summary = new (zone) LocationSummary(
6078 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6058 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6079 summary->set_in(0, (op_kind() == Token::kMUL) 6059 summary->set_in(0, (op_kind() == Token::kMUL)
6080 ? Location::Pair(Location::RegisterLocation(EAX), 6060 ? Location::Pair(Location::RegisterLocation(EAX),
6081 Location::RegisterLocation(EDX)) 6061 Location::RegisterLocation(EDX))
6082 : Location::Pair(Location::RequiresRegister(), 6062 : Location::Pair(Location::RequiresRegister(),
6083 Location::RequiresRegister())); 6063 Location::RequiresRegister()));
6084 summary->set_in(1, Location::Pair(Location::RequiresRegister(), 6064 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
6085 Location::RequiresRegister())); 6065 Location::RequiresRegister()));
6086 summary->set_out(0, Location::SameAsFirstInput()); 6066 summary->set_out(0, Location::SameAsFirstInput());
6087 if (kNumTemps > 0) { 6067 if (kNumTemps > 0) {
6088 summary->set_temp(0, Location::RequiresRegister()); 6068 summary->set_temp(0, Location::RequiresRegister());
6089 } 6069 }
6090 return summary; 6070 return summary;
6091 } 6071 }
6092 default: 6072 default:
6093 UNREACHABLE(); 6073 UNREACHABLE();
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
6164 UNREACHABLE(); 6144 UNREACHABLE();
6165 } 6145 }
6166 } 6146 }
6167 6147
6168 6148
6169 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, 6149 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone,
6170 bool opt) const { 6150 bool opt) const {
6171 const intptr_t kNumInputs = 2; 6151 const intptr_t kNumInputs = 2;
6172 const intptr_t kNumTemps = 6152 const intptr_t kNumTemps =
6173 (op_kind() == Token::kSHL) && CanDeoptimize() ? 2 : 0; 6153 (op_kind() == Token::kSHL) && CanDeoptimize() ? 2 : 0;
6174 LocationSummary* summary = new(zone) LocationSummary( 6154 LocationSummary* summary = new (zone)
6175 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6155 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6176 summary->set_in(0, Location::Pair(Location::RequiresRegister(), 6156 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
6177 Location::RequiresRegister())); 6157 Location::RequiresRegister()));
6178 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); 6158 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
6179 if ((op_kind() == Token::kSHL) && CanDeoptimize()) { 6159 if ((op_kind() == Token::kSHL) && CanDeoptimize()) {
6180 summary->set_temp(0, Location::RequiresRegister()); 6160 summary->set_temp(0, Location::RequiresRegister());
6181 summary->set_temp(1, Location::RequiresRegister()); 6161 summary->set_temp(1, Location::RequiresRegister());
6182 } 6162 }
6183 summary->set_out(0, Location::SameAsFirstInput()); 6163 summary->set_out(0, Location::SameAsFirstInput());
6184 return summary; 6164 return summary;
6185 } 6165 }
6186 6166
6187 6167
6188 static const intptr_t kMintShiftCountLimit = 63; 6168 static const intptr_t kMintShiftCountLimit = 63;
6189 6169
6190 bool ShiftMintOpInstr::has_shift_count_check() const { 6170 bool ShiftMintOpInstr::has_shift_count_check() const {
6191 return !RangeUtils::IsWithin( 6171 return !RangeUtils::IsWithin(right()->definition()->range(), 0,
6192 right()->definition()->range(), 0, kMintShiftCountLimit); 6172 kMintShiftCountLimit);
6193 } 6173 }
6194 6174
6195 6175
6196 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6176 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6197 PairLocation* left_pair = locs()->in(0).AsPairLocation(); 6177 PairLocation* left_pair = locs()->in(0).AsPairLocation();
6198 Register left_lo = left_pair->At(0).reg(); 6178 Register left_lo = left_pair->At(0).reg();
6199 Register left_hi = left_pair->At(1).reg(); 6179 Register left_hi = left_pair->At(1).reg();
6200 PairLocation* out_pair = locs()->out(0).AsPairLocation(); 6180 PairLocation* out_pair = locs()->out(0).AsPairLocation();
6201 Register out_lo = out_pair->At(0).reg(); 6181 Register out_lo = out_pair->At(0).reg();
6202 Register out_hi = out_pair->At(1).reg(); 6182 Register out_hi = out_pair->At(1).reg();
6203 ASSERT(out_lo == left_lo); 6183 ASSERT(out_lo == left_lo);
6204 ASSERT(out_hi == left_hi); 6184 ASSERT(out_hi == left_hi);
6205 6185
6206 Label* deopt = NULL; 6186 Label* deopt = NULL;
6207 if (CanDeoptimize()) { 6187 if (CanDeoptimize()) {
6208 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 6188 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
6209 } 6189 }
6210 if (locs()->in(1).IsConstant()) { 6190 if (locs()->in(1).IsConstant()) {
6211 // Code for a constant shift amount. 6191 // Code for a constant shift amount.
6212 ASSERT(locs()->in(1).constant().IsSmi()); 6192 ASSERT(locs()->in(1).constant().IsSmi());
6213 const int32_t shift = 6193 const int32_t shift =
6214 reinterpret_cast<int32_t>(locs()->in(1).constant().raw()) >> 1; 6194 reinterpret_cast<int32_t>(locs()->in(1).constant().raw()) >> 1;
6215 switch (op_kind()) { 6195 switch (op_kind()) {
6216 case Token::kSHR: { 6196 case Token::kSHR: {
6217 if (shift > 31) { 6197 if (shift > 31) {
6218 __ movl(left_lo, left_hi); // Shift by 32. 6198 __ movl(left_lo, left_hi); // Shift by 32.
6219 __ sarl(left_hi, Immediate(31)); // Sign extend left hi. 6199 __ sarl(left_hi, Immediate(31)); // Sign extend left hi.
6220 if (shift > 32) { 6200 if (shift > 32) {
6221 __ sarl(left_lo, Immediate(shift > 63 ? 31 : shift - 32)); 6201 __ sarl(left_lo, Immediate(shift > 63 ? 31 : shift - 32));
6222 } 6202 }
6223 } else { 6203 } else {
6224 __ shrdl(left_lo, left_hi, Immediate(shift)); 6204 __ shrdl(left_lo, left_hi, Immediate(shift));
6225 __ sarl(left_hi, Immediate(shift)); 6205 __ sarl(left_hi, Immediate(shift));
6226 } 6206 }
6227 break; 6207 break;
6228 } 6208 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
6289 __ cmpl(ECX, Immediate(kMintShiftCountLimit)); 6269 __ cmpl(ECX, Immediate(kMintShiftCountLimit));
6290 __ j(ABOVE, deopt); 6270 __ j(ABOVE, deopt);
6291 } 6271 }
6292 Label done, large_shift; 6272 Label done, large_shift;
6293 switch (op_kind()) { 6273 switch (op_kind()) {
6294 case Token::kSHR: { 6274 case Token::kSHR: {
6295 __ cmpl(ECX, Immediate(31)); 6275 __ cmpl(ECX, Immediate(31));
6296 __ j(ABOVE, &large_shift); 6276 __ j(ABOVE, &large_shift);
6297 6277
6298 __ shrdl(left_lo, left_hi, ECX); // Shift count in CL. 6278 __ shrdl(left_lo, left_hi, ECX); // Shift count in CL.
6299 __ sarl(left_hi, ECX); // Shift count in CL. 6279 __ sarl(left_hi, ECX); // Shift count in CL.
6300 __ jmp(&done, Assembler::kNearJump); 6280 __ jmp(&done, Assembler::kNearJump);
6301 6281
6302 __ Bind(&large_shift); 6282 __ Bind(&large_shift);
6303 // No need to subtract 32 from CL, only 5 bits used by sarl. 6283 // No need to subtract 32 from CL, only 5 bits used by sarl.
6304 __ movl(left_lo, left_hi); // Shift by 32. 6284 __ movl(left_lo, left_hi); // Shift by 32.
6305 __ sarl(left_hi, Immediate(31)); // Sign extend left hi. 6285 __ sarl(left_hi, Immediate(31)); // Sign extend left hi.
6306 __ sarl(left_lo, ECX); // Shift count: CL % 32. 6286 __ sarl(left_lo, ECX); // Shift count: CL % 32.
6307 break; 6287 break;
6308 } 6288 }
6309 case Token::kSHL: { 6289 case Token::kSHL: {
6310 if (can_overflow()) { 6290 if (can_overflow()) {
6311 Register temp1 = locs()->temp(0).reg(); 6291 Register temp1 = locs()->temp(0).reg();
6312 Register temp2 = locs()->temp(1).reg(); 6292 Register temp2 = locs()->temp(1).reg();
6313 __ movl(temp1, left_hi); // Preserve high 32 bits. 6293 __ movl(temp1, left_hi); // Preserve high 32 bits.
6314 __ cmpl(ECX, Immediate(31)); 6294 __ cmpl(ECX, Immediate(31));
6315 __ j(ABOVE, &large_shift); 6295 __ j(ABOVE, &large_shift);
6316 6296
6317 __ shldl(left_hi, left_lo, ECX); // Shift count in CL. 6297 __ shldl(left_hi, left_lo, ECX); // Shift count in CL.
6318 __ shll(left_lo, ECX); // Shift count in CL. 6298 __ shll(left_lo, ECX); // Shift count in CL.
6319 // Check for overflow by shifting back the high 32 bits 6299 // Check for overflow by shifting back the high 32 bits
6320 // and comparing with the input. 6300 // and comparing with the input.
6321 __ movl(temp2, left_hi); 6301 __ movl(temp2, left_hi);
6322 __ sarl(temp2, ECX); 6302 __ sarl(temp2, ECX);
6323 __ cmpl(temp1, temp2); 6303 __ cmpl(temp1, temp2);
6324 __ j(NOT_EQUAL, deopt); 6304 __ j(NOT_EQUAL, deopt);
6325 __ jmp(&done, Assembler::kNearJump); 6305 __ jmp(&done, Assembler::kNearJump);
6326 6306
6327 __ Bind(&large_shift); 6307 __ Bind(&large_shift);
6328 // No need to subtract 32 from CL, only 5 bits used by shll. 6308 // No need to subtract 32 from CL, only 5 bits used by shll.
6329 __ movl(left_hi, left_lo); // Shift by 32. 6309 __ movl(left_hi, left_lo); // Shift by 32.
6330 __ shll(left_hi, ECX); // Shift count: CL % 32. 6310 __ shll(left_hi, ECX); // Shift count: CL % 32.
6331 // Check for overflow by sign extending the high 32 bits 6311 // Check for overflow by sign extending the high 32 bits
6332 // and comparing with the input. 6312 // and comparing with the input.
6333 __ movl(temp2, left_hi); 6313 __ movl(temp2, left_hi);
6334 __ sarl(temp2, Immediate(31)); 6314 __ sarl(temp2, Immediate(31));
6335 __ cmpl(temp1, temp2); 6315 __ cmpl(temp1, temp2);
6336 __ j(NOT_EQUAL, deopt); 6316 __ j(NOT_EQUAL, deopt);
6337 // Also compare low word from input with high word from 6317 // Also compare low word from input with high word from
6338 // output shifted back shift - 32. 6318 // output shifted back shift - 32.
6339 __ movl(temp2, left_hi); 6319 __ movl(temp2, left_hi);
6340 __ sarl(temp2, ECX); // Shift count: CL % 32. 6320 __ sarl(temp2, ECX); // Shift count: CL % 32.
6341 __ cmpl(left_lo, temp2); 6321 __ cmpl(left_lo, temp2);
6342 __ j(NOT_EQUAL, deopt); 6322 __ j(NOT_EQUAL, deopt);
6343 __ xorl(left_lo, left_lo); // Zero left_lo. 6323 __ xorl(left_lo, left_lo); // Zero left_lo.
6344 } else { 6324 } else {
6345 __ cmpl(ECX, Immediate(31)); 6325 __ cmpl(ECX, Immediate(31));
6346 __ j(ABOVE, &large_shift); 6326 __ j(ABOVE, &large_shift);
6347 6327
6348 __ shldl(left_hi, left_lo, ECX); // Shift count in CL. 6328 __ shldl(left_hi, left_lo, ECX); // Shift count in CL.
6349 __ shll(left_lo, ECX); // Shift count in CL. 6329 __ shll(left_lo, ECX); // Shift count in CL.
6350 __ jmp(&done, Assembler::kNearJump); 6330 __ jmp(&done, Assembler::kNearJump);
6351 6331
6352 __ Bind(&large_shift); 6332 __ Bind(&large_shift);
6353 // No need to subtract 32 from CL, only 5 bits used by shll. 6333 // No need to subtract 32 from CL, only 5 bits used by shll.
6354 __ movl(left_hi, left_lo); // Shift by 32. 6334 __ movl(left_hi, left_lo); // Shift by 32.
6355 __ xorl(left_lo, left_lo); // Zero left_lo. 6335 __ xorl(left_lo, left_lo); // Zero left_lo.
6356 __ shll(left_hi, ECX); // Shift count: CL % 32. 6336 __ shll(left_hi, ECX); // Shift count: CL % 32.
6357 } 6337 }
6358 break; 6338 break;
6359 } 6339 }
6360 default: 6340 default:
6361 UNREACHABLE(); 6341 UNREACHABLE();
6362 } 6342 }
6363 __ Bind(&done); 6343 __ Bind(&done);
6364 } 6344 }
6365 } 6345 }
6366 6346
6367 6347
6368 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, 6348 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone,
6369 bool opt) const { 6349 bool opt) const {
6370 const intptr_t kNumInputs = 1; 6350 const intptr_t kNumInputs = 1;
6371 const intptr_t kNumTemps = 0; 6351 const intptr_t kNumTemps = 0;
6372 LocationSummary* summary = new(zone) LocationSummary( 6352 LocationSummary* summary = new (zone)
6373 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6353 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6374 summary->set_in(0, Location::Pair(Location::RequiresRegister(), 6354 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
6375 Location::RequiresRegister())); 6355 Location::RequiresRegister()));
6376 summary->set_out(0, Location::SameAsFirstInput()); 6356 summary->set_out(0, Location::SameAsFirstInput());
6377 return summary; 6357 return summary;
6378 } 6358 }
6379 6359
6380 6360
6381 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6361 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6382 ASSERT(op_kind() == Token::kBIT_NOT); 6362 ASSERT(op_kind() == Token::kBIT_NOT);
6383 PairLocation* left_pair = locs()->in(0).AsPairLocation(); 6363 PairLocation* left_pair = locs()->in(0).AsPairLocation();
(...skipping 21 matching lines...) Expand all
6405 6385
6406 CompileType UnaryUint32OpInstr::ComputeType() const { 6386 CompileType UnaryUint32OpInstr::ComputeType() const {
6407 return CompileType::Int(); 6387 return CompileType::Int();
6408 } 6388 }
6409 6389
6410 6390
6411 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, 6391 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone,
6412 bool opt) const { 6392 bool opt) const {
6413 const intptr_t kNumInputs = 2; 6393 const intptr_t kNumInputs = 2;
6414 const intptr_t kNumTemps = 0; 6394 const intptr_t kNumTemps = 0;
6415 LocationSummary* summary = new(zone) LocationSummary( 6395 LocationSummary* summary = new (zone)
6416 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6396 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6417 summary->set_in(0, Location::RequiresRegister()); 6397 summary->set_in(0, Location::RequiresRegister());
6418 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); 6398 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
6419 summary->set_out(0, Location::SameAsFirstInput()); 6399 summary->set_out(0, Location::SameAsFirstInput());
6420 return summary; 6400 return summary;
6421 } 6401 }
6422 6402
6423 6403
6424 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6404 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6425 const intptr_t kShifterLimit = 31; 6405 const intptr_t kShifterLimit = 31;
6426 6406
6427 Register left = locs()->in(0).reg(); 6407 Register left = locs()->in(0).reg();
6428 Register out = locs()->out(0).reg(); 6408 Register out = locs()->out(0).reg();
6429 ASSERT(left == out); 6409 ASSERT(left == out);
6430 6410
6431 6411
6432 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 6412 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
6433 6413
6434 if (locs()->in(1).IsConstant()) { 6414 if (locs()->in(1).IsConstant()) {
6435 // Shifter is constant. 6415 // Shifter is constant.
6436 6416
6437 const Object& constant = locs()->in(1).constant(); 6417 const Object& constant = locs()->in(1).constant();
6438 ASSERT(constant.IsSmi()); 6418 ASSERT(constant.IsSmi());
6439 const intptr_t shift_value = Smi::Cast(constant).Value(); 6419 const intptr_t shift_value = Smi::Cast(constant).Value();
6440 6420
6441 6421
6442 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). 6422 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit).
6443 switch (op_kind()) { 6423 switch (op_kind()) {
6444 case Token::kSHR: 6424 case Token::kSHR:
6445 __ shrl(left, Immediate(shift_value)); 6425 __ shrl(left, Immediate(shift_value));
6446 break; 6426 break;
6447 case Token::kSHL: 6427 case Token::kSHL:
6448 __ shll(left, Immediate(shift_value)); 6428 __ shll(left, Immediate(shift_value));
6449 break; 6429 break;
6450 default: 6430 default:
6451 UNREACHABLE(); 6431 UNREACHABLE();
6452 } 6432 }
6453 return; 6433 return;
6454 } 6434 }
6455 6435
6456 // Non constant shift value. 6436 // Non constant shift value.
6457 6437
6458 Register shifter = locs()->in(1).reg(); 6438 Register shifter = locs()->in(1).reg();
6459 ASSERT(shifter == ECX); 6439 ASSERT(shifter == ECX);
6460 6440
6461 Label done; 6441 Label done;
6462 Label zero; 6442 Label zero;
6463 6443
6464 // TODO(johnmccutchan): Use range information to avoid these checks. 6444 // TODO(johnmccutchan): Use range information to avoid these checks.
6465 __ SmiUntag(shifter); 6445 __ SmiUntag(shifter);
6466 __ cmpl(shifter, Immediate(0)); 6446 __ cmpl(shifter, Immediate(0));
6467 // If shift value is < 0, deoptimize. 6447 // If shift value is < 0, deoptimize.
6468 __ j(NEGATIVE, deopt); 6448 __ j(NEGATIVE, deopt);
6469 __ cmpl(shifter, Immediate(kShifterLimit)); 6449 __ cmpl(shifter, Immediate(kShifterLimit));
6470 // If shift value is >= 32, return zero. 6450 // If shift value is >= 32, return zero.
6471 __ j(ABOVE, &zero); 6451 __ j(ABOVE, &zero);
6472 6452
6473 // Do the shift. 6453 // Do the shift.
6474 switch (op_kind()) { 6454 switch (op_kind()) {
6475 case Token::kSHR: 6455 case Token::kSHR:
6476 __ shrl(left, shifter); 6456 __ shrl(left, shifter);
6477 __ jmp(&done); 6457 __ jmp(&done);
6478 break; 6458 break;
6479 case Token::kSHL: 6459 case Token::kSHL:
6480 __ shll(left, shifter); 6460 __ shll(left, shifter);
6481 __ jmp(&done); 6461 __ jmp(&done);
6482 break; 6462 break;
6483 default: 6463 default:
6484 UNREACHABLE(); 6464 UNREACHABLE();
6485 } 6465 }
6486 6466
6487 __ Bind(&zero); 6467 __ Bind(&zero);
6488 // Shift was greater than 31 bits, just return zero. 6468 // Shift was greater than 31 bits, just return zero.
6489 __ xorl(left, left); 6469 __ xorl(left, left);
6490 6470
6491 // Exit path. 6471 // Exit path.
6492 __ Bind(&done); 6472 __ Bind(&done);
6493 } 6473 }
6494 6474
6495 6475
6496 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, 6476 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone,
6497 bool opt) const { 6477 bool opt) const {
6498 const intptr_t kNumInputs = 1; 6478 const intptr_t kNumInputs = 1;
6499 const intptr_t kNumTemps = 0; 6479 const intptr_t kNumTemps = 0;
6500 LocationSummary* summary = new(zone) LocationSummary( 6480 LocationSummary* summary = new (zone)
6501 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6481 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6502 summary->set_in(0, Location::RequiresRegister()); 6482 summary->set_in(0, Location::RequiresRegister());
6503 summary->set_out(0, Location::SameAsFirstInput()); 6483 summary->set_out(0, Location::SameAsFirstInput());
6504 return summary; 6484 return summary;
6505 } 6485 }
6506 6486
6507 6487
6508 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6488 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6509 Register out = locs()->out(0).reg(); 6489 Register out = locs()->out(0).reg();
6510 ASSERT(locs()->in(0).reg() == out); 6490 ASSERT(locs()->in(0).reg() == out);
6511 6491
6512 ASSERT(op_kind() == Token::kBIT_NOT); 6492 ASSERT(op_kind() == Token::kBIT_NOT);
6513 6493
6514 __ notl(out); 6494 __ notl(out);
6515 } 6495 }
6516 6496
6517 6497
6518 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, 6498 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone,
6519 bool opt) const { 6499 bool opt) const {
6520 const intptr_t kNumInputs = 1; 6500 const intptr_t kNumInputs = 1;
6521 const intptr_t kNumTemps = 0; 6501 const intptr_t kNumTemps = 0;
6522 LocationSummary* summary = new(zone) LocationSummary( 6502 LocationSummary* summary = new (zone)
6523 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6503 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6524 if ((from() == kUnboxedInt32 || from() == kUnboxedUint32) && 6504 if ((from() == kUnboxedInt32 || from() == kUnboxedUint32) &&
6525 (to() == kUnboxedInt32 || to() == kUnboxedUint32)) { 6505 (to() == kUnboxedInt32 || to() == kUnboxedUint32)) {
6526 summary->set_in(0, Location::RequiresRegister()); 6506 summary->set_in(0, Location::RequiresRegister());
6527 summary->set_out(0, Location::SameAsFirstInput()); 6507 summary->set_out(0, Location::SameAsFirstInput());
6528 } else if (from() == kUnboxedMint) { 6508 } else if (from() == kUnboxedMint) {
6529 summary->set_in(0, Location::Pair( 6509 summary->set_in(
6530 CanDeoptimize() ? Location::WritableRegister() 6510 0, Location::Pair(CanDeoptimize() ? Location::WritableRegister()
6531 : Location::RequiresRegister(), 6511 : Location::RequiresRegister(),
6532 Location::RequiresRegister())); 6512 Location::RequiresRegister()));
6533 summary->set_out(0, Location::RequiresRegister()); 6513 summary->set_out(0, Location::RequiresRegister());
6534 } else if (from() == kUnboxedUint32) { 6514 } else if (from() == kUnboxedUint32) {
6535 summary->set_in(0, Location::RequiresRegister()); 6515 summary->set_in(0, Location::RequiresRegister());
6536 summary->set_out(0, Location::Pair(Location::RequiresRegister(), 6516 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
6537 Location::RequiresRegister())); 6517 Location::RequiresRegister()));
6538 } else if (from() == kUnboxedInt32) { 6518 } else if (from() == kUnboxedInt32) {
6539 summary->set_in(0, Location::RegisterLocation(EAX)); 6519 summary->set_in(0, Location::RegisterLocation(EAX));
6540 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), 6520 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
6541 Location::RegisterLocation(EDX))); 6521 Location::RegisterLocation(EDX)));
6542 } 6522 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
6593 Register out_hi = out_pair->At(1).reg(); 6573 Register out_hi = out_pair->At(1).reg();
6594 ASSERT(locs()->in(0).reg() == EAX); 6574 ASSERT(locs()->in(0).reg() == EAX);
6595 ASSERT(out_lo == EAX && out_hi == EDX); 6575 ASSERT(out_lo == EAX && out_hi == EDX);
6596 __ cdq(); 6576 __ cdq();
6597 } else { 6577 } else {
6598 UNREACHABLE(); 6578 UNREACHABLE();
6599 } 6579 }
6600 } 6580 }
6601 6581
6602 6582
6603 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, 6583 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
6604 bool opt) const { 6584 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall);
6605 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall);
6606 } 6585 }
6607 6586
6608 6587
6609
6610 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6588 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6611 compiler->GenerateRuntimeCall(token_pos(), 6589 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1,
6612 deopt_id(),
6613 kThrowRuntimeEntry,
6614 1,
6615 locs()); 6590 locs());
6616 __ int3(); 6591 __ int3();
6617 } 6592 }
6618 6593
6619 6594
6620 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, 6595 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
6621 bool opt) const { 6596 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall);
6622 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall);
6623 } 6597 }
6624 6598
6625 6599
6626 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6600 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6627 compiler->SetNeedsStacktrace(catch_try_index()); 6601 compiler->SetNeedsStacktrace(catch_try_index());
6628 compiler->GenerateRuntimeCall(token_pos(), 6602 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry,
6629 deopt_id(), 6603 2, locs());
6630 kReThrowRuntimeEntry,
6631 2,
6632 locs());
6633 __ int3(); 6604 __ int3();
6634 } 6605 }
6635 6606
6636 6607
6637 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, 6608 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const {
6638 bool opt) const { 6609 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
6639 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
6640 } 6610 }
6641 6611
6642 6612
6643 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6613 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6644 __ Stop(message()); 6614 __ Stop(message());
6645 } 6615 }
6646 6616
6647 6617
6648 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6618 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6649 if (!compiler->CanFallThroughTo(normal_entry())) { 6619 if (!compiler->CanFallThroughTo(normal_entry())) {
6650 __ jmp(compiler->GetJumpLabel(normal_entry())); 6620 __ jmp(compiler->GetJumpLabel(normal_entry()));
6651 } 6621 }
6652 } 6622 }
6653 6623
6654 6624
6655 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, 6625 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const {
6656 bool opt) const { 6626 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
6657 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
6658 } 6627 }
6659 6628
6660 6629
6661 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6630 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6662 if (!compiler->is_optimizing()) { 6631 if (!compiler->is_optimizing()) {
6663 if (FLAG_reorder_basic_blocks) { 6632 if (FLAG_reorder_basic_blocks) {
6664 compiler->EmitEdgeCounter(block()->preorder_number()); 6633 compiler->EmitEdgeCounter(block()->preorder_number());
6665 } 6634 }
6666 // Add a deoptimization descriptor for deoptimizing instructions that 6635 // Add a deoptimization descriptor for deoptimizing instructions that
6667 // may be inserted before this instruction. 6636 // may be inserted before this instruction.
6668 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, 6637 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(),
6669 GetDeoptId(),
6670 TokenPosition::kNoSource); 6638 TokenPosition::kNoSource);
6671 } 6639 }
6672 if (HasParallelMove()) { 6640 if (HasParallelMove()) {
6673 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); 6641 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
6674 } 6642 }
6675 6643
6676 // We can fall through if the successor is the next block in the list. 6644 // We can fall through if the successor is the next block in the list.
6677 // Otherwise, we need a jump. 6645 // Otherwise, we need a jump.
6678 if (!compiler->CanFallThroughTo(successor())) { 6646 if (!compiler->CanFallThroughTo(successor())) {
6679 __ jmp(compiler->GetJumpLabel(successor())); 6647 __ jmp(compiler->GetJumpLabel(successor()));
6680 } 6648 }
6681 } 6649 }
6682 6650
6683 6651
6684 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, 6652 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone,
6685 bool opt) const { 6653 bool opt) const {
6686 const intptr_t kNumInputs = 1; 6654 const intptr_t kNumInputs = 1;
6687 const intptr_t kNumTemps = 1; 6655 const intptr_t kNumTemps = 1;
6688 6656
6689 LocationSummary* summary = new(zone) LocationSummary( 6657 LocationSummary* summary = new (zone)
6690 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6658 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6691 6659
6692 summary->set_in(0, Location::RequiresRegister()); 6660 summary->set_in(0, Location::RequiresRegister());
6693 summary->set_temp(0, Location::RequiresRegister()); 6661 summary->set_temp(0, Location::RequiresRegister());
6694 6662
6695 return summary; 6663 return summary;
6696 } 6664 }
6697 6665
6698 6666
6699 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6667 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6700 Register target_reg = locs()->temp_slot(0)->reg(); 6668 Register target_reg = locs()->temp_slot(0)->reg();
6701 6669
6702 // Load code object from frame. 6670 // Load code object from frame.
6703 __ movl(target_reg, Address(EBP, kPcMarkerSlotFromFp * kWordSize)); 6671 __ movl(target_reg, Address(EBP, kPcMarkerSlotFromFp * kWordSize));
6704 // Load instructions object (active_instructions and Code::entry_point() may 6672 // Load instructions object (active_instructions and Code::entry_point() may
6705 // not point to this instruction object any more; see Code::DisableDartCode). 6673 // not point to this instruction object any more; see Code::DisableDartCode).
6706 __ movl(target_reg, 6674 __ movl(target_reg,
6707 FieldAddress(target_reg, Code::saved_instructions_offset())); 6675 FieldAddress(target_reg, Code::saved_instructions_offset()));
6708 __ addl(target_reg, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 6676 __ addl(target_reg, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
6709 6677
6710 // Add the offset. 6678 // Add the offset.
6711 Register offset_reg = locs()->in(0).reg(); 6679 Register offset_reg = locs()->in(0).reg();
6712 if (offset()->definition()->representation() == kTagged) { 6680 if (offset()->definition()->representation() == kTagged) {
6713 __ SmiUntag(offset_reg); 6681 __ SmiUntag(offset_reg);
6714 } 6682 }
6715 __ addl(target_reg, offset_reg); 6683 __ addl(target_reg, offset_reg);
6716 6684
6717 // Jump to the absolute address. 6685 // Jump to the absolute address.
6718 __ jmp(target_reg); 6686 __ jmp(target_reg);
6719 } 6687 }
6720 6688
6721 6689
6722 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, 6690 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone,
6723 bool opt) const { 6691 bool opt) const {
6724 const intptr_t kNumInputs = 2; 6692 const intptr_t kNumInputs = 2;
6725 const intptr_t kNumTemps = 0; 6693 const intptr_t kNumTemps = 0;
6726 if (needs_number_check()) { 6694 if (needs_number_check()) {
6727 LocationSummary* locs = new(zone) LocationSummary( 6695 LocationSummary* locs = new (zone)
6728 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 6696 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
6729 locs->set_in(0, Location::RegisterLocation(EAX)); 6697 locs->set_in(0, Location::RegisterLocation(EAX));
6730 locs->set_in(1, Location::RegisterLocation(ECX)); 6698 locs->set_in(1, Location::RegisterLocation(ECX));
6731 locs->set_out(0, Location::RegisterLocation(EAX)); 6699 locs->set_out(0, Location::RegisterLocation(EAX));
6732 return locs; 6700 return locs;
6733 } 6701 }
6734 LocationSummary* locs = new(zone) LocationSummary( 6702 LocationSummary* locs = new (zone)
6735 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6703 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6736 locs->set_in(0, Location::RegisterOrConstant(left())); 6704 locs->set_in(0, Location::RegisterOrConstant(left()));
6737 // Only one of the inputs can be a constant. Choose register if the first one 6705 // Only one of the inputs can be a constant. Choose register if the first one
6738 // is a constant. 6706 // is a constant.
6739 locs->set_in(1, locs->in(0).IsConstant() 6707 locs->set_in(1, locs->in(0).IsConstant()
6740 ? Location::RequiresRegister() 6708 ? Location::RequiresRegister()
6741 : Location::RegisterOrConstant(right())); 6709 : Location::RegisterOrConstant(right()));
6742 locs->set_out(0, Location::RequiresRegister()); 6710 locs->set_out(0, Location::RequiresRegister());
6743 return locs; 6711 return locs;
6744 } 6712 }
6745 6713
6746 6714
6747 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 6715 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
6748 BranchLabels labels) { 6716 BranchLabels labels) {
6749 Location left = locs()->in(0); 6717 Location left = locs()->in(0);
6750 Location right = locs()->in(1); 6718 Location right = locs()->in(1);
6751 ASSERT(!left.IsConstant() || !right.IsConstant()); 6719 ASSERT(!left.IsConstant() || !right.IsConstant());
6752 Condition true_condition; 6720 Condition true_condition;
6753 if (left.IsConstant()) { 6721 if (left.IsConstant()) {
6754 true_condition = compiler->EmitEqualityRegConstCompare(right.reg(), 6722 true_condition = compiler->EmitEqualityRegConstCompare(
6755 left.constant(), 6723 right.reg(), left.constant(), needs_number_check(), token_pos());
6756 needs_number_check(),
6757 token_pos());
6758 } else if (right.IsConstant()) { 6724 } else if (right.IsConstant()) {
6759 true_condition = compiler->EmitEqualityRegConstCompare(left.reg(), 6725 true_condition = compiler->EmitEqualityRegConstCompare(
6760 right.constant(), 6726 left.reg(), right.constant(), needs_number_check(), token_pos());
6761 needs_number_check(),
6762 token_pos());
6763 } else { 6727 } else {
6764 true_condition = compiler->EmitEqualityRegRegCompare(left.reg(), 6728 true_condition = compiler->EmitEqualityRegRegCompare(
6765 right.reg(), 6729 left.reg(), right.reg(), needs_number_check(), token_pos());
6766 needs_number_check(),
6767 token_pos());
6768 } 6730 }
6769 if (kind() != Token::kEQ_STRICT) { 6731 if (kind() != Token::kEQ_STRICT) {
6770 ASSERT(kind() == Token::kNE_STRICT); 6732 ASSERT(kind() == Token::kNE_STRICT);
6771 true_condition = NegateCondition(true_condition); 6733 true_condition = NegateCondition(true_condition);
6772 } 6734 }
6773 return true_condition; 6735 return true_condition;
6774 } 6736 }
6775 6737
6776 6738
6777 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6739 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6778 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); 6740 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
6779 6741
6780 Label is_true, is_false; 6742 Label is_true, is_false;
6781 BranchLabels labels = { &is_true, &is_false, &is_false }; 6743 BranchLabels labels = {&is_true, &is_false, &is_false};
6782 Condition true_condition = EmitComparisonCode(compiler, labels); 6744 Condition true_condition = EmitComparisonCode(compiler, labels);
6783 EmitBranchOnCondition(compiler, true_condition, labels); 6745 EmitBranchOnCondition(compiler, true_condition, labels);
6784 6746
6785 Register result = locs()->out(0).reg(); 6747 Register result = locs()->out(0).reg();
6786 Label done; 6748 Label done;
6787 __ Bind(&is_false); 6749 __ Bind(&is_false);
6788 __ LoadObject(result, Bool::False()); 6750 __ LoadObject(result, Bool::False());
6789 __ jmp(&done, Assembler::kNearJump); 6751 __ jmp(&done, Assembler::kNearJump);
6790 __ Bind(&is_true); 6752 __ Bind(&is_true);
6791 __ LoadObject(result, Bool::True()); 6753 __ LoadObject(result, Bool::True());
(...skipping 28 matching lines...) Expand all
6820 6782
6821 6783
6822 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6784 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6823 ASSERT(locs()->out(0).reg() == EDX); 6785 ASSERT(locs()->out(0).reg() == EDX);
6824 6786
6825 // Clear upper part of the out register. We are going to use setcc on it 6787 // Clear upper part of the out register. We are going to use setcc on it
6826 // which is a byte move. 6788 // which is a byte move.
6827 __ xorl(EDX, EDX); 6789 __ xorl(EDX, EDX);
6828 6790
6829 // Emit comparison code. This must not overwrite the result register. 6791 // Emit comparison code. This must not overwrite the result register.
6830 BranchLabels labels = { NULL, NULL, NULL }; 6792 BranchLabels labels = {NULL, NULL, NULL};
6831 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); 6793 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
6832 6794
6833 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); 6795 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
6834 6796
6835 intptr_t true_value = if_true_; 6797 intptr_t true_value = if_true_;
6836 intptr_t false_value = if_false_; 6798 intptr_t false_value = if_false_;
6837 6799
6838 if (is_power_of_two_kind) { 6800 if (is_power_of_two_kind) {
6839 if (true_value == 0) { 6801 if (true_value == 0) {
6840 // We need to have zero in EDX on true_condition. 6802 // We need to have zero in EDX on true_condition.
(...skipping 11 matching lines...) Expand all
6852 } 6814 }
6853 6815
6854 __ setcc(true_condition, DL); 6816 __ setcc(true_condition, DL);
6855 6817
6856 if (is_power_of_two_kind) { 6818 if (is_power_of_two_kind) {
6857 const intptr_t shift = 6819 const intptr_t shift =
6858 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); 6820 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value));
6859 __ shll(EDX, Immediate(shift + kSmiTagSize)); 6821 __ shll(EDX, Immediate(shift + kSmiTagSize));
6860 } else { 6822 } else {
6861 __ decl(EDX); 6823 __ decl(EDX);
6862 __ andl(EDX, Immediate( 6824 __ andl(EDX,
6863 Smi::RawValue(true_value) - Smi::RawValue(false_value))); 6825 Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value)));
6864 if (false_value != 0) { 6826 if (false_value != 0) {
6865 __ addl(EDX, Immediate(Smi::RawValue(false_value))); 6827 __ addl(EDX, Immediate(Smi::RawValue(false_value)));
6866 } 6828 }
6867 } 6829 }
6868 } 6830 }
6869 6831
6870 6832
6871 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, 6833 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone,
6872 bool opt) const { 6834 bool opt) const {
6873 const intptr_t kNumInputs = 1; 6835 const intptr_t kNumInputs = 1;
6874 const intptr_t kNumTemps = 0; 6836 const intptr_t kNumTemps = 0;
6875 LocationSummary* summary = new(zone) LocationSummary( 6837 LocationSummary* summary = new (zone)
6876 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 6838 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
6877 summary->set_in(0, Location::RegisterLocation(EAX)); // Function. 6839 summary->set_in(0, Location::RegisterLocation(EAX)); // Function.
6878 summary->set_out(0, Location::RegisterLocation(EAX)); 6840 summary->set_out(0, Location::RegisterLocation(EAX));
6879 return summary; 6841 return summary;
6880 } 6842 }
6881 6843
6882 6844
6883 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6845 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6884 // Load arguments descriptors. 6846 // Load arguments descriptors.
6885 intptr_t argument_count = ArgumentCount(); 6847 intptr_t argument_count = ArgumentCount();
6886 const Array& arguments_descriptor = 6848 const Array& arguments_descriptor = Array::ZoneHandle(
6887 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, 6849 ArgumentsDescriptor::New(argument_count, argument_names()));
6888 argument_names()));
6889 __ LoadObject(EDX, arguments_descriptor); 6850 __ LoadObject(EDX, arguments_descriptor);
6890 6851
6891 // EBX: Code (compiled code or lazy compile stub). 6852 // EBX: Code (compiled code or lazy compile stub).
6892 ASSERT(locs()->in(0).reg() == EAX); 6853 ASSERT(locs()->in(0).reg() == EAX);
6893 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); 6854 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset()));
6894 6855
6895 // EAX: Function. 6856 // EAX: Function.
6896 // EDX: Arguments descriptor array. 6857 // EDX: Arguments descriptor array.
6897 // ECX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). 6858 // ECX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
6898 __ xorl(ECX, ECX); 6859 __ xorl(ECX, ECX);
6899 __ call(EBX); 6860 __ call(EBX);
6900 compiler->RecordSafepoint(locs()); 6861 compiler->RecordSafepoint(locs());
6901 // Marks either the continuation point in unoptimized code or the 6862 // Marks either the continuation point in unoptimized code or the
6902 // deoptimization point in optimized code, after call. 6863 // deoptimization point in optimized code, after call.
6903 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); 6864 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id());
6904 if (compiler->is_optimizing()) { 6865 if (compiler->is_optimizing()) {
6905 compiler->AddDeoptIndexAtCall(deopt_id_after); 6866 compiler->AddDeoptIndexAtCall(deopt_id_after);
6906 } 6867 }
6907 // Add deoptimization continuation point after the call and before the 6868 // Add deoptimization continuation point after the call and before the
6908 // arguments are removed. 6869 // arguments are removed.
6909 // In optimized code this descriptor is needed for exception handling. 6870 // In optimized code this descriptor is needed for exception handling.
6910 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, 6871 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after,
6911 deopt_id_after,
6912 token_pos()); 6872 token_pos());
6913 __ Drop(argument_count); 6873 __ Drop(argument_count);
6914 } 6874 }
6915 6875
6916 6876
6917 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, 6877 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone,
6918 bool opt) const { 6878 bool opt) const {
6919 return LocationSummary::Make(zone, 6879 return LocationSummary::Make(zone, 1, Location::RequiresRegister(),
6920 1,
6921 Location::RequiresRegister(),
6922 LocationSummary::kNoCall); 6880 LocationSummary::kNoCall);
6923 } 6881 }
6924 6882
6925 6883
6926 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6884 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6927 Register value = locs()->in(0).reg(); 6885 Register value = locs()->in(0).reg();
6928 Register result = locs()->out(0).reg(); 6886 Register result = locs()->out(0).reg();
6929 6887
6930 Label done; 6888 Label done;
6931 __ LoadObject(result, Bool::True()); 6889 __ LoadObject(result, Bool::True());
6932 __ CompareRegisters(result, value); 6890 __ CompareRegisters(result, value);
6933 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 6891 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
6934 __ LoadObject(result, Bool::False()); 6892 __ LoadObject(result, Bool::False());
6935 __ Bind(&done); 6893 __ Bind(&done);
6936 } 6894 }
6937 6895
6938 6896
6939 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, 6897 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
6940 bool opt) const { 6898 bool opt) const {
6941 return MakeCallSummary(zone); 6899 return MakeCallSummary(zone);
6942 } 6900 }
6943 6901
6944 6902
6945 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6903 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6946 const Code& stub = Code::ZoneHandle( 6904 const Code& stub = Code::ZoneHandle(
6947 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); 6905 compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
6948 const StubEntry stub_entry(stub); 6906 const StubEntry stub_entry(stub);
6949 compiler->GenerateCall(token_pos(), 6907 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther,
6950 stub_entry,
6951 RawPcDescriptors::kOther,
6952 locs()); 6908 locs());
6953 compiler->AddStubCallTarget(stub); 6909 compiler->AddStubCallTarget(stub);
6954 __ Drop(ArgumentCount()); // Discard arguments. 6910 __ Drop(ArgumentCount()); // Discard arguments.
6955 } 6911 }
6956 6912
6957 6913
6958 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6914 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6959 ASSERT(!compiler->is_optimizing()); 6915 ASSERT(!compiler->is_optimizing());
6960 compiler->GenerateCall(token_pos(), 6916 compiler->GenerateCall(token_pos(), *StubCode::DebugStepCheck_entry(),
6961 *StubCode::DebugStepCheck_entry(), 6917 stub_kind_, locs());
6962 stub_kind_,
6963 locs());
6964 } 6918 }
6965 6919
6966 6920
6967 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary( 6921 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary(Zone* zone,
6968 Zone* zone, bool opt) const { 6922 bool opt) const {
6969 const intptr_t kNumInputs = 1; 6923 const intptr_t kNumInputs = 1;
6970 const intptr_t kNumTemps = 0; 6924 const intptr_t kNumTemps = 0;
6971 LocationSummary* locs = new(zone) LocationSummary( 6925 LocationSummary* locs = new (zone)
6972 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 6926 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
6973 locs->set_in(0, Location::RegisterLocation(EAX)); 6927 locs->set_in(0, Location::RegisterLocation(EAX));
6974 locs->set_out(0, Location::RegisterLocation(EAX)); 6928 locs->set_out(0, Location::RegisterLocation(EAX));
6975 return locs; 6929 return locs;
6976 } 6930 }
6977 6931
6978 6932
6979 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6933 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6980 const Register typed_data = locs()->in(0).reg(); 6934 const Register typed_data = locs()->in(0).reg();
6981 const Register result = locs()->out(0).reg(); 6935 const Register result = locs()->out(0).reg();
6982 __ PushObject(Object::null_object()); 6936 __ PushObject(Object::null_object());
6983 __ pushl(typed_data); 6937 __ pushl(typed_data);
6984 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, 6938 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(),
6985 deopt_id(), 6939 kGrowRegExpStackRuntimeEntry, 1, locs());
6986 kGrowRegExpStackRuntimeEntry,
6987 1,
6988 locs());
6989 __ Drop(1); 6940 __ Drop(1);
6990 __ popl(result); 6941 __ popl(result);
6991 } 6942 }
6992 6943
6993 6944
6994 } // namespace dart 6945 } // namespace dart
6995 6946
6996 #undef __ 6947 #undef __
6997 6948
6998 #endif // defined TARGET_ARCH_IA32 6949 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_dbc.cc ('k') | runtime/vm/intermediate_language_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698