OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
3673 __ j(ABOVE_EQUAL, ¬_smi); | 3610 __ j(ABOVE_EQUAL, ¬_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(¬_smi); | 3616 __ Bind(¬_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |