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