OLD | NEW |
1 | 1 |
2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 6 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
7 #if defined(TARGET_ARCH_ARM) | 7 #if defined(TARGET_ARCH_ARM) |
8 | 8 |
9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
10 | 10 |
(...skipping 13 matching lines...) Expand all Loading... |
24 #include "vm/symbols.h" | 24 #include "vm/symbols.h" |
25 | 25 |
26 #define __ compiler->assembler()-> | 26 #define __ compiler->assembler()-> |
27 #define Z (compiler->zone()) | 27 #define Z (compiler->zone()) |
28 | 28 |
29 namespace dart { | 29 namespace dart { |
30 | 30 |
31 // Generic summary for call instructions that have all arguments pushed | 31 // Generic summary for call instructions that have all arguments pushed |
32 // on the stack and return the result in a fixed register R0. | 32 // on the stack and return the result in a fixed register R0. |
33 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { | 33 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { |
34 LocationSummary* result = new(zone) LocationSummary( | 34 LocationSummary* result = |
35 zone, 0, 0, LocationSummary::kCall); | 35 new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
36 result->set_out(0, Location::RegisterLocation(R0)); | 36 result->set_out(0, Location::RegisterLocation(R0)); |
37 return result; | 37 return result; |
38 } | 38 } |
39 | 39 |
40 | 40 |
41 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, | 41 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, |
42 bool opt) const { | 42 bool opt) const { |
43 const intptr_t kNumInputs = 1; | 43 const intptr_t kNumInputs = 1; |
44 const intptr_t kNumTemps = 0; | 44 const intptr_t kNumTemps = 0; |
45 LocationSummary* locs = new(zone) LocationSummary( | 45 LocationSummary* locs = new (zone) |
46 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 46 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
47 locs->set_in(0, Location::AnyOrConstant(value())); | 47 locs->set_in(0, Location::AnyOrConstant(value())); |
48 return locs; | 48 return locs; |
49 } | 49 } |
50 | 50 |
51 | 51 |
52 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 52 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
53 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 53 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
54 // where PushArgument is handled by BindInstr::EmitNativeCode. | 54 // where PushArgument is handled by BindInstr::EmitNativeCode. |
55 if (compiler->is_optimizing()) { | 55 if (compiler->is_optimizing()) { |
56 Location value = locs()->in(0); | 56 Location value = locs()->in(0); |
57 if (value.IsRegister()) { | 57 if (value.IsRegister()) { |
58 __ Push(value.reg()); | 58 __ Push(value.reg()); |
59 } else if (value.IsConstant()) { | 59 } else if (value.IsConstant()) { |
60 __ PushObject(value.constant()); | 60 __ PushObject(value.constant()); |
61 } else { | 61 } else { |
62 ASSERT(value.IsStackSlot()); | 62 ASSERT(value.IsStackSlot()); |
63 const intptr_t value_offset = value.ToStackSlotOffset(); | 63 const intptr_t value_offset = value.ToStackSlotOffset(); |
64 __ LoadFromOffset(kWord, IP, value.base_reg(), value_offset); | 64 __ LoadFromOffset(kWord, IP, value.base_reg(), value_offset); |
65 __ Push(IP); | 65 __ Push(IP); |
66 } | 66 } |
67 } | 67 } |
68 } | 68 } |
69 | 69 |
70 | 70 |
71 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, | 71 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
72 bool opt) const { | |
73 const intptr_t kNumInputs = 1; | 72 const intptr_t kNumInputs = 1; |
74 const intptr_t kNumTemps = 0; | 73 const intptr_t kNumTemps = 0; |
75 LocationSummary* locs = new(zone) LocationSummary( | 74 LocationSummary* locs = new (zone) |
76 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 75 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
77 locs->set_in(0, Location::RegisterLocation(R0)); | 76 locs->set_in(0, Location::RegisterLocation(R0)); |
78 return locs; | 77 return locs; |
79 } | 78 } |
80 | 79 |
81 | 80 |
82 // Attempt optimized compilation at return instruction instead of at the entry. | 81 // Attempt optimized compilation at return instruction instead of at the entry. |
83 // The entry needs to be patchable, no inlined objects are allowed in the area | 82 // The entry needs to be patchable, no inlined objects are allowed in the area |
84 // that will be overwritten by the patch instructions: a branch macro sequence. | 83 // that will be overwritten by the patch instructions: a branch macro sequence. |
85 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 84 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
86 const Register result = locs()->in(0).reg(); | 85 const Register result = locs()->in(0).reg(); |
(...skipping 21 matching lines...) Expand all Loading... |
108 __ LeaveDartFrame(); // Disallows constant pool use. | 107 __ LeaveDartFrame(); // Disallows constant pool use. |
109 __ Ret(); | 108 __ Ret(); |
110 // This ReturnInstr may be emitted out of order by the optimizer. The next | 109 // This ReturnInstr may be emitted out of order by the optimizer. The next |
111 // block may be a target expecting a properly set constant pool pointer. | 110 // block may be a target expecting a properly set constant pool pointer. |
112 __ set_constant_pool_allowed(true); | 111 __ set_constant_pool_allowed(true); |
113 } | 112 } |
114 | 113 |
115 | 114 |
116 static Condition NegateCondition(Condition condition) { | 115 static Condition NegateCondition(Condition condition) { |
117 switch (condition) { | 116 switch (condition) { |
118 case EQ: return NE; | 117 case EQ: |
119 case NE: return EQ; | 118 return NE; |
120 case LT: return GE; | 119 case NE: |
121 case LE: return GT; | 120 return EQ; |
122 case GT: return LE; | 121 case LT: |
123 case GE: return LT; | 122 return GE; |
124 case CC: return CS; | 123 case LE: |
125 case LS: return HI; | 124 return GT; |
126 case HI: return LS; | 125 case GT: |
127 case CS: return CC; | 126 return LE; |
128 case VC: return VS; | 127 case GE: |
129 case VS: return VC; | 128 return LT; |
| 129 case CC: |
| 130 return CS; |
| 131 case LS: |
| 132 return HI; |
| 133 case HI: |
| 134 return LS; |
| 135 case CS: |
| 136 return CC; |
| 137 case VC: |
| 138 return VS; |
| 139 case VS: |
| 140 return VC; |
130 default: | 141 default: |
131 UNREACHABLE(); | 142 UNREACHABLE(); |
132 return EQ; | 143 return EQ; |
133 } | 144 } |
134 } | 145 } |
135 | 146 |
136 | 147 |
137 // Detect pattern when one value is zero and another is a power of 2. | 148 // Detect pattern when one value is zero and another is a power of 2. |
138 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 149 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
139 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 150 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
(...skipping 12 matching lines...) Expand all Loading... |
152 const Register result = locs()->out(0).reg(); | 163 const Register result = locs()->out(0).reg(); |
153 | 164 |
154 Location left = locs()->in(0); | 165 Location left = locs()->in(0); |
155 Location right = locs()->in(1); | 166 Location right = locs()->in(1); |
156 ASSERT(!left.IsConstant() || !right.IsConstant()); | 167 ASSERT(!left.IsConstant() || !right.IsConstant()); |
157 | 168 |
158 // Clear out register. | 169 // Clear out register. |
159 __ eor(result, result, Operand(result)); | 170 __ eor(result, result, Operand(result)); |
160 | 171 |
161 // Emit comparison code. This must not overwrite the result register. | 172 // Emit comparison code. This must not overwrite the result register. |
162 BranchLabels labels = { NULL, NULL, NULL }; | 173 BranchLabels labels = {NULL, NULL, NULL}; |
163 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 174 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
164 | 175 |
165 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 176 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
166 | 177 |
167 intptr_t true_value = if_true_; | 178 intptr_t true_value = if_true_; |
168 intptr_t false_value = if_false_; | 179 intptr_t false_value = if_false_; |
169 | 180 |
170 if (is_power_of_two_kind) { | 181 if (is_power_of_two_kind) { |
171 if (true_value == 0) { | 182 if (true_value == 0) { |
172 // We need to have zero in result on true_condition. | 183 // We need to have zero in result on true_condition. |
(...skipping 11 matching lines...) Expand all Loading... |
184 } | 195 } |
185 | 196 |
186 __ mov(result, Operand(1), true_condition); | 197 __ mov(result, Operand(1), true_condition); |
187 | 198 |
188 if (is_power_of_two_kind) { | 199 if (is_power_of_two_kind) { |
189 const intptr_t shift = | 200 const intptr_t shift = |
190 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); | 201 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
191 __ Lsl(result, result, Operand(shift + kSmiTagSize)); | 202 __ Lsl(result, result, Operand(shift + kSmiTagSize)); |
192 } else { | 203 } else { |
193 __ sub(result, result, Operand(1)); | 204 __ sub(result, result, Operand(1)); |
194 const int32_t val = | 205 const int32_t val = Smi::RawValue(true_value) - Smi::RawValue(false_value); |
195 Smi::RawValue(true_value) - Smi::RawValue(false_value); | |
196 __ AndImmediate(result, result, val); | 206 __ AndImmediate(result, result, val); |
197 if (false_value != 0) { | 207 if (false_value != 0) { |
198 __ AddImmediate(result, Smi::RawValue(false_value)); | 208 __ AddImmediate(result, Smi::RawValue(false_value)); |
199 } | 209 } |
200 } | 210 } |
201 } | 211 } |
202 | 212 |
203 | 213 |
204 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 214 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |
205 bool opt) const { | 215 bool opt) const { |
206 const intptr_t kNumInputs = 1; | 216 const intptr_t kNumInputs = 1; |
207 const intptr_t kNumTemps = 0; | 217 const intptr_t kNumTemps = 0; |
208 LocationSummary* summary = new(zone) LocationSummary( | 218 LocationSummary* summary = new (zone) |
209 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 219 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
210 summary->set_in(0, Location::RegisterLocation(R0)); // Function. | 220 summary->set_in(0, Location::RegisterLocation(R0)); // Function. |
211 summary->set_out(0, Location::RegisterLocation(R0)); | 221 summary->set_out(0, Location::RegisterLocation(R0)); |
212 return summary; | 222 return summary; |
213 } | 223 } |
214 | 224 |
215 | 225 |
216 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 226 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
217 // Load arguments descriptor in R4. | 227 // Load arguments descriptor in R4. |
218 int argument_count = ArgumentCount(); | 228 int argument_count = ArgumentCount(); |
219 const Array& arguments_descriptor = | 229 const Array& arguments_descriptor = Array::ZoneHandle( |
220 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 230 ArgumentsDescriptor::New(argument_count, argument_names())); |
221 argument_names())); | |
222 __ LoadObject(R4, arguments_descriptor); | 231 __ LoadObject(R4, arguments_descriptor); |
223 | 232 |
224 // R4: Arguments descriptor. | 233 // R4: Arguments descriptor. |
225 // R0: Function. | 234 // R0: Function. |
226 ASSERT(locs()->in(0).reg() == R0); | 235 ASSERT(locs()->in(0).reg() == R0); |
227 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 236 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
228 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); | 237 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); |
229 | 238 |
230 // R2: instructions entry point. | 239 // R2: instructions entry point. |
231 // R9: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). | 240 // R9: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). |
232 __ LoadImmediate(R9, 0); | 241 __ LoadImmediate(R9, 0); |
233 __ blx(R2); | 242 __ blx(R2); |
234 compiler->RecordSafepoint(locs()); | 243 compiler->RecordSafepoint(locs()); |
235 // Marks either the continuation point in unoptimized code or the | 244 // Marks either the continuation point in unoptimized code or the |
236 // deoptimization point in optimized code, after call. | 245 // deoptimization point in optimized code, after call. |
237 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); | 246 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); |
238 if (compiler->is_optimizing()) { | 247 if (compiler->is_optimizing()) { |
239 compiler->AddDeoptIndexAtCall(deopt_id_after); | 248 compiler->AddDeoptIndexAtCall(deopt_id_after); |
240 } | 249 } |
241 // Add deoptimization continuation point after the call and before the | 250 // Add deoptimization continuation point after the call and before the |
242 // arguments are removed. | 251 // arguments are removed. |
243 // In optimized code this descriptor is needed for exception handling. | 252 // In optimized code this descriptor is needed for exception handling. |
244 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 253 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, |
245 deopt_id_after, | |
246 token_pos()); | 254 token_pos()); |
247 __ Drop(argument_count); | 255 __ Drop(argument_count); |
248 } | 256 } |
249 | 257 |
250 | 258 |
251 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 259 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
252 bool opt) const { | 260 bool opt) const { |
253 return LocationSummary::Make(zone, | 261 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), |
254 0, | |
255 Location::RequiresRegister(), | |
256 LocationSummary::kNoCall); | 262 LocationSummary::kNoCall); |
257 } | 263 } |
258 | 264 |
259 | 265 |
260 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 266 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
261 const Register result = locs()->out(0).reg(); | 267 const Register result = locs()->out(0).reg(); |
262 __ LoadFromOffset(kWord, result, FP, local().index() * kWordSize); | 268 __ LoadFromOffset(kWord, result, FP, local().index() * kWordSize); |
263 } | 269 } |
264 | 270 |
265 | 271 |
266 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 272 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |
267 bool opt) const { | 273 bool opt) const { |
268 return LocationSummary::Make(zone, | 274 return LocationSummary::Make(zone, 1, Location::SameAsFirstInput(), |
269 1, | |
270 Location::SameAsFirstInput(), | |
271 LocationSummary::kNoCall); | 275 LocationSummary::kNoCall); |
272 } | 276 } |
273 | 277 |
274 | 278 |
275 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 279 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
276 const Register value = locs()->in(0).reg(); | 280 const Register value = locs()->in(0).reg(); |
277 const Register result = locs()->out(0).reg(); | 281 const Register result = locs()->out(0).reg(); |
278 ASSERT(result == value); // Assert that register assignment is correct. | 282 ASSERT(result == value); // Assert that register assignment is correct. |
279 __ StoreToOffset(kWord, value, FP, local().index() * kWordSize); | 283 __ StoreToOffset(kWord, value, FP, local().index() * kWordSize); |
280 } | 284 } |
281 | 285 |
282 | 286 |
283 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 287 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |
284 bool opt) const { | 288 bool opt) const { |
285 return LocationSummary::Make(zone, | 289 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), |
286 0, | |
287 Location::RequiresRegister(), | |
288 LocationSummary::kNoCall); | 290 LocationSummary::kNoCall); |
289 } | 291 } |
290 | 292 |
291 | 293 |
292 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 294 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
293 // The register allocator drops constant definitions that have no uses. | 295 // The register allocator drops constant definitions that have no uses. |
294 if (!locs()->out(0).IsInvalid()) { | 296 if (!locs()->out(0).IsInvalid()) { |
295 const Register result = locs()->out(0).reg(); | 297 const Register result = locs()->out(0).reg(); |
296 __ LoadObject(result, value()); | 298 __ LoadObject(result, value()); |
297 } | 299 } |
298 } | 300 } |
299 | 301 |
300 | 302 |
301 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 303 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
302 bool opt) const { | 304 bool opt) const { |
303 const intptr_t kNumInputs = 0; | 305 const intptr_t kNumInputs = 0; |
304 const intptr_t kNumTemps = (representation_ == kUnboxedInt32) ? 0 : 1; | 306 const intptr_t kNumTemps = (representation_ == kUnboxedInt32) ? 0 : 1; |
305 LocationSummary* locs = new(zone) LocationSummary( | 307 LocationSummary* locs = new (zone) |
306 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 308 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
307 if (representation_ == kUnboxedInt32) { | 309 if (representation_ == kUnboxedInt32) { |
308 locs->set_out(0, Location::RequiresRegister()); | 310 locs->set_out(0, Location::RequiresRegister()); |
309 } else { | 311 } else { |
310 ASSERT(representation_ == kUnboxedDouble); | 312 ASSERT(representation_ == kUnboxedDouble); |
311 locs->set_out(0, Location::RequiresFpuRegister()); | 313 locs->set_out(0, Location::RequiresFpuRegister()); |
312 } | 314 } |
313 if (kNumTemps > 0) { | 315 if (kNumTemps > 0) { |
314 locs->set_temp(0, Location::RequiresRegister()); | 316 locs->set_temp(0, Location::RequiresRegister()); |
315 } | 317 } |
316 return locs; | 318 return locs; |
(...skipping 23 matching lines...) Expand all Loading... |
340 break; | 342 break; |
341 } | 343 } |
342 } | 344 } |
343 } | 345 } |
344 | 346 |
345 | 347 |
346 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 348 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
347 bool opt) const { | 349 bool opt) const { |
348 const intptr_t kNumInputs = 2; | 350 const intptr_t kNumInputs = 2; |
349 const intptr_t kNumTemps = 0; | 351 const intptr_t kNumTemps = 0; |
350 LocationSummary* summary = new(zone) LocationSummary( | 352 LocationSummary* summary = new (zone) |
351 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 353 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
352 summary->set_in(0, Location::RegisterLocation(R0)); // Value. | 354 summary->set_in(0, Location::RegisterLocation(R0)); // Value. |
353 summary->set_in(1, Location::RegisterLocation(R1)); // Type arguments. | 355 summary->set_in(1, Location::RegisterLocation(R1)); // Type arguments. |
354 summary->set_out(0, Location::RegisterLocation(R0)); | 356 summary->set_out(0, Location::RegisterLocation(R0)); |
355 return summary; | 357 return summary; |
356 } | 358 } |
357 | 359 |
358 | 360 |
359 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 361 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
360 bool opt) const { | 362 bool opt) const { |
361 const intptr_t kNumInputs = 1; | 363 const intptr_t kNumInputs = 1; |
362 const intptr_t kNumTemps = 0; | 364 const intptr_t kNumTemps = 0; |
363 LocationSummary* locs = new(zone) LocationSummary( | 365 LocationSummary* locs = new (zone) |
364 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 366 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
365 locs->set_in(0, Location::RegisterLocation(R0)); | 367 locs->set_in(0, Location::RegisterLocation(R0)); |
366 locs->set_out(0, Location::RegisterLocation(R0)); | 368 locs->set_out(0, Location::RegisterLocation(R0)); |
367 return locs; | 369 return locs; |
368 } | 370 } |
369 | 371 |
370 | 372 |
371 static void EmitAssertBoolean(Register reg, | 373 static void EmitAssertBoolean(Register reg, |
372 TokenPosition token_pos, | 374 TokenPosition token_pos, |
373 intptr_t deopt_id, | 375 intptr_t deopt_id, |
374 LocationSummary* locs, | 376 LocationSummary* locs, |
375 FlowGraphCompiler* compiler) { | 377 FlowGraphCompiler* compiler) { |
376 // Check that the type of the value is allowed in conditional context. | 378 // Check that the type of the value is allowed in conditional context. |
377 // Call the runtime if the object is not bool::true or bool::false. | 379 // Call the runtime if the object is not bool::true or bool::false. |
378 ASSERT(locs->always_calls()); | 380 ASSERT(locs->always_calls()); |
379 Label done; | 381 Label done; |
380 | 382 |
381 if (Isolate::Current()->type_checks()) { | 383 if (Isolate::Current()->type_checks()) { |
382 __ CompareObject(reg, Bool::True()); | 384 __ CompareObject(reg, Bool::True()); |
383 __ b(&done, EQ); | 385 __ b(&done, EQ); |
384 __ CompareObject(reg, Bool::False()); | 386 __ CompareObject(reg, Bool::False()); |
385 __ b(&done, EQ); | 387 __ b(&done, EQ); |
386 } else { | 388 } else { |
387 ASSERT(Isolate::Current()->asserts()); | 389 ASSERT(Isolate::Current()->asserts()); |
388 __ CompareObject(reg, Object::null_instance()); | 390 __ CompareObject(reg, Object::null_instance()); |
389 __ b(&done, NE); | 391 __ b(&done, NE); |
390 } | 392 } |
391 | 393 |
392 __ Push(reg); // Push the source object. | 394 __ Push(reg); // Push the source object. |
393 compiler->GenerateRuntimeCall(token_pos, | 395 compiler->GenerateRuntimeCall(token_pos, deopt_id, |
394 deopt_id, | 396 kNonBoolTypeErrorRuntimeEntry, 1, locs); |
395 kNonBoolTypeErrorRuntimeEntry, | |
396 1, | |
397 locs); | |
398 // We should never return here. | 397 // We should never return here. |
399 __ bkpt(0); | 398 __ bkpt(0); |
400 __ Bind(&done); | 399 __ Bind(&done); |
401 } | 400 } |
402 | 401 |
403 | 402 |
404 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 403 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
405 const Register obj = locs()->in(0).reg(); | 404 const Register obj = locs()->in(0).reg(); |
406 const Register result = locs()->out(0).reg(); | 405 const Register result = locs()->out(0).reg(); |
407 | 406 |
408 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 407 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
409 ASSERT(obj == result); | 408 ASSERT(obj == result); |
410 } | 409 } |
411 | 410 |
412 | 411 |
413 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 412 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
414 switch (kind) { | 413 switch (kind) { |
415 case Token::kEQ: return EQ; | 414 case Token::kEQ: |
416 case Token::kNE: return NE; | 415 return EQ; |
417 case Token::kLT: return LT; | 416 case Token::kNE: |
418 case Token::kGT: return GT; | 417 return NE; |
419 case Token::kLTE: return LE; | 418 case Token::kLT: |
420 case Token::kGTE: return GE; | 419 return LT; |
| 420 case Token::kGT: |
| 421 return GT; |
| 422 case Token::kLTE: |
| 423 return LE; |
| 424 case Token::kGTE: |
| 425 return GE; |
421 default: | 426 default: |
422 UNREACHABLE(); | 427 UNREACHABLE(); |
423 return VS; | 428 return VS; |
424 } | 429 } |
425 } | 430 } |
426 | 431 |
427 | 432 |
428 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 433 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |
429 bool opt) const { | 434 bool opt) const { |
430 const intptr_t kNumInputs = 2; | 435 const intptr_t kNumInputs = 2; |
431 if (operation_cid() == kMintCid) { | 436 if (operation_cid() == kMintCid) { |
432 const intptr_t kNumTemps = 0; | 437 const intptr_t kNumTemps = 0; |
433 LocationSummary* locs = new(zone) LocationSummary( | 438 LocationSummary* locs = new (zone) |
434 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 439 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
435 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 440 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
436 Location::RequiresRegister())); | 441 Location::RequiresRegister())); |
437 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 442 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
438 Location::RequiresRegister())); | 443 Location::RequiresRegister())); |
439 locs->set_out(0, Location::RequiresRegister()); | 444 locs->set_out(0, Location::RequiresRegister()); |
440 return locs; | 445 return locs; |
441 } | 446 } |
442 if (operation_cid() == kDoubleCid) { | 447 if (operation_cid() == kDoubleCid) { |
443 const intptr_t kNumTemps = 0; | 448 const intptr_t kNumTemps = 0; |
444 LocationSummary* locs = new(zone) LocationSummary( | 449 LocationSummary* locs = new (zone) |
445 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 450 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
446 locs->set_in(0, Location::RequiresFpuRegister()); | 451 locs->set_in(0, Location::RequiresFpuRegister()); |
447 locs->set_in(1, Location::RequiresFpuRegister()); | 452 locs->set_in(1, Location::RequiresFpuRegister()); |
448 locs->set_out(0, Location::RequiresRegister()); | 453 locs->set_out(0, Location::RequiresRegister()); |
449 return locs; | 454 return locs; |
450 } | 455 } |
451 if (operation_cid() == kSmiCid) { | 456 if (operation_cid() == kSmiCid) { |
452 const intptr_t kNumTemps = 0; | 457 const intptr_t kNumTemps = 0; |
453 LocationSummary* locs = new(zone) LocationSummary( | 458 LocationSummary* locs = new (zone) |
454 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 459 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
455 locs->set_in(0, Location::RegisterOrConstant(left())); | 460 locs->set_in(0, Location::RegisterOrConstant(left())); |
456 // Only one input can be a constant operand. The case of two constant | 461 // Only one input can be a constant operand. The case of two constant |
457 // operands should be handled by constant propagation. | 462 // operands should be handled by constant propagation. |
458 locs->set_in(1, locs->in(0).IsConstant() | 463 locs->set_in(1, locs->in(0).IsConstant() |
459 ? Location::RequiresRegister() | 464 ? Location::RequiresRegister() |
460 : Location::RegisterOrConstant(right())); | 465 : Location::RegisterOrConstant(right())); |
461 locs->set_out(0, Location::RequiresRegister()); | 466 locs->set_out(0, Location::RequiresRegister()); |
462 return locs; | 467 return locs; |
463 } | 468 } |
464 UNREACHABLE(); | 469 UNREACHABLE(); |
(...skipping 13 matching lines...) Expand all Loading... |
478 __ LoadClassId(value_cid_reg, value_reg, NE); | 483 __ LoadClassId(value_cid_reg, value_reg, NE); |
479 } else { | 484 } else { |
480 __ b(value_is_smi, EQ); | 485 __ b(value_is_smi, EQ); |
481 __ LoadClassId(value_cid_reg, value_reg); | 486 __ LoadClassId(value_cid_reg, value_reg); |
482 } | 487 } |
483 } | 488 } |
484 | 489 |
485 | 490 |
486 static Condition FlipCondition(Condition condition) { | 491 static Condition FlipCondition(Condition condition) { |
487 switch (condition) { | 492 switch (condition) { |
488 case EQ: return EQ; | 493 case EQ: |
489 case NE: return NE; | 494 return EQ; |
490 case LT: return GT; | 495 case NE: |
491 case LE: return GE; | 496 return NE; |
492 case GT: return LT; | 497 case LT: |
493 case GE: return LE; | 498 return GT; |
494 case CC: return HI; | 499 case LE: |
495 case LS: return CS; | 500 return GE; |
496 case HI: return CC; | 501 case GT: |
497 case CS: return LS; | 502 return LT; |
| 503 case GE: |
| 504 return LE; |
| 505 case CC: |
| 506 return HI; |
| 507 case LS: |
| 508 return CS; |
| 509 case HI: |
| 510 return CC; |
| 511 case CS: |
| 512 return LS; |
498 default: | 513 default: |
499 UNREACHABLE(); | 514 UNREACHABLE(); |
500 return EQ; | 515 return EQ; |
501 } | 516 } |
502 } | 517 } |
503 | 518 |
504 | 519 |
505 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 520 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
506 Condition true_condition, | 521 Condition true_condition, |
507 BranchLabels labels) { | 522 BranchLabels labels) { |
(...skipping 29 matching lines...) Expand all Loading... |
537 __ CompareObject(left.reg(), right.constant()); | 552 __ CompareObject(left.reg(), right.constant()); |
538 } else { | 553 } else { |
539 __ cmp(left.reg(), Operand(right.reg())); | 554 __ cmp(left.reg(), Operand(right.reg())); |
540 } | 555 } |
541 return true_condition; | 556 return true_condition; |
542 } | 557 } |
543 | 558 |
544 | 559 |
545 static Condition TokenKindToMintCondition(Token::Kind kind) { | 560 static Condition TokenKindToMintCondition(Token::Kind kind) { |
546 switch (kind) { | 561 switch (kind) { |
547 case Token::kEQ: return EQ; | 562 case Token::kEQ: |
548 case Token::kNE: return NE; | 563 return EQ; |
549 case Token::kLT: return LT; | 564 case Token::kNE: |
550 case Token::kGT: return GT; | 565 return NE; |
551 case Token::kLTE: return LE; | 566 case Token::kLT: |
552 case Token::kGTE: return GE; | 567 return LT; |
| 568 case Token::kGT: |
| 569 return GT; |
| 570 case Token::kLTE: |
| 571 return LE; |
| 572 case Token::kGTE: |
| 573 return GE; |
553 default: | 574 default: |
554 UNREACHABLE(); | 575 UNREACHABLE(); |
555 return VS; | 576 return VS; |
556 } | 577 } |
557 } | 578 } |
558 | 579 |
559 | 580 |
560 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 581 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
561 LocationSummary* locs, | 582 LocationSummary* locs, |
562 Token::Kind kind) { | 583 Token::Kind kind) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 __ b(labels.false_label, FlipCondition(hi_cond)); | 637 __ b(labels.false_label, FlipCondition(hi_cond)); |
617 | 638 |
618 // If higher words are equal, compare lower words. | 639 // If higher words are equal, compare lower words. |
619 __ cmp(left_lo, Operand(right_lo)); | 640 __ cmp(left_lo, Operand(right_lo)); |
620 return lo_cond; | 641 return lo_cond; |
621 } | 642 } |
622 | 643 |
623 | 644 |
624 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 645 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
625 switch (kind) { | 646 switch (kind) { |
626 case Token::kEQ: return EQ; | 647 case Token::kEQ: |
627 case Token::kNE: return NE; | 648 return EQ; |
628 case Token::kLT: return LT; | 649 case Token::kNE: |
629 case Token::kGT: return GT; | 650 return NE; |
630 case Token::kLTE: return LE; | 651 case Token::kLT: |
631 case Token::kGTE: return GE; | 652 return LT; |
| 653 case Token::kGT: |
| 654 return GT; |
| 655 case Token::kLTE: |
| 656 return LE; |
| 657 case Token::kGTE: |
| 658 return GE; |
632 default: | 659 default: |
633 UNREACHABLE(); | 660 UNREACHABLE(); |
634 return VS; | 661 return VS; |
635 } | 662 } |
636 } | 663 } |
637 | 664 |
638 | 665 |
639 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 666 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
640 LocationSummary* locs, | 667 LocationSummary* locs, |
641 Token::Kind kind) { | 668 Token::Kind kind) { |
(...skipping 18 matching lines...) Expand all Loading... |
660 ASSERT(operation_cid() == kDoubleCid); | 687 ASSERT(operation_cid() == kDoubleCid); |
661 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 688 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
662 } | 689 } |
663 } | 690 } |
664 | 691 |
665 | 692 |
666 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 693 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
667 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 694 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
668 | 695 |
669 // The ARM code does not use true- and false-labels here. | 696 // The ARM code does not use true- and false-labels here. |
670 BranchLabels labels = { NULL, NULL, NULL }; | 697 BranchLabels labels = {NULL, NULL, NULL}; |
671 Condition true_condition = EmitComparisonCode(compiler, labels); | 698 Condition true_condition = EmitComparisonCode(compiler, labels); |
672 | 699 |
673 const Register result = locs()->out(0).reg(); | 700 const Register result = locs()->out(0).reg(); |
674 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { | 701 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
675 __ LoadObject(result, Bool::True(), true_condition); | 702 __ LoadObject(result, Bool::True(), true_condition); |
676 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 703 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
677 } else { | 704 } else { |
678 ASSERT(operation_cid() == kDoubleCid); | 705 ASSERT(operation_cid() == kDoubleCid); |
679 Label done; | 706 Label done; |
680 __ LoadObject(result, Bool::False()); | 707 __ LoadObject(result, Bool::False()); |
681 if (true_condition != NE) { | 708 if (true_condition != NE) { |
682 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. | 709 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. |
683 } | 710 } |
684 __ LoadObject(result, Bool::True(), true_condition); | 711 __ LoadObject(result, Bool::True(), true_condition); |
685 __ Bind(&done); | 712 __ Bind(&done); |
686 } | 713 } |
687 } | 714 } |
688 | 715 |
689 | 716 |
690 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 717 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
691 BranchInstr* branch) { | 718 BranchInstr* branch) { |
692 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 719 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
693 | 720 |
694 BranchLabels labels = compiler->CreateBranchLabels(branch); | 721 BranchLabels labels = compiler->CreateBranchLabels(branch); |
695 Condition true_condition = EmitComparisonCode(compiler, labels); | 722 Condition true_condition = EmitComparisonCode(compiler, labels); |
696 | 723 |
697 if (operation_cid() == kDoubleCid) { | 724 if (operation_cid() == kDoubleCid) { |
698 Label* nan_result = (true_condition == NE) ? | 725 Label* nan_result = |
699 labels.true_label : labels.false_label; | 726 (true_condition == NE) ? labels.true_label : labels.false_label; |
700 __ b(nan_result, VS); | 727 __ b(nan_result, VS); |
701 } | 728 } |
702 EmitBranchOnCondition(compiler, true_condition, labels); | 729 EmitBranchOnCondition(compiler, true_condition, labels); |
703 } | 730 } |
704 | 731 |
705 | 732 |
706 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, | 733 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
707 bool opt) const { | |
708 const intptr_t kNumInputs = 2; | 734 const intptr_t kNumInputs = 2; |
709 const intptr_t kNumTemps = 0; | 735 const intptr_t kNumTemps = 0; |
710 LocationSummary* locs = new(zone) LocationSummary( | 736 LocationSummary* locs = new (zone) |
711 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 737 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
712 locs->set_in(0, Location::RequiresRegister()); | 738 locs->set_in(0, Location::RequiresRegister()); |
713 // Only one input can be a constant operand. The case of two constant | 739 // Only one input can be a constant operand. The case of two constant |
714 // operands should be handled by constant propagation. | 740 // operands should be handled by constant propagation. |
715 locs->set_in(1, Location::RegisterOrConstant(right())); | 741 locs->set_in(1, Location::RegisterOrConstant(right())); |
716 return locs; | 742 return locs; |
717 } | 743 } |
718 | 744 |
719 | 745 |
720 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 746 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
721 BranchLabels labels) { | 747 BranchLabels labels) { |
722 const Register left = locs()->in(0).reg(); | 748 const Register left = locs()->in(0).reg(); |
723 Location right = locs()->in(1); | 749 Location right = locs()->in(1); |
724 if (right.IsConstant()) { | 750 if (right.IsConstant()) { |
725 ASSERT(right.constant().IsSmi()); | 751 ASSERT(right.constant().IsSmi()); |
726 const int32_t imm = | 752 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); |
727 reinterpret_cast<int32_t>(right.constant().raw()); | |
728 __ TestImmediate(left, imm); | 753 __ TestImmediate(left, imm); |
729 } else { | 754 } else { |
730 __ tst(left, Operand(right.reg())); | 755 __ tst(left, Operand(right.reg())); |
731 } | 756 } |
732 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; | 757 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |
733 return true_condition; | 758 return true_condition; |
734 } | 759 } |
735 | 760 |
736 | 761 |
737 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 762 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
738 // Never emitted outside of the BranchInstr. | 763 // Never emitted outside of the BranchInstr. |
739 UNREACHABLE(); | 764 UNREACHABLE(); |
740 } | 765 } |
741 | 766 |
742 | 767 |
743 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 768 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
744 BranchInstr* branch) { | 769 BranchInstr* branch) { |
745 BranchLabels labels = compiler->CreateBranchLabels(branch); | 770 BranchLabels labels = compiler->CreateBranchLabels(branch); |
746 Condition true_condition = EmitComparisonCode(compiler, labels); | 771 Condition true_condition = EmitComparisonCode(compiler, labels); |
747 EmitBranchOnCondition(compiler, true_condition, labels); | 772 EmitBranchOnCondition(compiler, true_condition, labels); |
748 } | 773 } |
749 | 774 |
750 | 775 |
751 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 776 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
752 bool opt) const { | 777 bool opt) const { |
753 const intptr_t kNumInputs = 1; | 778 const intptr_t kNumInputs = 1; |
754 const intptr_t kNumTemps = 1; | 779 const intptr_t kNumTemps = 1; |
755 LocationSummary* locs = new(zone) LocationSummary( | 780 LocationSummary* locs = new (zone) |
756 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 781 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
757 locs->set_in(0, Location::RequiresRegister()); | 782 locs->set_in(0, Location::RequiresRegister()); |
758 locs->set_temp(0, Location::RequiresRegister()); | 783 locs->set_temp(0, Location::RequiresRegister()); |
759 locs->set_out(0, Location::RequiresRegister()); | 784 locs->set_out(0, Location::RequiresRegister()); |
760 return locs; | 785 return locs; |
761 } | 786 } |
762 | 787 |
763 | 788 |
764 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 789 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
765 BranchLabels labels) { | 790 BranchLabels labels) { |
766 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 791 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
767 const Register val_reg = locs()->in(0).reg(); | 792 const Register val_reg = locs()->in(0).reg(); |
768 const Register cid_reg = locs()->temp(0).reg(); | 793 const Register cid_reg = locs()->temp(0).reg(); |
769 | 794 |
770 Label* deopt = CanDeoptimize() | 795 Label* deopt = |
771 ? compiler->AddDeoptStub(deopt_id(), | 796 CanDeoptimize() |
772 ICData::kDeoptTestCids, | 797 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, |
773 licm_hoisted_ ? ICData::kHoisted : 0) | 798 licm_hoisted_ ? ICData::kHoisted : 0) |
774 : NULL; | 799 : NULL; |
775 | 800 |
776 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 801 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
777 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 802 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
778 ASSERT(data[0] == kSmiCid); | 803 ASSERT(data[0] == kSmiCid); |
779 bool result = data[1] == true_result; | 804 bool result = data[1] == true_result; |
780 __ tst(val_reg, Operand(kSmiTagMask)); | 805 __ tst(val_reg, Operand(kSmiTagMask)); |
781 __ b(result ? labels.true_label : labels.false_label, EQ); | 806 __ b(result ? labels.true_label : labels.false_label, EQ); |
782 __ LoadClassId(cid_reg, val_reg); | 807 __ LoadClassId(cid_reg, val_reg); |
783 | 808 |
784 for (intptr_t i = 2; i < data.length(); i += 2) { | 809 for (intptr_t i = 2; i < data.length(); i += 2) { |
(...skipping 21 matching lines...) Expand all Loading... |
806 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 831 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
807 BranchInstr* branch) { | 832 BranchInstr* branch) { |
808 BranchLabels labels = compiler->CreateBranchLabels(branch); | 833 BranchLabels labels = compiler->CreateBranchLabels(branch); |
809 EmitComparisonCode(compiler, labels); | 834 EmitComparisonCode(compiler, labels); |
810 } | 835 } |
811 | 836 |
812 | 837 |
813 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 838 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
814 const Register result_reg = locs()->out(0).reg(); | 839 const Register result_reg = locs()->out(0).reg(); |
815 Label is_true, is_false, done; | 840 Label is_true, is_false, done; |
816 BranchLabels labels = { &is_true, &is_false, &is_false }; | 841 BranchLabels labels = {&is_true, &is_false, &is_false}; |
817 EmitComparisonCode(compiler, labels); | 842 EmitComparisonCode(compiler, labels); |
818 __ Bind(&is_false); | 843 __ Bind(&is_false); |
819 __ LoadObject(result_reg, Bool::False()); | 844 __ LoadObject(result_reg, Bool::False()); |
820 __ b(&done); | 845 __ b(&done); |
821 __ Bind(&is_true); | 846 __ Bind(&is_true); |
822 __ LoadObject(result_reg, Bool::True()); | 847 __ LoadObject(result_reg, Bool::True()); |
823 __ Bind(&done); | 848 __ Bind(&done); |
824 } | 849 } |
825 | 850 |
826 | 851 |
827 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 852 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
828 bool opt) const { | 853 bool opt) const { |
829 const intptr_t kNumInputs = 2; | 854 const intptr_t kNumInputs = 2; |
830 const intptr_t kNumTemps = 0; | 855 const intptr_t kNumTemps = 0; |
831 if (operation_cid() == kMintCid) { | 856 if (operation_cid() == kMintCid) { |
832 const intptr_t kNumTemps = 0; | 857 const intptr_t kNumTemps = 0; |
833 LocationSummary* locs = new(zone) LocationSummary( | 858 LocationSummary* locs = new (zone) |
834 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 859 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
835 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 860 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
836 Location::RequiresRegister())); | 861 Location::RequiresRegister())); |
837 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 862 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
838 Location::RequiresRegister())); | 863 Location::RequiresRegister())); |
839 locs->set_out(0, Location::RequiresRegister()); | 864 locs->set_out(0, Location::RequiresRegister()); |
840 return locs; | 865 return locs; |
841 } | 866 } |
842 if (operation_cid() == kDoubleCid) { | 867 if (operation_cid() == kDoubleCid) { |
843 LocationSummary* summary = new(zone) LocationSummary( | 868 LocationSummary* summary = new (zone) |
844 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 869 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
845 summary->set_in(0, Location::RequiresFpuRegister()); | 870 summary->set_in(0, Location::RequiresFpuRegister()); |
846 summary->set_in(1, Location::RequiresFpuRegister()); | 871 summary->set_in(1, Location::RequiresFpuRegister()); |
847 summary->set_out(0, Location::RequiresRegister()); | 872 summary->set_out(0, Location::RequiresRegister()); |
848 return summary; | 873 return summary; |
849 } | 874 } |
850 ASSERT(operation_cid() == kSmiCid); | 875 ASSERT(operation_cid() == kSmiCid); |
851 LocationSummary* summary = new(zone) LocationSummary( | 876 LocationSummary* summary = new (zone) |
852 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 877 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
853 summary->set_in(0, Location::RegisterOrConstant(left())); | 878 summary->set_in(0, Location::RegisterOrConstant(left())); |
854 // Only one input can be a constant operand. The case of two constant | 879 // Only one input can be a constant operand. The case of two constant |
855 // operands should be handled by constant propagation. | 880 // operands should be handled by constant propagation. |
856 summary->set_in(1, summary->in(0).IsConstant() | 881 summary->set_in(1, summary->in(0).IsConstant() |
857 ? Location::RequiresRegister() | 882 ? Location::RequiresRegister() |
858 : Location::RegisterOrConstant(right())); | 883 : Location::RegisterOrConstant(right())); |
859 summary->set_out(0, Location::RequiresRegister()); | 884 summary->set_out(0, Location::RequiresRegister()); |
860 return summary; | 885 return summary; |
861 } | 886 } |
862 | 887 |
863 | 888 |
864 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 889 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
865 BranchLabels labels) { | 890 BranchLabels labels) { |
866 if (operation_cid() == kSmiCid) { | 891 if (operation_cid() == kSmiCid) { |
867 return EmitSmiComparisonOp(compiler, locs(), kind()); | 892 return EmitSmiComparisonOp(compiler, locs(), kind()); |
868 } else if (operation_cid() == kMintCid) { | 893 } else if (operation_cid() == kMintCid) { |
869 return EmitUnboxedMintComparisonOp(compiler, locs(), kind(), labels); | 894 return EmitUnboxedMintComparisonOp(compiler, locs(), kind(), labels); |
870 } else { | 895 } else { |
871 ASSERT(operation_cid() == kDoubleCid); | 896 ASSERT(operation_cid() == kDoubleCid); |
872 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 897 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
873 } | 898 } |
874 } | 899 } |
875 | 900 |
876 | 901 |
877 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 902 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
878 Label is_true, is_false; | 903 Label is_true, is_false; |
879 BranchLabels labels = { &is_true, &is_false, &is_false }; | 904 BranchLabels labels = {&is_true, &is_false, &is_false}; |
880 Condition true_condition = EmitComparisonCode(compiler, labels); | 905 Condition true_condition = EmitComparisonCode(compiler, labels); |
881 | 906 |
882 const Register result = locs()->out(0).reg(); | 907 const Register result = locs()->out(0).reg(); |
883 if (operation_cid() == kSmiCid) { | 908 if (operation_cid() == kSmiCid) { |
884 __ LoadObject(result, Bool::True(), true_condition); | 909 __ LoadObject(result, Bool::True(), true_condition); |
885 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 910 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
886 } else if (operation_cid() == kMintCid) { | 911 } else if (operation_cid() == kMintCid) { |
887 EmitBranchOnCondition(compiler, true_condition, labels); | 912 EmitBranchOnCondition(compiler, true_condition, labels); |
888 Label done; | 913 Label done; |
889 __ Bind(&is_false); | 914 __ Bind(&is_false); |
(...skipping 16 matching lines...) Expand all Loading... |
906 | 931 |
907 | 932 |
908 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 933 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
909 BranchInstr* branch) { | 934 BranchInstr* branch) { |
910 BranchLabels labels = compiler->CreateBranchLabels(branch); | 935 BranchLabels labels = compiler->CreateBranchLabels(branch); |
911 Condition true_condition = EmitComparisonCode(compiler, labels); | 936 Condition true_condition = EmitComparisonCode(compiler, labels); |
912 | 937 |
913 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { | 938 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
914 EmitBranchOnCondition(compiler, true_condition, labels); | 939 EmitBranchOnCondition(compiler, true_condition, labels); |
915 } else if (operation_cid() == kDoubleCid) { | 940 } else if (operation_cid() == kDoubleCid) { |
916 Label* nan_result = (true_condition == NE) ? | 941 Label* nan_result = |
917 labels.true_label : labels.false_label; | 942 (true_condition == NE) ? labels.true_label : labels.false_label; |
918 __ b(nan_result, VS); | 943 __ b(nan_result, VS); |
919 EmitBranchOnCondition(compiler, true_condition, labels); | 944 EmitBranchOnCondition(compiler, true_condition, labels); |
920 } | 945 } |
921 } | 946 } |
922 | 947 |
923 | 948 |
924 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, | 949 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, |
925 bool opt) const { | 950 bool opt) const { |
926 return MakeCallSummary(zone); | 951 return MakeCallSummary(zone); |
927 } | 952 } |
928 | 953 |
929 | 954 |
930 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 955 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
931 SetupNative(); | 956 SetupNative(); |
932 const Register result = locs()->out(0).reg(); | 957 const Register result = locs()->out(0).reg(); |
933 | 958 |
934 // Push the result place holder initialized to NULL. | 959 // Push the result place holder initialized to NULL. |
935 __ PushObject(Object::null_object()); | 960 __ PushObject(Object::null_object()); |
936 // Pass a pointer to the first argument in R2. | 961 // Pass a pointer to the first argument in R2. |
937 if (!function().HasOptionalParameters()) { | 962 if (!function().HasOptionalParameters()) { |
938 __ AddImmediate(R2, FP, (kParamEndSlotFromFp + | 963 __ AddImmediate( |
939 function().NumParameters()) * kWordSize); | 964 R2, FP, (kParamEndSlotFromFp + function().NumParameters()) * kWordSize); |
940 } else { | 965 } else { |
941 __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize); | 966 __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize); |
942 } | 967 } |
943 // Compute the effective address. When running under the simulator, | 968 // Compute the effective address. When running under the simulator, |
944 // this is a redirection address that forces the simulator to call | 969 // this is a redirection address that forces the simulator to call |
945 // into the runtime system. | 970 // into the runtime system. |
946 uword entry; | 971 uword entry; |
947 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 972 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
948 const StubEntry* stub_entry; | 973 const StubEntry* stub_entry; |
949 if (link_lazily()) { | 974 if (link_lazily()) { |
(...skipping 10 matching lines...) Expand all Loading... |
960 } else { | 985 } else { |
961 // In the case of non bootstrap native methods the CallNativeCFunction | 986 // In the case of non bootstrap native methods the CallNativeCFunction |
962 // stub generates the redirection address when running under the simulator | 987 // stub generates the redirection address when running under the simulator |
963 // and hence we do not change 'entry' here. | 988 // and hence we do not change 'entry' here. |
964 stub_entry = StubCode::CallNativeCFunction_entry(); | 989 stub_entry = StubCode::CallNativeCFunction_entry(); |
965 } | 990 } |
966 } | 991 } |
967 __ LoadImmediate(R1, argc_tag); | 992 __ LoadImmediate(R1, argc_tag); |
968 ExternalLabel label(entry); | 993 ExternalLabel label(entry); |
969 __ LoadNativeEntry(R9, &label, link_lazily() ? kPatchable : kNotPatchable); | 994 __ LoadNativeEntry(R9, &label, link_lazily() ? kPatchable : kNotPatchable); |
970 compiler->GenerateCall(token_pos(), | 995 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, |
971 *stub_entry, | |
972 RawPcDescriptors::kOther, | |
973 locs()); | 996 locs()); |
974 __ Pop(result); | 997 __ Pop(result); |
975 } | 998 } |
976 | 999 |
977 | 1000 |
978 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 1001 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |
979 Zone* zone, bool opt) const { | 1002 Zone* zone, |
| 1003 bool opt) const { |
980 const intptr_t kNumInputs = 1; | 1004 const intptr_t kNumInputs = 1; |
981 // TODO(fschneider): Allow immediate operands for the char code. | 1005 // TODO(fschneider): Allow immediate operands for the char code. |
982 return LocationSummary::Make(zone, | 1006 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
983 kNumInputs, | |
984 Location::RequiresRegister(), | |
985 LocationSummary::kNoCall); | 1007 LocationSummary::kNoCall); |
986 } | 1008 } |
987 | 1009 |
988 | 1010 |
989 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 1011 void OneByteStringFromCharCodeInstr::EmitNativeCode( |
990 FlowGraphCompiler* compiler) { | 1012 FlowGraphCompiler* compiler) { |
991 ASSERT(compiler->is_optimizing()); | 1013 ASSERT(compiler->is_optimizing()); |
992 const Register char_code = locs()->in(0).reg(); | 1014 const Register char_code = locs()->in(0).reg(); |
993 const Register result = locs()->out(0).reg(); | 1015 const Register result = locs()->out(0).reg(); |
994 | 1016 |
995 __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset())); | 1017 __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset())); |
996 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); | 1018 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); |
997 __ ldr(result, Address(result, char_code, LSL, 1)); // Char code is a smi. | 1019 __ ldr(result, Address(result, char_code, LSL, 1)); // Char code is a smi. |
998 } | 1020 } |
999 | 1021 |
1000 | 1022 |
1001 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 1023 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
1002 bool opt) const { | 1024 bool opt) const { |
1003 const intptr_t kNumInputs = 1; | 1025 const intptr_t kNumInputs = 1; |
1004 return LocationSummary::Make(zone, | 1026 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
1005 kNumInputs, | |
1006 Location::RequiresRegister(), | |
1007 LocationSummary::kNoCall); | 1027 LocationSummary::kNoCall); |
1008 } | 1028 } |
1009 | 1029 |
1010 | 1030 |
1011 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1031 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1012 ASSERT(cid_ == kOneByteStringCid); | 1032 ASSERT(cid_ == kOneByteStringCid); |
1013 const Register str = locs()->in(0).reg(); | 1033 const Register str = locs()->in(0).reg(); |
1014 const Register result = locs()->out(0).reg(); | 1034 const Register result = locs()->out(0).reg(); |
1015 __ ldr(result, FieldAddress(str, String::length_offset())); | 1035 __ ldr(result, FieldAddress(str, String::length_offset())); |
1016 __ cmp(result, Operand(Smi::RawValue(1))); | 1036 __ cmp(result, Operand(Smi::RawValue(1))); |
1017 __ LoadImmediate(result, -1, NE); | 1037 __ LoadImmediate(result, -1, NE); |
1018 __ ldrb(result, FieldAddress(str, OneByteString::data_offset()), EQ); | 1038 __ ldrb(result, FieldAddress(str, OneByteString::data_offset()), EQ); |
1019 __ SmiTag(result); | 1039 __ SmiTag(result); |
1020 } | 1040 } |
1021 | 1041 |
1022 | 1042 |
1023 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 1043 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |
1024 bool opt) const { | 1044 bool opt) const { |
1025 const intptr_t kNumInputs = 1; | 1045 const intptr_t kNumInputs = 1; |
1026 const intptr_t kNumTemps = 0; | 1046 const intptr_t kNumTemps = 0; |
1027 LocationSummary* summary = new(zone) LocationSummary( | 1047 LocationSummary* summary = new (zone) |
1028 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 1048 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
1029 summary->set_in(0, Location::RegisterLocation(R0)); | 1049 summary->set_in(0, Location::RegisterLocation(R0)); |
1030 summary->set_out(0, Location::RegisterLocation(R0)); | 1050 summary->set_out(0, Location::RegisterLocation(R0)); |
1031 return summary; | 1051 return summary; |
1032 } | 1052 } |
1033 | 1053 |
1034 | 1054 |
1035 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1055 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1036 const Register array = locs()->in(0).reg(); | 1056 const Register array = locs()->in(0).reg(); |
1037 __ Push(array); | 1057 __ Push(array); |
1038 const int kNumberOfArguments = 1; | 1058 const int kNumberOfArguments = 1; |
1039 const Array& kNoArgumentNames = Object::null_array(); | 1059 const Array& kNoArgumentNames = Object::null_array(); |
1040 compiler->GenerateStaticCall(deopt_id(), | 1060 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), |
1041 token_pos(), | 1061 kNumberOfArguments, kNoArgumentNames, locs(), |
1042 CallFunction(), | |
1043 kNumberOfArguments, | |
1044 kNoArgumentNames, | |
1045 locs(), | |
1046 ICData::Handle()); | 1062 ICData::Handle()); |
1047 ASSERT(locs()->out(0).reg() == R0); | 1063 ASSERT(locs()->out(0).reg() == R0); |
1048 } | 1064 } |
1049 | 1065 |
1050 | 1066 |
1051 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 1067 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |
1052 bool opt) const { | 1068 bool opt) const { |
1053 const intptr_t kNumInputs = 1; | 1069 const intptr_t kNumInputs = 1; |
1054 return LocationSummary::Make(zone, | 1070 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
1055 kNumInputs, | |
1056 Location::RequiresRegister(), | |
1057 LocationSummary::kNoCall); | 1071 LocationSummary::kNoCall); |
1058 } | 1072 } |
1059 | 1073 |
1060 | 1074 |
1061 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1075 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1062 const Register obj = locs()->in(0).reg(); | 1076 const Register obj = locs()->in(0).reg(); |
1063 const Register result = locs()->out(0).reg(); | 1077 const Register result = locs()->out(0).reg(); |
1064 if (object()->definition()->representation() == kUntagged) { | 1078 if (object()->definition()->representation() == kUntagged) { |
1065 __ LoadFromOffset(kWord, result, obj, offset()); | 1079 __ LoadFromOffset(kWord, result, obj, offset()); |
1066 } else { | 1080 } else { |
1067 ASSERT(object()->definition()->representation() == kTagged); | 1081 ASSERT(object()->definition()->representation() == kTagged); |
1068 __ LoadFieldFromOffset(kWord, result, obj, offset()); | 1082 __ LoadFieldFromOffset(kWord, result, obj, offset()); |
1069 } | 1083 } |
1070 } | 1084 } |
1071 | 1085 |
1072 | 1086 |
1073 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 1087 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |
1074 bool opt) const { | 1088 bool opt) const { |
1075 const intptr_t kNumInputs = 1; | 1089 const intptr_t kNumInputs = 1; |
1076 return LocationSummary::Make(zone, | 1090 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
1077 kNumInputs, | |
1078 Location::RequiresRegister(), | |
1079 LocationSummary::kNoCall); | 1091 LocationSummary::kNoCall); |
1080 } | 1092 } |
1081 | 1093 |
1082 | 1094 |
1083 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1095 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1084 const Register object = locs()->in(0).reg(); | 1096 const Register object = locs()->in(0).reg(); |
1085 const Register result = locs()->out(0).reg(); | 1097 const Register result = locs()->out(0).reg(); |
1086 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 1098 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |
1087 if (CompileType::Smi().IsAssignableTo(value_type) || | 1099 if (CompileType::Smi().IsAssignableTo(value_type) || |
1088 value_type.IsTypeParameter()) { | 1100 value_type.IsTypeParameter()) { |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1205 } | 1217 } |
1206 | 1218 |
1207 return false; | 1219 return false; |
1208 } | 1220 } |
1209 | 1221 |
1210 | 1222 |
1211 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 1223 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
1212 bool opt) const { | 1224 bool opt) const { |
1213 const intptr_t kNumInputs = 2; | 1225 const intptr_t kNumInputs = 2; |
1214 const intptr_t kNumTemps = aligned() ? 0 : 1; | 1226 const intptr_t kNumTemps = aligned() ? 0 : 1; |
1215 LocationSummary* locs = new(zone) LocationSummary( | 1227 LocationSummary* locs = new (zone) |
1216 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1228 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1217 locs->set_in(0, Location::RequiresRegister()); | 1229 locs->set_in(0, Location::RequiresRegister()); |
1218 bool needs_base = false; | 1230 bool needs_base = false; |
1219 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), | 1231 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), |
1220 true, // Load. | 1232 true, // Load. |
1221 &needs_base)) { | 1233 &needs_base)) { |
1222 // CanBeImmediateIndex must return false for unsafe smis. | 1234 // CanBeImmediateIndex must return false for unsafe smis. |
1223 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1235 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
1224 } else { | 1236 } else { |
1225 locs->set_in(1, Location::RequiresRegister()); | 1237 locs->set_in(1, Location::RequiresRegister()); |
1226 } | 1238 } |
1227 if ((representation() == kUnboxedDouble) || | 1239 if ((representation() == kUnboxedDouble) || |
1228 (representation() == kUnboxedFloat32x4) || | 1240 (representation() == kUnboxedFloat32x4) || |
1229 (representation() == kUnboxedInt32x4) || | 1241 (representation() == kUnboxedInt32x4) || |
1230 (representation() == kUnboxedFloat64x2)) { | 1242 (representation() == kUnboxedFloat64x2)) { |
1231 if (class_id() == kTypedDataFloat32ArrayCid) { | 1243 if (class_id() == kTypedDataFloat32ArrayCid) { |
1232 // Need register <= Q7 for float operations. | 1244 // Need register <= Q7 for float operations. |
1233 // TODO(fschneider): Add a register policy to specify a subset of | 1245 // TODO(fschneider): Add a register policy to specify a subset of |
1234 // registers. | 1246 // registers. |
1235 locs->set_out(0, Location::FpuRegisterLocation(Q7)); | 1247 locs->set_out(0, Location::FpuRegisterLocation(Q7)); |
1236 } else { | 1248 } else { |
1237 locs->set_out(0, Location::RequiresFpuRegister()); | 1249 locs->set_out(0, Location::RequiresFpuRegister()); |
1238 } | 1250 } |
1239 } else if (representation() == kUnboxedUint32) { | 1251 } else if (representation() == kUnboxedUint32) { |
(...skipping 15 matching lines...) Expand all Loading... |
1255 | 1267 |
1256 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1268 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1257 // The array register points to the backing store for external arrays. | 1269 // The array register points to the backing store for external arrays. |
1258 const Register array = locs()->in(0).reg(); | 1270 const Register array = locs()->in(0).reg(); |
1259 const Location index = locs()->in(1); | 1271 const Location index = locs()->in(1); |
1260 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); | 1272 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |
1261 | 1273 |
1262 Address element_address(kNoRegister); | 1274 Address element_address(kNoRegister); |
1263 if (aligned()) { | 1275 if (aligned()) { |
1264 element_address = index.IsRegister() | 1276 element_address = index.IsRegister() |
1265 ? __ ElementAddressForRegIndex(true, // Load. | 1277 ? __ ElementAddressForRegIndex( |
1266 IsExternal(), class_id(), index_scale(), | 1278 true, // Load. |
1267 array, | 1279 IsExternal(), class_id(), index_scale(), array, |
1268 index.reg()) | 1280 index.reg()) |
1269 : __ ElementAddressForIntIndex(true, // Load. | 1281 : __ ElementAddressForIntIndex( |
1270 IsExternal(), class_id(), index_scale(), | 1282 true, // Load. |
1271 array, Smi::Cast(index.constant()).Value(), | 1283 IsExternal(), class_id(), index_scale(), array, |
1272 IP); // Temp register. | 1284 Smi::Cast(index.constant()).Value(), |
| 1285 IP); // Temp register. |
1273 // Warning: element_address may use register IP as base. | 1286 // Warning: element_address may use register IP as base. |
1274 } else { | 1287 } else { |
1275 if (index.IsRegister()) { | 1288 if (index.IsRegister()) { |
1276 __ LoadElementAddressForRegIndex(address, | 1289 __ LoadElementAddressForRegIndex(address, |
1277 true, // Load. | 1290 true, // Load. |
1278 IsExternal(), class_id(), index_scale(), | 1291 IsExternal(), class_id(), index_scale(), |
1279 array, | 1292 array, index.reg()); |
1280 index.reg()); | |
1281 } else { | 1293 } else { |
1282 __ LoadElementAddressForIntIndex(address, | 1294 __ LoadElementAddressForIntIndex(address, |
1283 true, // Load. | 1295 true, // Load. |
1284 IsExternal(), class_id(), index_scale(), | 1296 IsExternal(), class_id(), index_scale(), |
1285 array, | 1297 array, |
1286 Smi::Cast(index.constant()).Value()); | 1298 Smi::Cast(index.constant()).Value()); |
1287 } | 1299 } |
1288 } | 1300 } |
1289 | 1301 |
1290 if ((representation() == kUnboxedDouble) || | 1302 if ((representation() == kUnboxedDouble) || |
1291 (representation() == kUnboxedFloat32x4) || | 1303 (representation() == kUnboxedFloat32x4) || |
1292 (representation() == kUnboxedInt32x4) || | 1304 (representation() == kUnboxedInt32x4) || |
1293 (representation() == kUnboxedFloat64x2)) { | 1305 (representation() == kUnboxedFloat64x2)) { |
1294 const QRegister result = locs()->out(0).fpu_reg(); | 1306 const QRegister result = locs()->out(0).fpu_reg(); |
1295 const DRegister dresult0 = EvenDRegisterOf(result); | 1307 const DRegister dresult0 = EvenDRegisterOf(result); |
1296 switch (class_id()) { | 1308 switch (class_id()) { |
1297 case kTypedDataFloat32ArrayCid: | 1309 case kTypedDataFloat32ArrayCid: |
1298 // Load single precision float. | 1310 // Load single precision float. |
1299 // vldrs does not support indexed addressing. | 1311 // vldrs does not support indexed addressing. |
1300 __ vldrs(EvenSRegisterOf(dresult0), element_address); | 1312 __ vldrs(EvenSRegisterOf(dresult0), element_address); |
1301 break; | 1313 break; |
1302 case kTypedDataFloat64ArrayCid: | 1314 case kTypedDataFloat64ArrayCid: |
(...skipping 16 matching lines...) Expand all Loading... |
1319 (representation() == kUnboxedInt32)) { | 1331 (representation() == kUnboxedInt32)) { |
1320 Register result = locs()->out(0).reg(); | 1332 Register result = locs()->out(0).reg(); |
1321 switch (class_id()) { | 1333 switch (class_id()) { |
1322 case kTypedDataInt32ArrayCid: | 1334 case kTypedDataInt32ArrayCid: |
1323 ASSERT(representation() == kUnboxedInt32); | 1335 ASSERT(representation() == kUnboxedInt32); |
1324 if (aligned()) { | 1336 if (aligned()) { |
1325 __ ldr(result, element_address); | 1337 __ ldr(result, element_address); |
1326 } else { | 1338 } else { |
1327 __ LoadWordUnaligned(result, address, TMP); | 1339 __ LoadWordUnaligned(result, address, TMP); |
1328 } | 1340 } |
1329 break; | 1341 break; |
1330 case kTypedDataUint32ArrayCid: | 1342 case kTypedDataUint32ArrayCid: |
1331 ASSERT(representation() == kUnboxedUint32); | 1343 ASSERT(representation() == kUnboxedUint32); |
1332 if (aligned()) { | 1344 if (aligned()) { |
1333 __ ldr(result, element_address); | 1345 __ ldr(result, element_address); |
1334 } else { | 1346 } else { |
1335 __ LoadWordUnaligned(result, address, TMP); | 1347 __ LoadWordUnaligned(result, address, TMP); |
1336 } | 1348 } |
1337 break; | 1349 break; |
1338 default: | 1350 default: |
1339 UNREACHABLE(); | 1351 UNREACHABLE(); |
1340 } | 1352 } |
1341 return; | 1353 return; |
1342 } | 1354 } |
1343 | 1355 |
1344 ASSERT(representation() == kTagged); | 1356 ASSERT(representation() == kTagged); |
1345 | 1357 |
1346 const Register result = locs()->out(0).reg(); | 1358 const Register result = locs()->out(0).reg(); |
1347 switch (class_id()) { | 1359 switch (class_id()) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1384 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1396 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
1385 __ ldr(result, element_address); | 1397 __ ldr(result, element_address); |
1386 break; | 1398 break; |
1387 } | 1399 } |
1388 } | 1400 } |
1389 | 1401 |
1390 | 1402 |
1391 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1403 Representation StoreIndexedInstr::RequiredInputRepresentation( |
1392 intptr_t idx) const { | 1404 intptr_t idx) const { |
1393 // Array can be a Dart object or a pointer to external data. | 1405 // Array can be a Dart object or a pointer to external data. |
1394 if (idx == 0) return kNoRepresentation; // Flexible input representation. | 1406 if (idx == 0) return kNoRepresentation; // Flexible input representation. |
1395 if (idx == 1) return kTagged; // Index is a smi. | 1407 if (idx == 1) return kTagged; // Index is a smi. |
1396 ASSERT(idx == 2); | 1408 ASSERT(idx == 2); |
1397 switch (class_id_) { | 1409 switch (class_id_) { |
1398 case kArrayCid: | 1410 case kArrayCid: |
1399 case kOneByteStringCid: | 1411 case kOneByteStringCid: |
1400 case kTypedDataInt8ArrayCid: | 1412 case kTypedDataInt8ArrayCid: |
1401 case kTypedDataUint8ArrayCid: | 1413 case kTypedDataUint8ArrayCid: |
1402 case kExternalTypedDataUint8ArrayCid: | 1414 case kExternalTypedDataUint8ArrayCid: |
1403 case kTypedDataUint8ClampedArrayCid: | 1415 case kTypedDataUint8ClampedArrayCid: |
1404 case kExternalTypedDataUint8ClampedArrayCid: | 1416 case kExternalTypedDataUint8ClampedArrayCid: |
1405 case kTypedDataInt16ArrayCid: | 1417 case kTypedDataInt16ArrayCid: |
(...skipping 22 matching lines...) Expand all Loading... |
1428 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1440 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
1429 bool opt) const { | 1441 bool opt) const { |
1430 const intptr_t kNumInputs = 3; | 1442 const intptr_t kNumInputs = 3; |
1431 LocationSummary* locs; | 1443 LocationSummary* locs; |
1432 | 1444 |
1433 bool needs_base = false; | 1445 bool needs_base = false; |
1434 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), | 1446 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), |
1435 false, // Store. | 1447 false, // Store. |
1436 &needs_base)) { | 1448 &needs_base)) { |
1437 const intptr_t kNumTemps = aligned() ? (needs_base ? 1 : 0) : 2; | 1449 const intptr_t kNumTemps = aligned() ? (needs_base ? 1 : 0) : 2; |
1438 locs = new(zone) LocationSummary( | 1450 locs = new (zone) |
1439 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1451 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1440 | 1452 |
1441 // CanBeImmediateIndex must return false for unsafe smis. | 1453 // CanBeImmediateIndex must return false for unsafe smis. |
1442 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1454 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
1443 if (needs_base) { | 1455 if (needs_base) { |
1444 locs->set_temp(0, Location::RequiresRegister()); | 1456 locs->set_temp(0, Location::RequiresRegister()); |
1445 } | 1457 } |
1446 if (!aligned()) { | 1458 if (!aligned()) { |
1447 locs->set_temp(0, Location::RequiresRegister()); | 1459 locs->set_temp(0, Location::RequiresRegister()); |
1448 locs->set_temp(1, Location::RequiresRegister()); | 1460 locs->set_temp(1, Location::RequiresRegister()); |
1449 } | 1461 } |
1450 } else { | 1462 } else { |
1451 const intptr_t kNumTemps = aligned() ? 0 : 2; | 1463 const intptr_t kNumTemps = aligned() ? 0 : 2; |
1452 locs = new(zone) LocationSummary( | 1464 locs = new (zone) |
1453 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1465 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1454 | 1466 |
1455 locs->set_in(1, Location::WritableRegister()); | 1467 locs->set_in(1, Location::WritableRegister()); |
1456 if (!aligned()) { | 1468 if (!aligned()) { |
1457 locs->set_temp(0, Location::RequiresRegister()); | 1469 locs->set_temp(0, Location::RequiresRegister()); |
1458 locs->set_temp(1, Location::RequiresRegister()); | 1470 locs->set_temp(1, Location::RequiresRegister()); |
1459 } | 1471 } |
1460 } | 1472 } |
1461 locs->set_in(0, Location::RequiresRegister()); | 1473 locs->set_in(0, Location::RequiresRegister()); |
1462 | 1474 |
1463 switch (class_id()) { | 1475 switch (class_id()) { |
1464 case kArrayCid: | 1476 case kArrayCid: |
1465 locs->set_in(2, ShouldEmitStoreBarrier() | 1477 locs->set_in(2, ShouldEmitStoreBarrier() |
1466 ? Location::WritableRegister() | 1478 ? Location::WritableRegister() |
1467 : Location::RegisterOrConstant(value())); | 1479 : Location::RegisterOrConstant(value())); |
1468 break; | 1480 break; |
1469 case kExternalTypedDataUint8ArrayCid: | 1481 case kExternalTypedDataUint8ArrayCid: |
1470 case kExternalTypedDataUint8ClampedArrayCid: | 1482 case kExternalTypedDataUint8ClampedArrayCid: |
1471 case kTypedDataInt8ArrayCid: | 1483 case kTypedDataInt8ArrayCid: |
1472 case kTypedDataUint8ArrayCid: | 1484 case kTypedDataUint8ArrayCid: |
1473 case kTypedDataUint8ClampedArrayCid: | 1485 case kTypedDataUint8ClampedArrayCid: |
1474 case kOneByteStringCid: | 1486 case kOneByteStringCid: |
1475 case kTypedDataInt16ArrayCid: | 1487 case kTypedDataInt16ArrayCid: |
1476 case kTypedDataUint16ArrayCid: | 1488 case kTypedDataUint16ArrayCid: |
1477 case kTypedDataInt32ArrayCid: | 1489 case kTypedDataInt32ArrayCid: |
(...skipping 23 matching lines...) Expand all Loading... |
1501 const Register array = locs()->in(0).reg(); | 1513 const Register array = locs()->in(0).reg(); |
1502 const Location index = locs()->in(1); | 1514 const Location index = locs()->in(1); |
1503 const Register temp = | 1515 const Register temp = |
1504 (locs()->temp_count() > 0) ? locs()->temp(0).reg() : kNoRegister; | 1516 (locs()->temp_count() > 0) ? locs()->temp(0).reg() : kNoRegister; |
1505 const Register temp2 = | 1517 const Register temp2 = |
1506 (locs()->temp_count() > 1) ? locs()->temp(1).reg() : kNoRegister; | 1518 (locs()->temp_count() > 1) ? locs()->temp(1).reg() : kNoRegister; |
1507 | 1519 |
1508 Address element_address(kNoRegister); | 1520 Address element_address(kNoRegister); |
1509 if (aligned()) { | 1521 if (aligned()) { |
1510 element_address = index.IsRegister() | 1522 element_address = index.IsRegister() |
1511 ? __ ElementAddressForRegIndex(false, // Store. | 1523 ? __ ElementAddressForRegIndex( |
1512 IsExternal(), class_id(), index_scale(), | 1524 false, // Store. |
1513 array, | 1525 IsExternal(), class_id(), index_scale(), array, |
1514 index.reg()) | 1526 index.reg()) |
1515 : __ ElementAddressForIntIndex(false, // Store. | 1527 : __ ElementAddressForIntIndex( |
1516 IsExternal(), class_id(), index_scale(), | 1528 false, // Store. |
1517 array, Smi::Cast(index.constant()).Value(), | 1529 IsExternal(), class_id(), index_scale(), array, |
1518 temp); | 1530 Smi::Cast(index.constant()).Value(), temp); |
1519 } else { | 1531 } else { |
1520 if (index.IsRegister()) { | 1532 if (index.IsRegister()) { |
1521 __ LoadElementAddressForRegIndex(temp, | 1533 __ LoadElementAddressForRegIndex(temp, |
1522 false, // Store. | 1534 false, // Store. |
1523 IsExternal(), class_id(), index_scale(), | 1535 IsExternal(), class_id(), index_scale(), |
1524 array, | 1536 array, index.reg()); |
1525 index.reg()); | |
1526 } else { | 1537 } else { |
1527 __ LoadElementAddressForIntIndex(temp, | 1538 __ LoadElementAddressForIntIndex(temp, |
1528 false, // Store. | 1539 false, // Store. |
1529 IsExternal(), class_id(), index_scale(), | 1540 IsExternal(), class_id(), index_scale(), |
1530 array, | 1541 array, |
1531 Smi::Cast(index.constant()).Value()); | 1542 Smi::Cast(index.constant()).Value()); |
1532 } | 1543 } |
1533 } | 1544 } |
1534 | 1545 |
1535 switch (class_id()) { | 1546 switch (class_id()) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1569 if (value > 0xFF) { | 1580 if (value > 0xFF) { |
1570 value = 0xFF; | 1581 value = 0xFF; |
1571 } else if (value < 0) { | 1582 } else if (value < 0) { |
1572 value = 0; | 1583 value = 0; |
1573 } | 1584 } |
1574 __ LoadImmediate(IP, static_cast<int8_t>(value)); | 1585 __ LoadImmediate(IP, static_cast<int8_t>(value)); |
1575 __ strb(IP, element_address); | 1586 __ strb(IP, element_address); |
1576 } else { | 1587 } else { |
1577 const Register value = locs()->in(2).reg(); | 1588 const Register value = locs()->in(2).reg(); |
1578 __ LoadImmediate(IP, 0x1FE); // Smi 0xFF. | 1589 __ LoadImmediate(IP, 0x1FE); // Smi 0xFF. |
1579 __ cmp(value, Operand(IP)); // Compare Smi value and smi 0xFF. | 1590 __ cmp(value, Operand(IP)); // Compare Smi value and smi 0xFF. |
1580 // Clamp to 0x00 or 0xFF respectively. | 1591 // Clamp to 0x00 or 0xFF respectively. |
1581 __ mov(IP, Operand(0), LE); // IP = value <= 0x1FE ? 0 : 0x1FE. | 1592 __ mov(IP, Operand(0), LE); // IP = value <= 0x1FE ? 0 : 0x1FE. |
1582 __ mov(IP, Operand(value), LS); // IP = value in range ? value : IP. | 1593 __ mov(IP, Operand(value), LS); // IP = value in range ? value : IP. |
1583 __ SmiUntag(IP); | 1594 __ SmiUntag(IP); |
1584 __ strb(IP, element_address); | 1595 __ strb(IP, element_address); |
1585 } | 1596 } |
1586 break; | 1597 break; |
1587 } | 1598 } |
1588 case kTypedDataInt16ArrayCid: | 1599 case kTypedDataInt16ArrayCid: |
1589 case kTypedDataUint16ArrayCid: { | 1600 case kTypedDataUint16ArrayCid: { |
1590 const Register value = locs()->in(2).reg(); | 1601 const Register value = locs()->in(2).reg(); |
1591 __ SmiUntag(IP, value); | 1602 __ SmiUntag(IP, value); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1631 } | 1642 } |
1632 | 1643 |
1633 | 1644 |
1634 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 1645 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |
1635 bool opt) const { | 1646 bool opt) const { |
1636 const intptr_t kNumInputs = 1; | 1647 const intptr_t kNumInputs = 1; |
1637 | 1648 |
1638 const intptr_t value_cid = value()->Type()->ToCid(); | 1649 const intptr_t value_cid = value()->Type()->ToCid(); |
1639 const intptr_t field_cid = field().guarded_cid(); | 1650 const intptr_t field_cid = field().guarded_cid(); |
1640 | 1651 |
1641 const bool emit_full_guard = | 1652 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); |
1642 !opt || (field_cid == kIllegalCid); | |
1643 | 1653 |
1644 const bool needs_value_cid_temp_reg = emit_full_guard || | 1654 const bool needs_value_cid_temp_reg = |
1645 ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); | 1655 emit_full_guard || ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); |
1646 | 1656 |
1647 const bool needs_field_temp_reg = emit_full_guard; | 1657 const bool needs_field_temp_reg = emit_full_guard; |
1648 | 1658 |
1649 intptr_t num_temps = 0; | 1659 intptr_t num_temps = 0; |
1650 if (needs_value_cid_temp_reg) { | 1660 if (needs_value_cid_temp_reg) { |
1651 num_temps++; | 1661 num_temps++; |
1652 } | 1662 } |
1653 if (needs_field_temp_reg) { | 1663 if (needs_field_temp_reg) { |
1654 num_temps++; | 1664 num_temps++; |
1655 } | 1665 } |
1656 | 1666 |
1657 LocationSummary* summary = new(zone) LocationSummary( | 1667 LocationSummary* summary = new (zone) |
1658 zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 1668 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
1659 summary->set_in(0, Location::RequiresRegister()); | 1669 summary->set_in(0, Location::RequiresRegister()); |
1660 | 1670 |
1661 for (intptr_t i = 0; i < num_temps; i++) { | 1671 for (intptr_t i = 0; i < num_temps; i++) { |
1662 summary->set_temp(i, Location::RequiresRegister()); | 1672 summary->set_temp(i, Location::RequiresRegister()); |
1663 } | 1673 } |
1664 | 1674 |
1665 return summary; | 1675 return summary; |
1666 } | 1676 } |
1667 | 1677 |
1668 | 1678 |
1669 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1679 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1670 ASSERT(sizeof(classid_t) == kInt16Size); | 1680 ASSERT(sizeof(classid_t) == kInt16Size); |
1671 | 1681 |
1672 const intptr_t value_cid = value()->Type()->ToCid(); | 1682 const intptr_t value_cid = value()->Type()->ToCid(); |
1673 const intptr_t field_cid = field().guarded_cid(); | 1683 const intptr_t field_cid = field().guarded_cid(); |
1674 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1684 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
1675 | 1685 |
1676 if (field_cid == kDynamicCid) { | 1686 if (field_cid == kDynamicCid) { |
1677 if (Compiler::IsBackgroundCompilation()) { | 1687 if (Compiler::IsBackgroundCompilation()) { |
1678 // Field state changed while compiling. | 1688 // Field state changed while compiling. |
1679 Compiler::AbortBackgroundCompilation(deopt_id(), | 1689 Compiler::AbortBackgroundCompilation( |
| 1690 deopt_id(), |
1680 "GuardFieldClassInstr: field state changed while compiling"); | 1691 "GuardFieldClassInstr: field state changed while compiling"); |
1681 } | 1692 } |
1682 ASSERT(!compiler->is_optimizing()); | 1693 ASSERT(!compiler->is_optimizing()); |
1683 return; // Nothing to emit. | 1694 return; // Nothing to emit. |
1684 } | 1695 } |
1685 | 1696 |
1686 const bool emit_full_guard = | 1697 const bool emit_full_guard = |
1687 !compiler->is_optimizing() || (field_cid == kIllegalCid); | 1698 !compiler->is_optimizing() || (field_cid == kIllegalCid); |
1688 | 1699 |
1689 const bool needs_value_cid_temp_reg = emit_full_guard || | 1700 const bool needs_value_cid_temp_reg = |
1690 ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); | 1701 emit_full_guard || ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); |
1691 | 1702 |
1692 const bool needs_field_temp_reg = emit_full_guard; | 1703 const bool needs_field_temp_reg = emit_full_guard; |
1693 | 1704 |
1694 const Register value_reg = locs()->in(0).reg(); | 1705 const Register value_reg = locs()->in(0).reg(); |
1695 | 1706 |
1696 const Register value_cid_reg = needs_value_cid_temp_reg ? | 1707 const Register value_cid_reg = |
1697 locs()->temp(0).reg() : kNoRegister; | 1708 needs_value_cid_temp_reg ? locs()->temp(0).reg() : kNoRegister; |
1698 | 1709 |
1699 const Register field_reg = needs_field_temp_reg ? | 1710 const Register field_reg = needs_field_temp_reg |
1700 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; | 1711 ? locs()->temp(locs()->temp_count() - 1).reg() |
| 1712 : kNoRegister; |
1701 | 1713 |
1702 Label ok, fail_label; | 1714 Label ok, fail_label; |
1703 | 1715 |
1704 Label* deopt = compiler->is_optimizing() ? | 1716 Label* deopt = |
1705 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1717 compiler->is_optimizing() |
| 1718 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1719 : NULL; |
1706 | 1720 |
1707 Label* fail = (deopt != NULL) ? deopt : &fail_label; | 1721 Label* fail = (deopt != NULL) ? deopt : &fail_label; |
1708 | 1722 |
1709 if (emit_full_guard) { | 1723 if (emit_full_guard) { |
1710 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1724 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
1711 | 1725 |
1712 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); | 1726 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); |
1713 FieldAddress field_nullability_operand( | 1727 FieldAddress field_nullability_operand(field_reg, |
1714 field_reg, Field::is_nullable_offset()); | 1728 Field::is_nullable_offset()); |
1715 | 1729 |
1716 if (value_cid == kDynamicCid) { | 1730 if (value_cid == kDynamicCid) { |
1717 LoadValueCid(compiler, value_cid_reg, value_reg); | 1731 LoadValueCid(compiler, value_cid_reg, value_reg); |
1718 __ ldrh(IP, field_cid_operand); | 1732 __ ldrh(IP, field_cid_operand); |
1719 __ cmp(value_cid_reg, Operand(IP)); | 1733 __ cmp(value_cid_reg, Operand(IP)); |
1720 __ b(&ok, EQ); | 1734 __ b(&ok, EQ); |
1721 __ ldrh(IP, field_nullability_operand); | 1735 __ ldrh(IP, field_nullability_operand); |
1722 __ cmp(value_cid_reg, Operand(IP)); | 1736 __ cmp(value_cid_reg, Operand(IP)); |
1723 } else if (value_cid == kNullCid) { | 1737 } else if (value_cid == kNullCid) { |
1724 __ ldrh(value_cid_reg, field_nullability_operand); | 1738 __ ldrh(value_cid_reg, field_nullability_operand); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1802 } | 1816 } |
1803 __ Bind(&ok); | 1817 __ Bind(&ok); |
1804 } | 1818 } |
1805 | 1819 |
1806 | 1820 |
1807 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 1821 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |
1808 bool opt) const { | 1822 bool opt) const { |
1809 const intptr_t kNumInputs = 1; | 1823 const intptr_t kNumInputs = 1; |
1810 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1824 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
1811 const intptr_t kNumTemps = 3; | 1825 const intptr_t kNumTemps = 3; |
1812 LocationSummary* summary = new(zone) LocationSummary( | 1826 LocationSummary* summary = new (zone) |
1813 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1827 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1814 summary->set_in(0, Location::RequiresRegister()); | 1828 summary->set_in(0, Location::RequiresRegister()); |
1815 // We need temporaries for field object, length offset and expected length. | 1829 // We need temporaries for field object, length offset and expected length. |
1816 summary->set_temp(0, Location::RequiresRegister()); | 1830 summary->set_temp(0, Location::RequiresRegister()); |
1817 summary->set_temp(1, Location::RequiresRegister()); | 1831 summary->set_temp(1, Location::RequiresRegister()); |
1818 summary->set_temp(2, Location::RequiresRegister()); | 1832 summary->set_temp(2, Location::RequiresRegister()); |
1819 return summary; | 1833 return summary; |
1820 } else { | 1834 } else { |
1821 // TODO(vegorov): can use TMP when length is small enough to fit into | 1835 // TODO(vegorov): can use TMP when length is small enough to fit into |
1822 // immediate. | 1836 // immediate. |
1823 const intptr_t kNumTemps = 1; | 1837 const intptr_t kNumTemps = 1; |
1824 LocationSummary* summary = new(zone) LocationSummary( | 1838 LocationSummary* summary = new (zone) |
1825 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1839 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1826 summary->set_in(0, Location::RequiresRegister()); | 1840 summary->set_in(0, Location::RequiresRegister()); |
1827 summary->set_temp(0, Location::RequiresRegister()); | 1841 summary->set_temp(0, Location::RequiresRegister()); |
1828 return summary; | 1842 return summary; |
1829 } | 1843 } |
1830 UNREACHABLE(); | 1844 UNREACHABLE(); |
1831 } | 1845 } |
1832 | 1846 |
1833 | 1847 |
1834 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1848 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1835 if (field().guarded_list_length() == Field::kNoFixedLength) { | 1849 if (field().guarded_list_length() == Field::kNoFixedLength) { |
1836 if (Compiler::IsBackgroundCompilation()) { | 1850 if (Compiler::IsBackgroundCompilation()) { |
1837 // Field state changed while compiling. | 1851 // Field state changed while compiling. |
1838 Compiler::AbortBackgroundCompilation(deopt_id(), | 1852 Compiler::AbortBackgroundCompilation( |
| 1853 deopt_id(), |
1839 "GuardFieldLengthInstr: field state changed while compiling"); | 1854 "GuardFieldLengthInstr: field state changed while compiling"); |
1840 } | 1855 } |
1841 ASSERT(!compiler->is_optimizing()); | 1856 ASSERT(!compiler->is_optimizing()); |
1842 return; // Nothing to emit. | 1857 return; // Nothing to emit. |
1843 } | 1858 } |
1844 | 1859 |
1845 Label* deopt = compiler->is_optimizing() ? | 1860 Label* deopt = |
1846 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1861 compiler->is_optimizing() |
| 1862 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1863 : NULL; |
1847 | 1864 |
1848 const Register value_reg = locs()->in(0).reg(); | 1865 const Register value_reg = locs()->in(0).reg(); |
1849 | 1866 |
1850 if (!compiler->is_optimizing() || | 1867 if (!compiler->is_optimizing() || |
1851 (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1868 (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
1852 const Register field_reg = locs()->temp(0).reg(); | 1869 const Register field_reg = locs()->temp(0).reg(); |
1853 const Register offset_reg = locs()->temp(1).reg(); | 1870 const Register offset_reg = locs()->temp(1).reg(); |
1854 const Register length_reg = locs()->temp(2).reg(); | 1871 const Register length_reg = locs()->temp(2).reg(); |
1855 | 1872 |
1856 Label ok; | 1873 Label ok; |
1857 | 1874 |
1858 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1875 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
1859 | 1876 |
1860 __ ldrsb(offset_reg, FieldAddress(field_reg, | 1877 __ ldrsb( |
1861 Field::guarded_list_length_in_object_offset_offset())); | 1878 offset_reg, |
1862 __ ldr(length_reg, FieldAddress(field_reg, | 1879 FieldAddress(field_reg, |
1863 Field::guarded_list_length_offset())); | 1880 Field::guarded_list_length_in_object_offset_offset())); |
| 1881 __ ldr(length_reg, |
| 1882 FieldAddress(field_reg, Field::guarded_list_length_offset())); |
1864 | 1883 |
1865 __ tst(offset_reg, Operand(offset_reg)); | 1884 __ tst(offset_reg, Operand(offset_reg)); |
1866 __ b(&ok, MI); | 1885 __ b(&ok, MI); |
1867 | 1886 |
1868 // Load the length from the value. GuardFieldClass already verified that | 1887 // Load the length from the value. GuardFieldClass already verified that |
1869 // value's class matches guarded class id of the field. | 1888 // value's class matches guarded class id of the field. |
1870 // offset_reg contains offset already corrected by -kHeapObjectTag that is | 1889 // offset_reg contains offset already corrected by -kHeapObjectTag that is |
1871 // why we use Address instead of FieldAddress. | 1890 // why we use Address instead of FieldAddress. |
1872 __ ldr(IP, Address(value_reg, offset_reg)); | 1891 __ ldr(IP, Address(value_reg, offset_reg)); |
1873 __ cmp(length_reg, Operand(IP)); | 1892 __ cmp(length_reg, Operand(IP)); |
1874 | 1893 |
1875 if (deopt == NULL) { | 1894 if (deopt == NULL) { |
1876 __ b(&ok, EQ); | 1895 __ b(&ok, EQ); |
1877 | 1896 |
1878 __ Push(field_reg); | 1897 __ Push(field_reg); |
1879 __ Push(value_reg); | 1898 __ Push(value_reg); |
1880 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); | 1899 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); |
1881 __ Drop(2); // Drop the field and the value. | 1900 __ Drop(2); // Drop the field and the value. |
1882 } else { | 1901 } else { |
1883 __ b(deopt, NE); | 1902 __ b(deopt, NE); |
1884 } | 1903 } |
1885 | 1904 |
1886 __ Bind(&ok); | 1905 __ Bind(&ok); |
1887 } else { | 1906 } else { |
1888 ASSERT(compiler->is_optimizing()); | 1907 ASSERT(compiler->is_optimizing()); |
1889 ASSERT(field().guarded_list_length() >= 0); | 1908 ASSERT(field().guarded_list_length() >= 0); |
1890 ASSERT(field().guarded_list_length_in_object_offset() != | 1909 ASSERT(field().guarded_list_length_in_object_offset() != |
1891 Field::kUnknownLengthOffset); | 1910 Field::kUnknownLengthOffset); |
1892 | 1911 |
1893 const Register length_reg = locs()->temp(0).reg(); | 1912 const Register length_reg = locs()->temp(0).reg(); |
1894 | 1913 |
1895 __ ldr(length_reg, | 1914 __ ldr(length_reg, |
1896 FieldAddress(value_reg, | 1915 FieldAddress(value_reg, |
1897 field().guarded_list_length_in_object_offset())); | 1916 field().guarded_list_length_in_object_offset())); |
1898 __ CompareImmediate(length_reg, | 1917 __ CompareImmediate(length_reg, |
1899 Smi::RawValue(field().guarded_list_length())); | 1918 Smi::RawValue(field().guarded_list_length())); |
1900 __ b(deopt, NE); | 1919 __ b(deopt, NE); |
1901 } | 1920 } |
1902 } | 1921 } |
1903 | 1922 |
1904 | 1923 |
1905 class BoxAllocationSlowPath : public SlowPathCode { | 1924 class BoxAllocationSlowPath : public SlowPathCode { |
1906 public: | 1925 public: |
1907 BoxAllocationSlowPath(Instruction* instruction, | 1926 BoxAllocationSlowPath(Instruction* instruction, |
1908 const Class& cls, | 1927 const Class& cls, |
1909 Register result) | 1928 Register result) |
1910 : instruction_(instruction), | 1929 : instruction_(instruction), cls_(cls), result_(result) {} |
1911 cls_(cls), | |
1912 result_(result) { } | |
1913 | 1930 |
1914 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1931 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
1915 if (Assembler::EmittingComments()) { | 1932 if (Assembler::EmittingComments()) { |
1916 __ Comment("%s slow path allocation of %s", | 1933 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), |
1917 instruction_->DebugName(), | |
1918 String::Handle(cls_.ScrubbedName()).ToCString()); | 1934 String::Handle(cls_.ScrubbedName()).ToCString()); |
1919 } | 1935 } |
1920 __ Bind(entry_label()); | 1936 __ Bind(entry_label()); |
1921 const Code& stub = Code::ZoneHandle( | 1937 const Code& stub = Code::ZoneHandle( |
1922 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); | 1938 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); |
1923 const StubEntry stub_entry(stub); | 1939 const StubEntry stub_entry(stub); |
1924 | 1940 |
1925 LocationSummary* locs = instruction_->locs(); | 1941 LocationSummary* locs = instruction_->locs(); |
1926 | 1942 |
1927 locs->live_registers()->Remove(Location::RegisterLocation(result_)); | 1943 locs->live_registers()->Remove(Location::RegisterLocation(result_)); |
1928 | 1944 |
1929 compiler->SaveLiveRegisters(locs); | 1945 compiler->SaveLiveRegisters(locs); |
1930 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. | 1946 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. |
1931 stub_entry, | 1947 stub_entry, RawPcDescriptors::kOther, locs); |
1932 RawPcDescriptors::kOther, | |
1933 locs); | |
1934 compiler->AddStubCallTarget(stub); | 1948 compiler->AddStubCallTarget(stub); |
1935 __ MoveRegister(result_, R0); | 1949 __ MoveRegister(result_, R0); |
1936 compiler->RestoreLiveRegisters(locs); | 1950 compiler->RestoreLiveRegisters(locs); |
1937 __ b(exit_label()); | 1951 __ b(exit_label()); |
1938 } | 1952 } |
1939 | 1953 |
1940 static void Allocate(FlowGraphCompiler* compiler, | 1954 static void Allocate(FlowGraphCompiler* compiler, |
1941 Instruction* instruction, | 1955 Instruction* instruction, |
1942 const Class& cls, | 1956 const Class& cls, |
1943 Register result, | 1957 Register result, |
1944 Register temp) { | 1958 Register temp) { |
1945 if (compiler->intrinsic_mode()) { | 1959 if (compiler->intrinsic_mode()) { |
1946 __ TryAllocate(cls, | 1960 __ TryAllocate(cls, compiler->intrinsic_slow_path_label(), result, temp); |
1947 compiler->intrinsic_slow_path_label(), | |
1948 result, | |
1949 temp); | |
1950 } else { | 1961 } else { |
1951 BoxAllocationSlowPath* slow_path = | 1962 BoxAllocationSlowPath* slow_path = |
1952 new BoxAllocationSlowPath(instruction, cls, result); | 1963 new BoxAllocationSlowPath(instruction, cls, result); |
1953 compiler->AddSlowPathCode(slow_path); | 1964 compiler->AddSlowPathCode(slow_path); |
1954 | 1965 |
1955 __ TryAllocate(cls, | 1966 __ TryAllocate(cls, slow_path->entry_label(), result, temp); |
1956 slow_path->entry_label(), | |
1957 result, | |
1958 temp); | |
1959 __ Bind(slow_path->exit_label()); | 1967 __ Bind(slow_path->exit_label()); |
1960 } | 1968 } |
1961 } | 1969 } |
1962 | 1970 |
1963 private: | 1971 private: |
1964 Instruction* instruction_; | 1972 Instruction* instruction_; |
1965 const Class& cls_; | 1973 const Class& cls_; |
1966 const Register result_; | 1974 const Register result_; |
1967 }; | 1975 }; |
1968 | 1976 |
1969 | 1977 |
1970 | |
1971 | |
1972 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 1978 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |
1973 bool opt) const { | 1979 bool opt) const { |
1974 const bool might_box = (representation() == kTagged) && !can_pack_into_smi(); | 1980 const bool might_box = (representation() == kTagged) && !can_pack_into_smi(); |
1975 const intptr_t kNumInputs = 2; | 1981 const intptr_t kNumInputs = 2; |
1976 const intptr_t kNumTemps = might_box ? 1 : 0; | 1982 const intptr_t kNumTemps = might_box ? 1 : 0; |
1977 LocationSummary* summary = new(zone) LocationSummary( | 1983 LocationSummary* summary = new (zone) LocationSummary( |
1978 zone, kNumInputs, kNumTemps, | 1984 zone, kNumInputs, kNumTemps, |
1979 might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall); | 1985 might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall); |
1980 summary->set_in(0, Location::RequiresRegister()); | 1986 summary->set_in(0, Location::RequiresRegister()); |
1981 summary->set_in(1, Location::RequiresRegister()); | 1987 summary->set_in(1, Location::RequiresRegister()); |
1982 | 1988 |
1983 if (might_box) { | 1989 if (might_box) { |
1984 summary->set_temp(0, Location::RequiresRegister()); | 1990 summary->set_temp(0, Location::RequiresRegister()); |
1985 } | 1991 } |
1986 | 1992 |
1987 if (representation() == kUnboxedMint) { | 1993 if (representation() == kUnboxedMint) { |
1988 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 1994 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
1989 Location::RequiresRegister())); | 1995 Location::RequiresRegister())); |
1990 } else { | 1996 } else { |
1991 ASSERT(representation() == kTagged); | 1997 ASSERT(representation() == kTagged); |
1992 summary->set_out(0, Location::RequiresRegister()); | 1998 summary->set_out(0, Location::RequiresRegister()); |
1993 } | 1999 } |
1994 | 2000 |
1995 return summary; | 2001 return summary; |
1996 } | 2002 } |
1997 | 2003 |
1998 | 2004 |
1999 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2005 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2000 // The string register points to the backing store for external strings. | 2006 // The string register points to the backing store for external strings. |
2001 const Register str = locs()->in(0).reg(); | 2007 const Register str = locs()->in(0).reg(); |
2002 const Location index = locs()->in(1); | 2008 const Location index = locs()->in(1); |
2003 | 2009 |
2004 Address element_address = __ ElementAddressForRegIndex( | 2010 Address element_address = __ ElementAddressForRegIndex( |
2005 true, IsExternal(), class_id(), index_scale(), str, index.reg()); | 2011 true, IsExternal(), class_id(), index_scale(), str, index.reg()); |
2006 // Warning: element_address may use register IP as base. | 2012 // Warning: element_address may use register IP as base. |
2007 | 2013 |
2008 if (representation() == kUnboxedMint) { | 2014 if (representation() == kUnboxedMint) { |
2009 ASSERT(compiler->is_optimizing()); | 2015 ASSERT(compiler->is_optimizing()); |
2010 ASSERT(locs()->out(0).IsPairLocation()); | 2016 ASSERT(locs()->out(0).IsPairLocation()); |
2011 PairLocation* result_pair = locs()->out(0).AsPairLocation(); | 2017 PairLocation* result_pair = locs()->out(0).AsPairLocation(); |
2012 Register result1 = result_pair->At(0).reg(); | 2018 Register result1 = result_pair->At(0).reg(); |
2013 Register result2 = result_pair->At(1).reg(); | 2019 Register result2 = result_pair->At(1).reg(); |
2014 switch (class_id()) { | 2020 switch (class_id()) { |
2015 case kOneByteStringCid: | 2021 case kOneByteStringCid: |
(...skipping 11 matching lines...) Expand all Loading... |
2027 default: | 2033 default: |
2028 UNREACHABLE(); | 2034 UNREACHABLE(); |
2029 } | 2035 } |
2030 } else { | 2036 } else { |
2031 ASSERT(representation() == kTagged); | 2037 ASSERT(representation() == kTagged); |
2032 Register result = locs()->out(0).reg(); | 2038 Register result = locs()->out(0).reg(); |
2033 switch (class_id()) { | 2039 switch (class_id()) { |
2034 case kOneByteStringCid: | 2040 case kOneByteStringCid: |
2035 case kExternalOneByteStringCid: | 2041 case kExternalOneByteStringCid: |
2036 switch (element_count()) { | 2042 switch (element_count()) { |
2037 case 1: __ ldrb(result, element_address); break; | 2043 case 1: |
2038 case 2: __ ldrh(result, element_address); break; | 2044 __ ldrb(result, element_address); |
2039 case 4: __ ldr(result, element_address); break; | 2045 break; |
2040 default: UNREACHABLE(); | 2046 case 2: |
| 2047 __ ldrh(result, element_address); |
| 2048 break; |
| 2049 case 4: |
| 2050 __ ldr(result, element_address); |
| 2051 break; |
| 2052 default: |
| 2053 UNREACHABLE(); |
2041 } | 2054 } |
2042 break; | 2055 break; |
2043 case kTwoByteStringCid: | 2056 case kTwoByteStringCid: |
2044 case kExternalTwoByteStringCid: | 2057 case kExternalTwoByteStringCid: |
2045 switch (element_count()) { | 2058 switch (element_count()) { |
2046 case 1: __ ldrh(result, element_address); break; | 2059 case 1: |
2047 case 2: __ ldr(result, element_address); break; | 2060 __ ldrh(result, element_address); |
2048 default: UNREACHABLE(); | 2061 break; |
| 2062 case 2: |
| 2063 __ ldr(result, element_address); |
| 2064 break; |
| 2065 default: |
| 2066 UNREACHABLE(); |
2049 } | 2067 } |
2050 break; | 2068 break; |
2051 default: | 2069 default: |
2052 UNREACHABLE(); | 2070 UNREACHABLE(); |
2053 break; | 2071 break; |
2054 } | 2072 } |
2055 if (can_pack_into_smi()) { | 2073 if (can_pack_into_smi()) { |
2056 __ SmiTag(result); | 2074 __ SmiTag(result); |
2057 } else { | 2075 } else { |
2058 // If the value cannot fit in a smi then allocate a mint box for it. | 2076 // If the value cannot fit in a smi then allocate a mint box for it. |
2059 Register value = locs()->temp(0).reg(); | 2077 Register value = locs()->temp(0).reg(); |
2060 Register temp = locs()->temp(1).reg(); | 2078 Register temp = locs()->temp(1).reg(); |
2061 // Value register needs to be manually preserved on allocation slow-path. | 2079 // Value register needs to be manually preserved on allocation slow-path. |
2062 locs()->live_registers()->Add(locs()->temp(0), kUnboxedInt32); | 2080 locs()->live_registers()->Add(locs()->temp(0), kUnboxedInt32); |
2063 | 2081 |
2064 ASSERT(result != value); | 2082 ASSERT(result != value); |
2065 __ MoveRegister(value, result); | 2083 __ MoveRegister(value, result); |
2066 __ SmiTag(result); | 2084 __ SmiTag(result); |
2067 | 2085 |
2068 Label done; | 2086 Label done; |
2069 __ TestImmediate(value, 0xC0000000); | 2087 __ TestImmediate(value, 0xC0000000); |
2070 __ b(&done, EQ); | 2088 __ b(&done, EQ); |
2071 BoxAllocationSlowPath::Allocate( | 2089 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), |
2072 compiler, this, compiler->mint_class(), result, temp); | 2090 result, temp); |
2073 __ eor(temp, temp, Operand(temp)); | 2091 __ eor(temp, temp, Operand(temp)); |
2074 __ StoreToOffset(kWord, value, result, | 2092 __ StoreToOffset(kWord, value, result, |
2075 Mint::value_offset() - kHeapObjectTag); | 2093 Mint::value_offset() - kHeapObjectTag); |
2076 __ StoreToOffset(kWord, temp, result, | 2094 __ StoreToOffset(kWord, temp, result, |
2077 Mint::value_offset() - kHeapObjectTag + kWordSize); | 2095 Mint::value_offset() - kHeapObjectTag + kWordSize); |
2078 __ Bind(&done); | 2096 __ Bind(&done); |
2079 } | 2097 } |
2080 } | 2098 } |
2081 } | 2099 } |
2082 | 2100 |
2083 | 2101 |
2084 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 2102 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |
2085 bool opt) const { | 2103 bool opt) const { |
2086 const intptr_t kNumInputs = 2; | 2104 const intptr_t kNumInputs = 2; |
2087 const intptr_t kNumTemps = | 2105 const intptr_t kNumTemps = |
2088 (IsUnboxedStore() && opt) ? 2 : | 2106 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); |
2089 ((IsPotentialUnboxedStore()) ? 3 : 0); | 2107 LocationSummary* summary = new (zone) |
2090 LocationSummary* summary = new(zone) LocationSummary( | 2108 LocationSummary(zone, kNumInputs, kNumTemps, |
2091 zone, kNumInputs, kNumTemps, | 2109 ((IsUnboxedStore() && opt && is_initialization()) || |
2092 ((IsUnboxedStore() && opt && is_initialization()) || | 2110 IsPotentialUnboxedStore()) |
2093 IsPotentialUnboxedStore()) | 2111 ? LocationSummary::kCallOnSlowPath |
2094 ? LocationSummary::kCallOnSlowPath | 2112 : LocationSummary::kNoCall); |
2095 : LocationSummary::kNoCall); | |
2096 | 2113 |
2097 summary->set_in(0, Location::RequiresRegister()); | 2114 summary->set_in(0, Location::RequiresRegister()); |
2098 if (IsUnboxedStore() && opt) { | 2115 if (IsUnboxedStore() && opt) { |
2099 summary->set_in(1, Location::RequiresFpuRegister()); | 2116 summary->set_in(1, Location::RequiresFpuRegister()); |
2100 summary->set_temp(0, Location::RequiresRegister()); | 2117 summary->set_temp(0, Location::RequiresRegister()); |
2101 summary->set_temp(1, Location::RequiresRegister()); | 2118 summary->set_temp(1, Location::RequiresRegister()); |
2102 } else if (IsPotentialUnboxedStore()) { | 2119 } else if (IsPotentialUnboxedStore()) { |
2103 summary->set_in(1, ShouldEmitStoreBarrier() | 2120 summary->set_in(1, ShouldEmitStoreBarrier() ? Location::WritableRegister() |
2104 ? Location::WritableRegister() | 2121 : Location::RequiresRegister()); |
2105 : Location::RequiresRegister()); | |
2106 summary->set_temp(0, Location::RequiresRegister()); | 2122 summary->set_temp(0, Location::RequiresRegister()); |
2107 summary->set_temp(1, Location::RequiresRegister()); | 2123 summary->set_temp(1, Location::RequiresRegister()); |
2108 summary->set_temp(2, opt ? Location::RequiresFpuRegister() | 2124 summary->set_temp(2, opt ? Location::RequiresFpuRegister() |
2109 : Location::FpuRegisterLocation(Q1)); | 2125 : Location::FpuRegisterLocation(Q1)); |
2110 } else { | 2126 } else { |
2111 summary->set_in(1, ShouldEmitStoreBarrier() | 2127 summary->set_in(1, ShouldEmitStoreBarrier() |
2112 ? Location::WritableRegister() | 2128 ? Location::WritableRegister() |
2113 : Location::RegisterOrConstant(value())); | 2129 : Location::RegisterOrConstant(value())); |
2114 } | 2130 } |
2115 return summary; | 2131 return summary; |
2116 } | 2132 } |
2117 | 2133 |
2118 | 2134 |
2119 static void EnsureMutableBox(FlowGraphCompiler* compiler, | 2135 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
2120 StoreInstanceFieldInstr* instruction, | 2136 StoreInstanceFieldInstr* instruction, |
2121 Register box_reg, | 2137 Register box_reg, |
2122 const Class& cls, | 2138 const Class& cls, |
2123 Register instance_reg, | 2139 Register instance_reg, |
2124 intptr_t offset, | 2140 intptr_t offset, |
2125 Register temp) { | 2141 Register temp) { |
2126 Label done; | 2142 Label done; |
2127 __ ldr(box_reg, FieldAddress(instance_reg, offset)); | 2143 __ ldr(box_reg, FieldAddress(instance_reg, offset)); |
2128 __ CompareObject(box_reg, Object::null_object()); | 2144 __ CompareObject(box_reg, Object::null_object()); |
2129 __ b(&done, NE); | 2145 __ b(&done, NE); |
2130 | 2146 |
2131 BoxAllocationSlowPath::Allocate( | 2147 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); |
2132 compiler, instruction, cls, box_reg, temp); | |
2133 | 2148 |
2134 __ MoveRegister(temp, box_reg); | 2149 __ MoveRegister(temp, box_reg); |
2135 __ StoreIntoObjectOffset(instance_reg, offset, temp); | 2150 __ StoreIntoObjectOffset(instance_reg, offset, temp); |
2136 __ Bind(&done); | 2151 __ Bind(&done); |
2137 } | 2152 } |
2138 | 2153 |
2139 | 2154 |
2140 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2155 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2141 ASSERT(sizeof(classid_t) == kInt16Size); | 2156 ASSERT(sizeof(classid_t) == kInt16Size); |
2142 | 2157 |
(...skipping 16 matching lines...) Expand all Loading... |
2159 case kFloat32x4Cid: | 2174 case kFloat32x4Cid: |
2160 cls = &compiler->float32x4_class(); | 2175 cls = &compiler->float32x4_class(); |
2161 break; | 2176 break; |
2162 case kFloat64x2Cid: | 2177 case kFloat64x2Cid: |
2163 cls = &compiler->float64x2_class(); | 2178 cls = &compiler->float64x2_class(); |
2164 break; | 2179 break; |
2165 default: | 2180 default: |
2166 UNREACHABLE(); | 2181 UNREACHABLE(); |
2167 } | 2182 } |
2168 | 2183 |
2169 BoxAllocationSlowPath::Allocate( | 2184 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2); |
2170 compiler, this, *cls, temp, temp2); | |
2171 __ MoveRegister(temp2, temp); | 2185 __ MoveRegister(temp2, temp); |
2172 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2); | 2186 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2); |
2173 } else { | 2187 } else { |
2174 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes_)); | 2188 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes_)); |
2175 } | 2189 } |
2176 switch (cid) { | 2190 switch (cid) { |
2177 case kDoubleCid: | 2191 case kDoubleCid: |
2178 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); | 2192 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); |
2179 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); | 2193 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
2180 break; | 2194 break; |
2181 case kFloat32x4Cid: | 2195 case kFloat32x4Cid: |
2182 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr"); | 2196 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr"); |
2183 __ StoreMultipleDToOffset(value, 2, temp, | 2197 __ StoreMultipleDToOffset(value, 2, temp, |
2184 Float32x4::value_offset() - kHeapObjectTag); | 2198 Float32x4::value_offset() - kHeapObjectTag); |
2185 break; | 2199 break; |
2186 case kFloat64x2Cid: | 2200 case kFloat64x2Cid: |
2187 __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr"); | 2201 __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr"); |
2188 __ StoreMultipleDToOffset(value, 2, temp, | 2202 __ StoreMultipleDToOffset(value, 2, temp, |
2189 Float64x2::value_offset() - kHeapObjectTag); | 2203 Float64x2::value_offset() - kHeapObjectTag); |
2190 break; | 2204 break; |
2191 default: | 2205 default: |
2192 UNREACHABLE(); | 2206 UNREACHABLE(); |
2193 } | 2207 } |
2194 | 2208 |
2195 return; | 2209 return; |
2196 } | 2210 } |
2197 | 2211 |
2198 if (IsPotentialUnboxedStore()) { | 2212 if (IsPotentialUnboxedStore()) { |
2199 const Register value_reg = locs()->in(1).reg(); | 2213 const Register value_reg = locs()->in(1).reg(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2231 __ b(&store_float32x4, EQ); | 2245 __ b(&store_float32x4, EQ); |
2232 | 2246 |
2233 __ ldrh(temp2, FieldAddress(temp, Field::guarded_cid_offset())); | 2247 __ ldrh(temp2, FieldAddress(temp, Field::guarded_cid_offset())); |
2234 __ CompareImmediate(temp2, kFloat64x2Cid); | 2248 __ CompareImmediate(temp2, kFloat64x2Cid); |
2235 __ b(&store_float64x2, EQ); | 2249 __ b(&store_float64x2, EQ); |
2236 | 2250 |
2237 // Fall through. | 2251 // Fall through. |
2238 __ b(&store_pointer); | 2252 __ b(&store_pointer); |
2239 | 2253 |
2240 if (!compiler->is_optimizing()) { | 2254 if (!compiler->is_optimizing()) { |
2241 locs()->live_registers()->Add(locs()->in(0)); | 2255 locs()->live_registers()->Add(locs()->in(0)); |
2242 locs()->live_registers()->Add(locs()->in(1)); | 2256 locs()->live_registers()->Add(locs()->in(1)); |
2243 } | 2257 } |
2244 | 2258 |
2245 { | 2259 { |
2246 __ Bind(&store_double); | 2260 __ Bind(&store_double); |
2247 EnsureMutableBox(compiler, | 2261 EnsureMutableBox(compiler, this, temp, compiler->double_class(), |
2248 this, | 2262 instance_reg, offset_in_bytes_, temp2); |
2249 temp, | |
2250 compiler->double_class(), | |
2251 instance_reg, | |
2252 offset_in_bytes_, | |
2253 temp2); | |
2254 __ CopyDoubleField(temp, value_reg, TMP, temp2, fpu_temp); | 2263 __ CopyDoubleField(temp, value_reg, TMP, temp2, fpu_temp); |
2255 __ b(&skip_store); | 2264 __ b(&skip_store); |
2256 } | 2265 } |
2257 | 2266 |
2258 { | 2267 { |
2259 __ Bind(&store_float32x4); | 2268 __ Bind(&store_float32x4); |
2260 EnsureMutableBox(compiler, | 2269 EnsureMutableBox(compiler, this, temp, compiler->float32x4_class(), |
2261 this, | 2270 instance_reg, offset_in_bytes_, temp2); |
2262 temp, | |
2263 compiler->float32x4_class(), | |
2264 instance_reg, | |
2265 offset_in_bytes_, | |
2266 temp2); | |
2267 __ CopyFloat32x4Field(temp, value_reg, TMP, temp2, fpu_temp); | 2271 __ CopyFloat32x4Field(temp, value_reg, TMP, temp2, fpu_temp); |
2268 __ b(&skip_store); | 2272 __ b(&skip_store); |
2269 } | 2273 } |
2270 | 2274 |
2271 { | 2275 { |
2272 __ Bind(&store_float64x2); | 2276 __ Bind(&store_float64x2); |
2273 EnsureMutableBox(compiler, | 2277 EnsureMutableBox(compiler, this, temp, compiler->float64x2_class(), |
2274 this, | 2278 instance_reg, offset_in_bytes_, temp2); |
2275 temp, | |
2276 compiler->float64x2_class(), | |
2277 instance_reg, | |
2278 offset_in_bytes_, | |
2279 temp2); | |
2280 __ CopyFloat64x2Field(temp, value_reg, TMP, temp2, fpu_temp); | 2279 __ CopyFloat64x2Field(temp, value_reg, TMP, temp2, fpu_temp); |
2281 __ b(&skip_store); | 2280 __ b(&skip_store); |
2282 } | 2281 } |
2283 | 2282 |
2284 __ Bind(&store_pointer); | 2283 __ Bind(&store_pointer); |
2285 } | 2284 } |
2286 | 2285 |
2287 if (ShouldEmitStoreBarrier()) { | 2286 if (ShouldEmitStoreBarrier()) { |
2288 const Register value_reg = locs()->in(1).reg(); | 2287 const Register value_reg = locs()->in(1).reg(); |
2289 __ StoreIntoObjectOffset(instance_reg, | 2288 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, value_reg, |
2290 offset_in_bytes_, | |
2291 value_reg, | |
2292 CanValueBeSmi()); | 2289 CanValueBeSmi()); |
2293 } else { | 2290 } else { |
2294 if (locs()->in(1).IsConstant()) { | 2291 if (locs()->in(1).IsConstant()) { |
2295 __ StoreIntoObjectNoBarrierOffset(instance_reg, | 2292 __ StoreIntoObjectNoBarrierOffset(instance_reg, offset_in_bytes_, |
2296 offset_in_bytes_, | |
2297 locs()->in(1).constant()); | 2293 locs()->in(1).constant()); |
2298 } else { | 2294 } else { |
2299 const Register value_reg = locs()->in(1).reg(); | 2295 const Register value_reg = locs()->in(1).reg(); |
2300 __ StoreIntoObjectNoBarrierOffset(instance_reg, | 2296 __ StoreIntoObjectNoBarrierOffset(instance_reg, offset_in_bytes_, |
2301 offset_in_bytes_, | |
2302 value_reg); | 2297 value_reg); |
2303 } | 2298 } |
2304 } | 2299 } |
2305 __ Bind(&skip_store); | 2300 __ Bind(&skip_store); |
2306 } | 2301 } |
2307 | 2302 |
2308 | 2303 |
2309 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2304 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |
2310 bool opt) const { | 2305 bool opt) const { |
2311 const intptr_t kNumInputs = 1; | 2306 const intptr_t kNumInputs = 1; |
2312 const intptr_t kNumTemps = 0; | 2307 const intptr_t kNumTemps = 0; |
2313 LocationSummary* summary = new(zone) LocationSummary( | 2308 LocationSummary* summary = new (zone) |
2314 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2309 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2315 summary->set_in(0, Location::RequiresRegister()); | 2310 summary->set_in(0, Location::RequiresRegister()); |
2316 summary->set_out(0, Location::RequiresRegister()); | 2311 summary->set_out(0, Location::RequiresRegister()); |
2317 return summary; | 2312 return summary; |
2318 } | 2313 } |
2319 | 2314 |
2320 | 2315 |
2321 // When the parser is building an implicit static getter for optimization, | 2316 // When the parser is building an implicit static getter for optimization, |
2322 // it can generate a function body where deoptimization ids do not line up | 2317 // it can generate a function body where deoptimization ids do not line up |
2323 // with the unoptimized code. | 2318 // with the unoptimized code. |
2324 // | 2319 // |
2325 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 2320 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
2326 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2321 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2327 const Register field = locs()->in(0).reg(); | 2322 const Register field = locs()->in(0).reg(); |
2328 const Register result = locs()->out(0).reg(); | 2323 const Register result = locs()->out(0).reg(); |
2329 __ LoadFieldFromOffset(kWord, result, field, Field::static_value_offset()); | 2324 __ LoadFieldFromOffset(kWord, result, field, Field::static_value_offset()); |
2330 } | 2325 } |
2331 | 2326 |
2332 | 2327 |
2333 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2328 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |
2334 bool opt) const { | 2329 bool opt) const { |
2335 LocationSummary* locs = new(zone) LocationSummary( | 2330 LocationSummary* locs = |
2336 zone, 1, 1, LocationSummary::kNoCall); | 2331 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); |
2337 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 2332 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
2338 : Location::RequiresRegister()); | 2333 : Location::RequiresRegister()); |
2339 locs->set_temp(0, Location::RequiresRegister()); | 2334 locs->set_temp(0, Location::RequiresRegister()); |
2340 return locs; | 2335 return locs; |
2341 } | 2336 } |
2342 | 2337 |
2343 | 2338 |
2344 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2339 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2345 const Register value = locs()->in(0).reg(); | 2340 const Register value = locs()->in(0).reg(); |
2346 const Register temp = locs()->temp(0).reg(); | 2341 const Register temp = locs()->temp(0).reg(); |
2347 | 2342 |
2348 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 2343 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
2349 if (this->value()->NeedsStoreBuffer()) { | 2344 if (this->value()->NeedsStoreBuffer()) { |
2350 __ StoreIntoObject(temp, | 2345 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), |
2351 FieldAddress(temp, Field::static_value_offset()), | 2346 value, CanValueBeSmi()); |
2352 value, | |
2353 CanValueBeSmi()); | |
2354 } else { | 2347 } else { |
2355 __ StoreIntoObjectNoBarrier( | 2348 __ StoreIntoObjectNoBarrier( |
2356 temp, FieldAddress(temp, Field::static_value_offset()), value); | 2349 temp, FieldAddress(temp, Field::static_value_offset()), value); |
2357 } | 2350 } |
2358 } | 2351 } |
2359 | 2352 |
2360 | 2353 |
2361 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 2354 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
2362 bool opt) const { | 2355 bool opt) const { |
2363 const intptr_t kNumInputs = 2; | 2356 const intptr_t kNumInputs = 2; |
2364 const intptr_t kNumTemps = 0; | 2357 const intptr_t kNumTemps = 0; |
2365 LocationSummary* summary = new(zone) LocationSummary( | 2358 LocationSummary* summary = new (zone) |
2366 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2359 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2367 summary->set_in(0, Location::RegisterLocation(R0)); | 2360 summary->set_in(0, Location::RegisterLocation(R0)); |
2368 summary->set_in(1, Location::RegisterLocation(R1)); | 2361 summary->set_in(1, Location::RegisterLocation(R1)); |
2369 summary->set_out(0, Location::RegisterLocation(R0)); | 2362 summary->set_out(0, Location::RegisterLocation(R0)); |
2370 return summary; | 2363 return summary; |
2371 } | 2364 } |
2372 | 2365 |
2373 | 2366 |
2374 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2367 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2375 ASSERT(locs()->in(0).reg() == R0); // Value. | 2368 ASSERT(locs()->in(0).reg() == R0); // Value. |
2376 ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments. | 2369 ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments. |
2377 | 2370 |
2378 compiler->GenerateInstanceOf(token_pos(), | 2371 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), negate_result(), |
2379 deopt_id(), | |
2380 type(), | |
2381 negate_result(), | |
2382 locs()); | 2372 locs()); |
2383 ASSERT(locs()->out(0).reg() == R0); | 2373 ASSERT(locs()->out(0).reg() == R0); |
2384 } | 2374 } |
2385 | 2375 |
2386 | 2376 |
2387 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 2377 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
2388 bool opt) const { | 2378 bool opt) const { |
2389 const intptr_t kNumInputs = 2; | 2379 const intptr_t kNumInputs = 2; |
2390 const intptr_t kNumTemps = 0; | 2380 const intptr_t kNumTemps = 0; |
2391 LocationSummary* locs = new(zone) LocationSummary( | 2381 LocationSummary* locs = new (zone) |
2392 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2382 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2393 locs->set_in(kElementTypePos, Location::RegisterLocation(R1)); | 2383 locs->set_in(kElementTypePos, Location::RegisterLocation(R1)); |
2394 locs->set_in(kLengthPos, Location::RegisterLocation(R2)); | 2384 locs->set_in(kLengthPos, Location::RegisterLocation(R2)); |
2395 locs->set_out(0, Location::RegisterLocation(R0)); | 2385 locs->set_out(0, Location::RegisterLocation(R0)); |
2396 return locs; | 2386 return locs; |
2397 } | 2387 } |
2398 | 2388 |
2399 | 2389 |
2400 // Inlines array allocation for known constant values. | 2390 // Inlines array allocation for known constant values. |
2401 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 2391 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
2402 intptr_t num_elements, | 2392 intptr_t num_elements, |
2403 Label* slow_path, | 2393 Label* slow_path, |
2404 Label* done) { | 2394 Label* done) { |
2405 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. | 2395 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. |
2406 const Register kLengthReg = R2; | 2396 const Register kLengthReg = R2; |
2407 const Register kElemTypeReg = R1; | 2397 const Register kElemTypeReg = R1; |
2408 const intptr_t instance_size = Array::InstanceSize(num_elements); | 2398 const intptr_t instance_size = Array::InstanceSize(num_elements); |
2409 | 2399 |
2410 __ TryAllocateArray(kArrayCid, instance_size, slow_path, | 2400 __ TryAllocateArray(kArrayCid, instance_size, slow_path, |
2411 R0, // instance | 2401 R0, // instance |
2412 R3, // end address | 2402 R3, // end address |
2413 R8, | 2403 R8, R6); |
2414 R6); | |
2415 // R0: new object start as a tagged pointer. | 2404 // R0: new object start as a tagged pointer. |
2416 // R3: new object end address. | 2405 // R3: new object end address. |
2417 | 2406 |
2418 // Store the type argument field. | 2407 // Store the type argument field. |
2419 __ StoreIntoObjectNoBarrier(R0, | 2408 __ StoreIntoObjectNoBarrier( |
2420 FieldAddress(R0, Array::type_arguments_offset()), | 2409 R0, FieldAddress(R0, Array::type_arguments_offset()), kElemTypeReg); |
2421 kElemTypeReg); | |
2422 | 2410 |
2423 // Set the length field. | 2411 // Set the length field. |
2424 __ StoreIntoObjectNoBarrier(R0, | 2412 __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, Array::length_offset()), |
2425 FieldAddress(R0, Array::length_offset()), | |
2426 kLengthReg); | 2413 kLengthReg); |
2427 | 2414 |
2428 // Initialize all array elements to raw_null. | 2415 // Initialize all array elements to raw_null. |
2429 // R0: new object start as a tagged pointer. | 2416 // R0: new object start as a tagged pointer. |
2430 // R3: new object end address. | 2417 // R3: new object end address. |
2431 // R6: iterator which initially points to the start of the variable | 2418 // R6: iterator which initially points to the start of the variable |
2432 // data area to be initialized. | 2419 // data area to be initialized. |
2433 // R8: null | 2420 // R8: null |
2434 if (num_elements > 0) { | 2421 if (num_elements > 0) { |
2435 const intptr_t array_size = instance_size - sizeof(RawArray); | 2422 const intptr_t array_size = instance_size - sizeof(RawArray); |
(...skipping 19 matching lines...) Expand all Loading... |
2455 | 2442 |
2456 | 2443 |
2457 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2444 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2458 const Register kLengthReg = R2; | 2445 const Register kLengthReg = R2; |
2459 const Register kElemTypeReg = R1; | 2446 const Register kElemTypeReg = R1; |
2460 const Register kResultReg = R0; | 2447 const Register kResultReg = R0; |
2461 | 2448 |
2462 ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg); | 2449 ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg); |
2463 ASSERT(locs()->in(kLengthPos).reg() == kLengthReg); | 2450 ASSERT(locs()->in(kLengthPos).reg() == kLengthReg); |
2464 | 2451 |
2465 if (compiler->is_optimizing() && | 2452 if (compiler->is_optimizing() && !FLAG_precompiled_mode && |
2466 !FLAG_precompiled_mode && | |
2467 num_elements()->BindsToConstant() && | 2453 num_elements()->BindsToConstant() && |
2468 num_elements()->BoundConstant().IsSmi()) { | 2454 num_elements()->BoundConstant().IsSmi()) { |
2469 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); | 2455 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); |
2470 if ((length >= 0) && (length <= Array::kMaxElements)) { | 2456 if ((length >= 0) && (length <= Array::kMaxElements)) { |
2471 Label slow_path, done; | 2457 Label slow_path, done; |
2472 InlineArrayAllocation(compiler, length, &slow_path, &done); | 2458 InlineArrayAllocation(compiler, length, &slow_path, &done); |
2473 __ Bind(&slow_path); | 2459 __ Bind(&slow_path); |
2474 __ PushObject(Object::null_object()); // Make room for the result. | 2460 __ PushObject(Object::null_object()); // Make room for the result. |
2475 __ Push(kLengthReg); // length. | 2461 __ Push(kLengthReg); // length. |
2476 __ Push(kElemTypeReg); | 2462 __ Push(kElemTypeReg); |
2477 compiler->GenerateRuntimeCall(token_pos(), | 2463 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2478 deopt_id(), | 2464 kAllocateArrayRuntimeEntry, 2, locs()); |
2479 kAllocateArrayRuntimeEntry, | |
2480 2, | |
2481 locs()); | |
2482 __ Drop(2); | 2465 __ Drop(2); |
2483 __ Pop(kResultReg); | 2466 __ Pop(kResultReg); |
2484 __ Bind(&done); | 2467 __ Bind(&done); |
2485 return; | 2468 return; |
2486 } | 2469 } |
2487 } | 2470 } |
2488 const Code& stub = Code::ZoneHandle(compiler->zone(), | 2471 const Code& stub = Code::ZoneHandle(compiler->zone(), |
2489 StubCode::AllocateArray_entry()->code()); | 2472 StubCode::AllocateArray_entry()->code()); |
2490 compiler->AddStubCallTarget(stub); | 2473 compiler->AddStubCallTarget(stub); |
2491 compiler->GenerateCall(token_pos(), | 2474 compiler->GenerateCall(token_pos(), *StubCode::AllocateArray_entry(), |
2492 *StubCode::AllocateArray_entry(), | 2475 RawPcDescriptors::kOther, locs()); |
2493 RawPcDescriptors::kOther, | |
2494 locs()); | |
2495 ASSERT(locs()->out(0).reg() == kResultReg); | 2476 ASSERT(locs()->out(0).reg() == kResultReg); |
2496 } | 2477 } |
2497 | 2478 |
2498 | 2479 |
2499 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 2480 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |
2500 bool opt) const { | 2481 bool opt) const { |
2501 const intptr_t kNumInputs = 1; | 2482 const intptr_t kNumInputs = 1; |
2502 const intptr_t kNumTemps = | 2483 const intptr_t kNumTemps = |
2503 (IsUnboxedLoad() && opt) ? 1 : | 2484 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 3 : 0); |
2504 ((IsPotentialUnboxedLoad()) ? 3 : 0); | |
2505 | 2485 |
2506 LocationSummary* locs = new(zone) LocationSummary( | 2486 LocationSummary* locs = new (zone) LocationSummary( |
2507 zone, kNumInputs, kNumTemps, | 2487 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) |
2508 (opt && !IsPotentialUnboxedLoad()) | 2488 ? LocationSummary::kNoCall |
2509 ? LocationSummary::kNoCall | 2489 : LocationSummary::kCallOnSlowPath); |
2510 : LocationSummary::kCallOnSlowPath); | |
2511 | 2490 |
2512 locs->set_in(0, Location::RequiresRegister()); | 2491 locs->set_in(0, Location::RequiresRegister()); |
2513 | 2492 |
2514 if (IsUnboxedLoad() && opt) { | 2493 if (IsUnboxedLoad() && opt) { |
2515 locs->set_temp(0, Location::RequiresRegister()); | 2494 locs->set_temp(0, Location::RequiresRegister()); |
2516 } else if (IsPotentialUnboxedLoad()) { | 2495 } else if (IsPotentialUnboxedLoad()) { |
2517 locs->set_temp(0, opt ? Location::RequiresFpuRegister() | 2496 locs->set_temp(0, opt ? Location::RequiresFpuRegister() |
2518 : Location::FpuRegisterLocation(Q1)); | 2497 : Location::FpuRegisterLocation(Q1)); |
2519 locs->set_temp(1, Location::RequiresRegister()); | 2498 locs->set_temp(1, Location::RequiresRegister()); |
2520 locs->set_temp(2, Location::RequiresRegister()); | 2499 locs->set_temp(2, Location::RequiresRegister()); |
(...skipping 14 matching lines...) Expand all Loading... |
2535 const intptr_t cid = field()->UnboxedFieldCid(); | 2514 const intptr_t cid = field()->UnboxedFieldCid(); |
2536 switch (cid) { | 2515 switch (cid) { |
2537 case kDoubleCid: | 2516 case kDoubleCid: |
2538 __ Comment("UnboxedDoubleLoadFieldInstr"); | 2517 __ Comment("UnboxedDoubleLoadFieldInstr"); |
2539 __ LoadDFromOffset(result, temp, | 2518 __ LoadDFromOffset(result, temp, |
2540 Double::value_offset() - kHeapObjectTag); | 2519 Double::value_offset() - kHeapObjectTag); |
2541 break; | 2520 break; |
2542 case kFloat32x4Cid: | 2521 case kFloat32x4Cid: |
2543 __ Comment("UnboxedFloat32x4LoadFieldInstr"); | 2522 __ Comment("UnboxedFloat32x4LoadFieldInstr"); |
2544 __ LoadMultipleDFromOffset(result, 2, temp, | 2523 __ LoadMultipleDFromOffset(result, 2, temp, |
2545 Float32x4::value_offset() - kHeapObjectTag); | 2524 Float32x4::value_offset() - kHeapObjectTag); |
2546 break; | 2525 break; |
2547 case kFloat64x2Cid: | 2526 case kFloat64x2Cid: |
2548 __ Comment("UnboxedFloat64x2LoadFieldInstr"); | 2527 __ Comment("UnboxedFloat64x2LoadFieldInstr"); |
2549 __ LoadMultipleDFromOffset(result, 2, temp, | 2528 __ LoadMultipleDFromOffset(result, 2, temp, |
2550 Float64x2::value_offset() - kHeapObjectTag); | 2529 Float64x2::value_offset() - kHeapObjectTag); |
2551 break; | 2530 break; |
2552 default: | 2531 default: |
2553 UNREACHABLE(); | 2532 UNREACHABLE(); |
2554 } | 2533 } |
2555 return; | 2534 return; |
2556 } | 2535 } |
2557 | 2536 |
2558 Label done; | 2537 Label done; |
2559 const Register result_reg = locs()->out(0).reg(); | 2538 const Register result_reg = locs()->out(0).reg(); |
2560 if (IsPotentialUnboxedLoad()) { | 2539 if (IsPotentialUnboxedLoad()) { |
(...skipping 30 matching lines...) Expand all Loading... |
2591 | 2570 |
2592 // Fall through. | 2571 // Fall through. |
2593 __ b(&load_pointer); | 2572 __ b(&load_pointer); |
2594 | 2573 |
2595 if (!compiler->is_optimizing()) { | 2574 if (!compiler->is_optimizing()) { |
2596 locs()->live_registers()->Add(locs()->in(0)); | 2575 locs()->live_registers()->Add(locs()->in(0)); |
2597 } | 2576 } |
2598 | 2577 |
2599 { | 2578 { |
2600 __ Bind(&load_double); | 2579 __ Bind(&load_double); |
2601 BoxAllocationSlowPath::Allocate( | 2580 BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(), |
2602 compiler, | 2581 result_reg, temp); |
2603 this, | |
2604 compiler->double_class(), | |
2605 result_reg, | |
2606 temp); | |
2607 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2582 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
2608 __ CopyDoubleField(result_reg, temp, TMP, temp2, value); | 2583 __ CopyDoubleField(result_reg, temp, TMP, temp2, value); |
2609 __ b(&done); | 2584 __ b(&done); |
2610 } | 2585 } |
2611 | 2586 |
2612 { | 2587 { |
2613 __ Bind(&load_float32x4); | 2588 __ Bind(&load_float32x4); |
2614 BoxAllocationSlowPath::Allocate( | 2589 BoxAllocationSlowPath::Allocate( |
2615 compiler, | 2590 compiler, this, compiler->float32x4_class(), result_reg, temp); |
2616 this, | |
2617 compiler->float32x4_class(), | |
2618 result_reg, | |
2619 temp); | |
2620 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2591 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
2621 __ CopyFloat32x4Field(result_reg, temp, TMP, temp2, value); | 2592 __ CopyFloat32x4Field(result_reg, temp, TMP, temp2, value); |
2622 __ b(&done); | 2593 __ b(&done); |
2623 } | 2594 } |
2624 | 2595 |
2625 { | 2596 { |
2626 __ Bind(&load_float64x2); | 2597 __ Bind(&load_float64x2); |
2627 BoxAllocationSlowPath::Allocate( | 2598 BoxAllocationSlowPath::Allocate( |
2628 compiler, | 2599 compiler, this, compiler->float64x2_class(), result_reg, temp); |
2629 this, | |
2630 compiler->float64x2_class(), | |
2631 result_reg, | |
2632 temp); | |
2633 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2600 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
2634 __ CopyFloat64x2Field(result_reg, temp, TMP, temp2, value); | 2601 __ CopyFloat64x2Field(result_reg, temp, TMP, temp2, value); |
2635 __ b(&done); | 2602 __ b(&done); |
2636 } | 2603 } |
2637 | 2604 |
2638 __ Bind(&load_pointer); | 2605 __ Bind(&load_pointer); |
2639 } | 2606 } |
2640 __ LoadFieldFromOffset(kWord, result_reg, instance_reg, offset_in_bytes()); | 2607 __ LoadFieldFromOffset(kWord, result_reg, instance_reg, offset_in_bytes()); |
2641 __ Bind(&done); | 2608 __ Bind(&done); |
2642 } | 2609 } |
2643 | 2610 |
2644 | 2611 |
2645 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2612 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
2646 bool opt) const { | 2613 bool opt) const { |
2647 const intptr_t kNumInputs = 1; | 2614 const intptr_t kNumInputs = 1; |
2648 const intptr_t kNumTemps = 0; | 2615 const intptr_t kNumTemps = 0; |
2649 LocationSummary* locs = new(zone) LocationSummary( | 2616 LocationSummary* locs = new (zone) |
2650 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2617 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2651 locs->set_in(0, Location::RegisterLocation(R0)); | 2618 locs->set_in(0, Location::RegisterLocation(R0)); |
2652 locs->set_out(0, Location::RegisterLocation(R0)); | 2619 locs->set_out(0, Location::RegisterLocation(R0)); |
2653 return locs; | 2620 return locs; |
2654 } | 2621 } |
2655 | 2622 |
2656 | 2623 |
2657 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2624 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2658 const Register instantiator_reg = locs()->in(0).reg(); | 2625 const Register instantiator_reg = locs()->in(0).reg(); |
2659 const Register result_reg = locs()->out(0).reg(); | 2626 const Register result_reg = locs()->out(0).reg(); |
2660 | 2627 |
2661 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2628 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
2662 // A runtime call to instantiate the type is required. | 2629 // A runtime call to instantiate the type is required. |
2663 __ PushObject(Object::null_object()); // Make room for the result. | 2630 __ PushObject(Object::null_object()); // Make room for the result. |
2664 __ PushObject(type()); | 2631 __ PushObject(type()); |
2665 __ Push(instantiator_reg); // Push instantiator type arguments. | 2632 __ Push(instantiator_reg); // Push instantiator type arguments. |
2666 compiler->GenerateRuntimeCall(token_pos(), | 2633 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2667 deopt_id(), | 2634 kInstantiateTypeRuntimeEntry, 2, locs()); |
2668 kInstantiateTypeRuntimeEntry, | 2635 __ Drop(2); // Drop instantiator and uninstantiated type. |
2669 2, | |
2670 locs()); | |
2671 __ Drop(2); // Drop instantiator and uninstantiated type. | |
2672 __ Pop(result_reg); // Pop instantiated type. | 2636 __ Pop(result_reg); // Pop instantiated type. |
2673 ASSERT(instantiator_reg == result_reg); | 2637 ASSERT(instantiator_reg == result_reg); |
2674 } | 2638 } |
2675 | 2639 |
2676 | 2640 |
2677 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2641 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
2678 Zone* zone, bool opt) const { | 2642 Zone* zone, |
| 2643 bool opt) const { |
2679 const intptr_t kNumInputs = 1; | 2644 const intptr_t kNumInputs = 1; |
2680 const intptr_t kNumTemps = 0; | 2645 const intptr_t kNumTemps = 0; |
2681 LocationSummary* locs = new(zone) LocationSummary( | 2646 LocationSummary* locs = new (zone) |
2682 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2647 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2683 locs->set_in(0, Location::RegisterLocation(R0)); | 2648 locs->set_in(0, Location::RegisterLocation(R0)); |
2684 locs->set_out(0, Location::RegisterLocation(R0)); | 2649 locs->set_out(0, Location::RegisterLocation(R0)); |
2685 return locs; | 2650 return locs; |
2686 } | 2651 } |
2687 | 2652 |
2688 | 2653 |
2689 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2654 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
2690 FlowGraphCompiler* compiler) { | 2655 FlowGraphCompiler* compiler) { |
2691 const Register instantiator_reg = locs()->in(0).reg(); | 2656 const Register instantiator_reg = locs()->in(0).reg(); |
2692 const Register result_reg = locs()->out(0).reg(); | 2657 const Register result_reg = locs()->out(0).reg(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2725 __ Bind(&found); | 2690 __ Bind(&found); |
2726 __ ldr(R0, Address(R2, 1 * kWordSize)); // Cached instantiated args. | 2691 __ ldr(R0, Address(R2, 1 * kWordSize)); // Cached instantiated args. |
2727 __ b(&type_arguments_instantiated); | 2692 __ b(&type_arguments_instantiated); |
2728 | 2693 |
2729 __ Bind(&slow_case); | 2694 __ Bind(&slow_case); |
2730 // Instantiate non-null type arguments. | 2695 // Instantiate non-null type arguments. |
2731 // A runtime call to instantiate the type arguments is required. | 2696 // A runtime call to instantiate the type arguments is required. |
2732 __ PushObject(Object::null_object()); // Make room for the result. | 2697 __ PushObject(Object::null_object()); // Make room for the result. |
2733 __ PushObject(type_arguments()); | 2698 __ PushObject(type_arguments()); |
2734 __ Push(instantiator_reg); // Push instantiator type arguments. | 2699 __ Push(instantiator_reg); // Push instantiator type arguments. |
2735 compiler->GenerateRuntimeCall(token_pos(), | 2700 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2736 deopt_id(), | 2701 kInstantiateTypeArgumentsRuntimeEntry, 2, |
2737 kInstantiateTypeArgumentsRuntimeEntry, | |
2738 2, | |
2739 locs()); | 2702 locs()); |
2740 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 2703 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
2741 __ Pop(result_reg); // Pop instantiated type arguments. | 2704 __ Pop(result_reg); // Pop instantiated type arguments. |
2742 __ Bind(&type_arguments_instantiated); | 2705 __ Bind(&type_arguments_instantiated); |
2743 } | 2706 } |
2744 | 2707 |
2745 | 2708 |
2746 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2709 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
2747 Zone* zone, | 2710 Zone* zone, |
2748 bool opt) const { | 2711 bool opt) const { |
2749 ASSERT(opt); | 2712 ASSERT(opt); |
2750 const intptr_t kNumInputs = 0; | 2713 const intptr_t kNumInputs = 0; |
2751 const intptr_t kNumTemps = 3; | 2714 const intptr_t kNumTemps = 3; |
2752 LocationSummary* locs = new(zone) LocationSummary( | 2715 LocationSummary* locs = new (zone) LocationSummary( |
2753 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2716 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2754 locs->set_temp(0, Location::RegisterLocation(R1)); | 2717 locs->set_temp(0, Location::RegisterLocation(R1)); |
2755 locs->set_temp(1, Location::RegisterLocation(R2)); | 2718 locs->set_temp(1, Location::RegisterLocation(R2)); |
2756 locs->set_temp(2, Location::RegisterLocation(R3)); | 2719 locs->set_temp(2, Location::RegisterLocation(R3)); |
2757 locs->set_out(0, Location::RegisterLocation(R0)); | 2720 locs->set_out(0, Location::RegisterLocation(R0)); |
2758 return locs; | 2721 return locs; |
2759 } | 2722 } |
2760 | 2723 |
2761 | 2724 |
2762 class AllocateContextSlowPath : public SlowPathCode { | 2725 class AllocateContextSlowPath : public SlowPathCode { |
2763 public: | 2726 public: |
2764 explicit AllocateContextSlowPath( | 2727 explicit AllocateContextSlowPath( |
2765 AllocateUninitializedContextInstr* instruction) | 2728 AllocateUninitializedContextInstr* instruction) |
2766 : instruction_(instruction) { } | 2729 : instruction_(instruction) {} |
2767 | 2730 |
2768 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2731 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2769 __ Comment("AllocateContextSlowPath"); | 2732 __ Comment("AllocateContextSlowPath"); |
2770 __ Bind(entry_label()); | 2733 __ Bind(entry_label()); |
2771 | 2734 |
2772 LocationSummary* locs = instruction_->locs(); | 2735 LocationSummary* locs = instruction_->locs(); |
2773 locs->live_registers()->Remove(locs->out(0)); | 2736 locs->live_registers()->Remove(locs->out(0)); |
2774 | 2737 |
2775 compiler->SaveLiveRegisters(locs); | 2738 compiler->SaveLiveRegisters(locs); |
2776 | 2739 |
2777 __ LoadImmediate(R1, instruction_->num_context_variables()); | 2740 __ LoadImmediate(R1, instruction_->num_context_variables()); |
2778 const Code& stub = Code::ZoneHandle( | 2741 const Code& stub = Code::ZoneHandle( |
2779 compiler->zone(), StubCode::AllocateContext_entry()->code()); | 2742 compiler->zone(), StubCode::AllocateContext_entry()->code()); |
2780 compiler->AddStubCallTarget(stub); | 2743 compiler->AddStubCallTarget(stub); |
2781 compiler->GenerateCall(instruction_->token_pos(), | 2744 compiler->GenerateCall(instruction_->token_pos(), |
2782 *StubCode::AllocateContext_entry(), | 2745 *StubCode::AllocateContext_entry(), |
2783 RawPcDescriptors::kOther, | 2746 RawPcDescriptors::kOther, locs); |
2784 locs); | |
2785 ASSERT(instruction_->locs()->out(0).reg() == R0); | 2747 ASSERT(instruction_->locs()->out(0).reg() == R0); |
2786 compiler->RestoreLiveRegisters(instruction_->locs()); | 2748 compiler->RestoreLiveRegisters(instruction_->locs()); |
2787 __ b(exit_label()); | 2749 __ b(exit_label()); |
2788 } | 2750 } |
2789 | 2751 |
2790 private: | 2752 private: |
2791 AllocateUninitializedContextInstr* instruction_; | 2753 AllocateUninitializedContextInstr* instruction_; |
2792 }; | 2754 }; |
2793 | 2755 |
2794 | 2756 |
2795 void AllocateUninitializedContextInstr::EmitNativeCode( | 2757 void AllocateUninitializedContextInstr::EmitNativeCode( |
2796 FlowGraphCompiler* compiler) { | 2758 FlowGraphCompiler* compiler) { |
2797 Register temp0 = locs()->temp(0).reg(); | 2759 Register temp0 = locs()->temp(0).reg(); |
2798 Register temp1 = locs()->temp(1).reg(); | 2760 Register temp1 = locs()->temp(1).reg(); |
2799 Register temp2 = locs()->temp(2).reg(); | 2761 Register temp2 = locs()->temp(2).reg(); |
2800 Register result = locs()->out(0).reg(); | 2762 Register result = locs()->out(0).reg(); |
2801 // Try allocate the object. | 2763 // Try allocate the object. |
2802 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2764 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
2803 compiler->AddSlowPathCode(slow_path); | 2765 compiler->AddSlowPathCode(slow_path); |
2804 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2766 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
2805 | 2767 |
2806 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 2768 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
2807 result, // instance | 2769 result, // instance |
2808 temp0, | 2770 temp0, temp1, temp2); |
2809 temp1, | |
2810 temp2); | |
2811 | 2771 |
2812 // Setup up number of context variables field. | 2772 // Setup up number of context variables field. |
2813 __ LoadImmediate(temp0, num_context_variables()); | 2773 __ LoadImmediate(temp0, num_context_variables()); |
2814 __ str(temp0, FieldAddress(result, Context::num_variables_offset())); | 2774 __ str(temp0, FieldAddress(result, Context::num_variables_offset())); |
2815 | 2775 |
2816 __ Bind(slow_path->exit_label()); | 2776 __ Bind(slow_path->exit_label()); |
2817 } | 2777 } |
2818 | 2778 |
2819 | 2779 |
2820 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 2780 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |
2821 bool opt) const { | 2781 bool opt) const { |
2822 const intptr_t kNumInputs = 0; | 2782 const intptr_t kNumInputs = 0; |
2823 const intptr_t kNumTemps = 1; | 2783 const intptr_t kNumTemps = 1; |
2824 LocationSummary* locs = new(zone) LocationSummary( | 2784 LocationSummary* locs = new (zone) |
2825 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2785 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2826 locs->set_temp(0, Location::RegisterLocation(R1)); | 2786 locs->set_temp(0, Location::RegisterLocation(R1)); |
2827 locs->set_out(0, Location::RegisterLocation(R0)); | 2787 locs->set_out(0, Location::RegisterLocation(R0)); |
2828 return locs; | 2788 return locs; |
2829 } | 2789 } |
2830 | 2790 |
2831 | 2791 |
2832 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2792 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2833 ASSERT(locs()->temp(0).reg() == R1); | 2793 ASSERT(locs()->temp(0).reg() == R1); |
2834 ASSERT(locs()->out(0).reg() == R0); | 2794 ASSERT(locs()->out(0).reg() == R0); |
2835 | 2795 |
2836 __ LoadImmediate(R1, num_context_variables()); | 2796 __ LoadImmediate(R1, num_context_variables()); |
2837 compiler->GenerateCall(token_pos(), | 2797 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), |
2838 *StubCode::AllocateContext_entry(), | 2798 RawPcDescriptors::kOther, locs()); |
2839 RawPcDescriptors::kOther, | |
2840 locs()); | |
2841 } | 2799 } |
2842 | 2800 |
2843 | 2801 |
2844 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2802 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
2845 bool opt) const { | 2803 bool opt) const { |
2846 const intptr_t kNumInputs = 1; | 2804 const intptr_t kNumInputs = 1; |
2847 const intptr_t kNumTemps = 1; | 2805 const intptr_t kNumTemps = 1; |
2848 LocationSummary* locs = new(zone) LocationSummary( | 2806 LocationSummary* locs = new (zone) |
2849 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2807 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2850 locs->set_in(0, Location::RegisterLocation(R0)); | 2808 locs->set_in(0, Location::RegisterLocation(R0)); |
2851 locs->set_temp(0, Location::RegisterLocation(R1)); | 2809 locs->set_temp(0, Location::RegisterLocation(R1)); |
2852 return locs; | 2810 return locs; |
2853 } | 2811 } |
2854 | 2812 |
2855 | 2813 |
2856 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2814 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2857 Register field = locs()->in(0).reg(); | 2815 Register field = locs()->in(0).reg(); |
2858 Register temp = locs()->temp(0).reg(); | 2816 Register temp = locs()->temp(0).reg(); |
2859 Label call_runtime, no_call; | 2817 Label call_runtime, no_call; |
2860 | 2818 |
2861 __ ldr(temp, FieldAddress(field, Field::static_value_offset())); | 2819 __ ldr(temp, FieldAddress(field, Field::static_value_offset())); |
2862 __ CompareObject(temp, Object::sentinel()); | 2820 __ CompareObject(temp, Object::sentinel()); |
2863 __ b(&call_runtime, EQ); | 2821 __ b(&call_runtime, EQ); |
2864 | 2822 |
2865 __ CompareObject(temp, Object::transition_sentinel()); | 2823 __ CompareObject(temp, Object::transition_sentinel()); |
2866 __ b(&no_call, NE); | 2824 __ b(&no_call, NE); |
2867 | 2825 |
2868 __ Bind(&call_runtime); | 2826 __ Bind(&call_runtime); |
2869 __ PushObject(Object::null_object()); // Make room for (unused) result. | 2827 __ PushObject(Object::null_object()); // Make room for (unused) result. |
2870 __ Push(field); | 2828 __ Push(field); |
2871 compiler->GenerateRuntimeCall(token_pos(), | 2829 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2872 deopt_id(), | 2830 kInitStaticFieldRuntimeEntry, 1, locs()); |
2873 kInitStaticFieldRuntimeEntry, | |
2874 1, | |
2875 locs()); | |
2876 __ Drop(2); // Remove argument and result placeholder. | 2831 __ Drop(2); // Remove argument and result placeholder. |
2877 __ Bind(&no_call); | 2832 __ Bind(&no_call); |
2878 } | 2833 } |
2879 | 2834 |
2880 | 2835 |
2881 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2836 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
2882 bool opt) const { | 2837 bool opt) const { |
2883 const intptr_t kNumInputs = 1; | 2838 const intptr_t kNumInputs = 1; |
2884 const intptr_t kNumTemps = 0; | 2839 const intptr_t kNumTemps = 0; |
2885 LocationSummary* locs = new(zone) LocationSummary( | 2840 LocationSummary* locs = new (zone) |
2886 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2841 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2887 locs->set_in(0, Location::RegisterLocation(R0)); | 2842 locs->set_in(0, Location::RegisterLocation(R0)); |
2888 locs->set_out(0, Location::RegisterLocation(R0)); | 2843 locs->set_out(0, Location::RegisterLocation(R0)); |
2889 return locs; | 2844 return locs; |
2890 } | 2845 } |
2891 | 2846 |
2892 | 2847 |
2893 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2848 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2894 const Register context_value = locs()->in(0).reg(); | 2849 const Register context_value = locs()->in(0).reg(); |
2895 const Register result = locs()->out(0).reg(); | 2850 const Register result = locs()->out(0).reg(); |
2896 | 2851 |
2897 __ PushObject(Object::null_object()); // Make room for the result. | 2852 __ PushObject(Object::null_object()); // Make room for the result. |
2898 __ Push(context_value); | 2853 __ Push(context_value); |
2899 compiler->GenerateRuntimeCall(token_pos(), | 2854 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2900 deopt_id(), | 2855 kCloneContextRuntimeEntry, 1, locs()); |
2901 kCloneContextRuntimeEntry, | 2856 __ Drop(1); // Remove argument. |
2902 1, | |
2903 locs()); | |
2904 __ Drop(1); // Remove argument. | |
2905 __ Pop(result); // Get result (cloned context). | 2857 __ Pop(result); // Get result (cloned context). |
2906 } | 2858 } |
2907 | 2859 |
2908 | 2860 |
2909 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2861 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
2910 bool opt) const { | 2862 bool opt) const { |
2911 UNREACHABLE(); | 2863 UNREACHABLE(); |
2912 return NULL; | 2864 return NULL; |
2913 } | 2865 } |
2914 | 2866 |
2915 | 2867 |
2916 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2868 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2917 __ Bind(compiler->GetJumpLabel(this)); | 2869 __ Bind(compiler->GetJumpLabel(this)); |
2918 compiler->AddExceptionHandler(catch_try_index(), | 2870 compiler->AddExceptionHandler(catch_try_index(), try_index(), |
2919 try_index(), | |
2920 compiler->assembler()->CodeSize(), | 2871 compiler->assembler()->CodeSize(), |
2921 catch_handler_types_, | 2872 catch_handler_types_, needs_stacktrace()); |
2922 needs_stacktrace()); | |
2923 // On lazy deoptimization we patch the optimized code here to enter the | 2873 // On lazy deoptimization we patch the optimized code here to enter the |
2924 // deoptimization stub. | 2874 // deoptimization stub. |
2925 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 2875 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |
2926 if (compiler->is_optimizing()) { | 2876 if (compiler->is_optimizing()) { |
2927 compiler->AddDeoptIndexAtCall(deopt_id); | 2877 compiler->AddDeoptIndexAtCall(deopt_id); |
2928 } else { | 2878 } else { |
2929 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 2879 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id, |
2930 deopt_id, | |
2931 TokenPosition::kNoSource); | 2880 TokenPosition::kNoSource); |
2932 } | 2881 } |
2933 if (HasParallelMove()) { | 2882 if (HasParallelMove()) { |
2934 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2883 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
2935 } | 2884 } |
2936 | 2885 |
2937 // Restore SP from FP as we are coming from a throw and the code for | 2886 // Restore SP from FP as we are coming from a throw and the code for |
2938 // popping arguments has not been run. | 2887 // popping arguments has not been run. |
2939 const intptr_t fp_sp_dist = | 2888 const intptr_t fp_sp_dist = |
2940 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 2889 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
(...skipping 21 matching lines...) Expand all Loading... |
2962 // Initialize exception and stack trace variables. | 2911 // Initialize exception and stack trace variables. |
2963 if (exception_var().is_captured()) { | 2912 if (exception_var().is_captured()) { |
2964 ASSERT(stacktrace_var().is_captured()); | 2913 ASSERT(stacktrace_var().is_captured()); |
2965 __ StoreIntoObjectOffset(CTX, | 2914 __ StoreIntoObjectOffset(CTX, |
2966 Context::variable_offset(exception_var().index()), | 2915 Context::variable_offset(exception_var().index()), |
2967 kExceptionObjectReg); | 2916 kExceptionObjectReg); |
2968 __ StoreIntoObjectOffset(CTX, | 2917 __ StoreIntoObjectOffset(CTX, |
2969 Context::variable_offset(stacktrace_var().index()), | 2918 Context::variable_offset(stacktrace_var().index()), |
2970 kStackTraceObjectReg); | 2919 kStackTraceObjectReg); |
2971 } else { | 2920 } else { |
2972 __ StoreToOffset(kWord, kExceptionObjectReg, | 2921 __ StoreToOffset(kWord, kExceptionObjectReg, FP, |
2973 FP, exception_var().index() * kWordSize); | 2922 exception_var().index() * kWordSize); |
2974 __ StoreToOffset(kWord, kStackTraceObjectReg, | 2923 __ StoreToOffset(kWord, kStackTraceObjectReg, FP, |
2975 FP, stacktrace_var().index() * kWordSize); | 2924 stacktrace_var().index() * kWordSize); |
2976 } | 2925 } |
2977 } | 2926 } |
2978 | 2927 |
2979 | 2928 |
2980 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 2929 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |
2981 bool opt) const { | 2930 bool opt) const { |
2982 const intptr_t kNumInputs = 0; | 2931 const intptr_t kNumInputs = 0; |
2983 const intptr_t kNumTemps = 1; | 2932 const intptr_t kNumTemps = 1; |
2984 LocationSummary* summary = new(zone) LocationSummary( | 2933 LocationSummary* summary = new (zone) LocationSummary( |
2985 zone, kNumInputs, | 2934 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2986 kNumTemps, | |
2987 LocationSummary::kCallOnSlowPath); | |
2988 summary->set_temp(0, Location::RequiresRegister()); | 2935 summary->set_temp(0, Location::RequiresRegister()); |
2989 return summary; | 2936 return summary; |
2990 } | 2937 } |
2991 | 2938 |
2992 | 2939 |
2993 class CheckStackOverflowSlowPath : public SlowPathCode { | 2940 class CheckStackOverflowSlowPath : public SlowPathCode { |
2994 public: | 2941 public: |
2995 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2942 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
2996 : instruction_(instruction) { } | 2943 : instruction_(instruction) {} |
2997 | 2944 |
2998 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2945 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2999 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { | 2946 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { |
3000 const Register value = instruction_->locs()->temp(0).reg(); | 2947 const Register value = instruction_->locs()->temp(0).reg(); |
3001 __ Comment("CheckStackOverflowSlowPathOsr"); | 2948 __ Comment("CheckStackOverflowSlowPathOsr"); |
3002 __ Bind(osr_entry_label()); | 2949 __ Bind(osr_entry_label()); |
3003 __ LoadImmediate(value, Thread::kOsrRequest); | 2950 __ LoadImmediate(value, Thread::kOsrRequest); |
3004 __ str(value, Address(THR, Thread::stack_overflow_flags_offset())); | 2951 __ str(value, Address(THR, Thread::stack_overflow_flags_offset())); |
3005 } | 2952 } |
3006 __ Comment("CheckStackOverflowSlowPath"); | 2953 __ Comment("CheckStackOverflowSlowPath"); |
3007 __ Bind(entry_label()); | 2954 __ Bind(entry_label()); |
3008 compiler->SaveLiveRegisters(instruction_->locs()); | 2955 compiler->SaveLiveRegisters(instruction_->locs()); |
3009 // pending_deoptimization_env_ is needed to generate a runtime call that | 2956 // pending_deoptimization_env_ is needed to generate a runtime call that |
3010 // may throw an exception. | 2957 // may throw an exception. |
3011 ASSERT(compiler->pending_deoptimization_env_ == NULL); | 2958 ASSERT(compiler->pending_deoptimization_env_ == NULL); |
3012 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); | 2959 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |
3013 compiler->pending_deoptimization_env_ = env; | 2960 compiler->pending_deoptimization_env_ = env; |
3014 compiler->GenerateRuntimeCall(instruction_->token_pos(), | 2961 compiler->GenerateRuntimeCall( |
3015 instruction_->deopt_id(), | 2962 instruction_->token_pos(), instruction_->deopt_id(), |
3016 kStackOverflowRuntimeEntry, | 2963 kStackOverflowRuntimeEntry, 0, instruction_->locs()); |
3017 0, | |
3018 instruction_->locs()); | |
3019 | 2964 |
3020 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { | 2965 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { |
3021 // In unoptimized code, record loop stack checks as possible OSR entries. | 2966 // In unoptimized code, record loop stack checks as possible OSR entries. |
3022 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, | 2967 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, |
3023 instruction_->deopt_id(), | 2968 instruction_->deopt_id(), |
3024 TokenPosition::kNoSource); | 2969 TokenPosition::kNoSource); |
3025 } | 2970 } |
3026 compiler->pending_deoptimization_env_ = NULL; | 2971 compiler->pending_deoptimization_env_ = NULL; |
3027 compiler->RestoreLiveRegisters(instruction_->locs()); | 2972 compiler->RestoreLiveRegisters(instruction_->locs()); |
3028 __ b(exit_label()); | 2973 __ b(exit_label()); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3063 } | 3008 } |
3064 __ Bind(slow_path->exit_label()); | 3009 __ Bind(slow_path->exit_label()); |
3065 } | 3010 } |
3066 | 3011 |
3067 | 3012 |
3068 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 3013 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
3069 BinarySmiOpInstr* shift_left) { | 3014 BinarySmiOpInstr* shift_left) { |
3070 const LocationSummary& locs = *shift_left->locs(); | 3015 const LocationSummary& locs = *shift_left->locs(); |
3071 const Register left = locs.in(0).reg(); | 3016 const Register left = locs.in(0).reg(); |
3072 const Register result = locs.out(0).reg(); | 3017 const Register result = locs.out(0).reg(); |
3073 Label* deopt = shift_left->CanDeoptimize() ? | 3018 Label* deopt = shift_left->CanDeoptimize() |
3074 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | 3019 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
3075 : NULL; | 3020 ICData::kDeoptBinarySmiOp) |
| 3021 : NULL; |
3076 if (locs.in(1).IsConstant()) { | 3022 if (locs.in(1).IsConstant()) { |
3077 const Object& constant = locs.in(1).constant(); | 3023 const Object& constant = locs.in(1).constant(); |
3078 ASSERT(constant.IsSmi()); | 3024 ASSERT(constant.IsSmi()); |
3079 // Immediate shift operation takes 5 bits for the count. | 3025 // Immediate shift operation takes 5 bits for the count. |
3080 const intptr_t kCountLimit = 0x1F; | 3026 const intptr_t kCountLimit = 0x1F; |
3081 const intptr_t value = Smi::Cast(constant).Value(); | 3027 const intptr_t value = Smi::Cast(constant).Value(); |
3082 ASSERT((0 < value) && (value < kCountLimit)); | 3028 ASSERT((0 < value) && (value < kCountLimit)); |
3083 if (shift_left->can_overflow()) { | 3029 if (shift_left->can_overflow()) { |
3084 // Check for overflow (preserve left). | 3030 // Check for overflow (preserve left). |
3085 __ Lsl(IP, left, Operand(value)); | 3031 __ Lsl(IP, left, Operand(value)); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3155 __ b(deopt, NE); // Overflow. | 3101 __ b(deopt, NE); // Overflow. |
3156 // Shift for result now we know there is no overflow. | 3102 // Shift for result now we know there is no overflow. |
3157 __ Lsl(result, left, IP); | 3103 __ Lsl(result, left, IP); |
3158 } | 3104 } |
3159 } | 3105 } |
3160 | 3106 |
3161 | 3107 |
3162 class CheckedSmiSlowPath : public SlowPathCode { | 3108 class CheckedSmiSlowPath : public SlowPathCode { |
3163 public: | 3109 public: |
3164 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) | 3110 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) |
3165 : instruction_(instruction), try_index_(try_index) { } | 3111 : instruction_(instruction), try_index_(try_index) {} |
3166 | 3112 |
3167 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 3113 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
3168 if (Assembler::EmittingComments()) { | 3114 if (Assembler::EmittingComments()) { |
3169 __ Comment("slow path smi operation"); | 3115 __ Comment("slow path smi operation"); |
3170 } | 3116 } |
3171 __ Bind(entry_label()); | 3117 __ Bind(entry_label()); |
3172 LocationSummary* locs = instruction_->locs(); | 3118 LocationSummary* locs = instruction_->locs(); |
3173 Register result = locs->out(0).reg(); | 3119 Register result = locs->out(0).reg(); |
3174 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 3120 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
3175 | 3121 |
3176 compiler->SaveLiveRegisters(locs); | 3122 compiler->SaveLiveRegisters(locs); |
3177 __ Push(locs->in(0).reg()); | 3123 __ Push(locs->in(0).reg()); |
3178 __ Push(locs->in(1).reg()); | 3124 __ Push(locs->in(1).reg()); |
3179 compiler->EmitMegamorphicInstanceCall( | 3125 compiler->EmitMegamorphicInstanceCall( |
3180 *instruction_->call()->ic_data(), | 3126 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
3181 instruction_->call()->ArgumentCount(), | 3127 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
3182 instruction_->call()->deopt_id(), | 3128 locs, try_index_, |
3183 instruction_->call()->token_pos(), | |
3184 locs, | |
3185 try_index_, | |
3186 /* slow_path_argument_count = */ 2); | 3129 /* slow_path_argument_count = */ 2); |
3187 __ mov(result, Operand(R0)); | 3130 __ mov(result, Operand(R0)); |
3188 compiler->RestoreLiveRegisters(locs); | 3131 compiler->RestoreLiveRegisters(locs); |
3189 __ b(exit_label()); | 3132 __ b(exit_label()); |
3190 } | 3133 } |
3191 | 3134 |
3192 private: | 3135 private: |
3193 CheckedSmiOpInstr* instruction_; | 3136 CheckedSmiOpInstr* instruction_; |
3194 intptr_t try_index_; | 3137 intptr_t try_index_; |
3195 }; | 3138 }; |
3196 | 3139 |
3197 | 3140 |
3198 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 3141 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
3199 bool opt) const { | 3142 bool opt) const { |
3200 const intptr_t kNumInputs = 2; | 3143 const intptr_t kNumInputs = 2; |
3201 const intptr_t kNumTemps = 0; | 3144 const intptr_t kNumTemps = 0; |
3202 LocationSummary* summary = new(zone) LocationSummary( | 3145 LocationSummary* summary = new (zone) LocationSummary( |
3203 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3146 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
3204 summary->set_in(0, Location::RequiresRegister()); | 3147 summary->set_in(0, Location::RequiresRegister()); |
3205 summary->set_in(1, Location::RequiresRegister()); | 3148 summary->set_in(1, Location::RequiresRegister()); |
3206 summary->set_out(0, Location::RequiresRegister()); | 3149 summary->set_out(0, Location::RequiresRegister()); |
3207 return summary; | 3150 return summary; |
3208 } | 3151 } |
3209 | 3152 |
3210 | 3153 |
3211 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3154 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3212 CheckedSmiSlowPath* slow_path = | 3155 CheckedSmiSlowPath* slow_path = |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3268 | 3211 |
3269 class CheckedSmiComparisonSlowPath : public SlowPathCode { | 3212 class CheckedSmiComparisonSlowPath : public SlowPathCode { |
3270 public: | 3213 public: |
3271 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, | 3214 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, |
3272 intptr_t try_index, | 3215 intptr_t try_index, |
3273 BranchLabels labels, | 3216 BranchLabels labels, |
3274 bool merged) | 3217 bool merged) |
3275 : instruction_(instruction), | 3218 : instruction_(instruction), |
3276 try_index_(try_index), | 3219 try_index_(try_index), |
3277 labels_(labels), | 3220 labels_(labels), |
3278 merged_(merged) { } | 3221 merged_(merged) {} |
3279 | 3222 |
3280 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 3223 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
3281 if (Assembler::EmittingComments()) { | 3224 if (Assembler::EmittingComments()) { |
3282 __ Comment("slow path smi operation"); | 3225 __ Comment("slow path smi operation"); |
3283 } | 3226 } |
3284 __ Bind(entry_label()); | 3227 __ Bind(entry_label()); |
3285 LocationSummary* locs = instruction_->locs(); | 3228 LocationSummary* locs = instruction_->locs(); |
3286 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); | 3229 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); |
3287 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 3230 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
3288 | 3231 |
3289 compiler->SaveLiveRegisters(locs); | 3232 compiler->SaveLiveRegisters(locs); |
3290 __ Push(locs->in(0).reg()); | 3233 __ Push(locs->in(0).reg()); |
3291 __ Push(locs->in(1).reg()); | 3234 __ Push(locs->in(1).reg()); |
3292 compiler->EmitMegamorphicInstanceCall( | 3235 compiler->EmitMegamorphicInstanceCall( |
3293 *instruction_->call()->ic_data(), | 3236 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
3294 instruction_->call()->ArgumentCount(), | 3237 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
3295 instruction_->call()->deopt_id(), | 3238 locs, try_index_, |
3296 instruction_->call()->token_pos(), | |
3297 locs, | |
3298 try_index_, | |
3299 /* slow_path_argument_count = */ 2); | 3239 /* slow_path_argument_count = */ 2); |
3300 __ mov(result, Operand(R0)); | 3240 __ mov(result, Operand(R0)); |
3301 compiler->RestoreLiveRegisters(locs); | 3241 compiler->RestoreLiveRegisters(locs); |
3302 if (merged_) { | 3242 if (merged_) { |
3303 __ CompareObject(result, Bool::True()); | 3243 __ CompareObject(result, Bool::True()); |
3304 __ b(instruction_->is_negated() | 3244 __ b( |
3305 ? labels_.false_label : labels_.true_label, EQ); | 3245 instruction_->is_negated() ? labels_.false_label : labels_.true_label, |
3306 __ b(instruction_->is_negated() | 3246 EQ); |
3307 ? labels_.true_label : labels_.false_label); | 3247 __ b(instruction_->is_negated() ? labels_.true_label |
| 3248 : labels_.false_label); |
3308 } else { | 3249 } else { |
3309 __ b(exit_label()); | 3250 __ b(exit_label()); |
3310 } | 3251 } |
3311 } | 3252 } |
3312 | 3253 |
3313 private: | 3254 private: |
3314 CheckedSmiComparisonInstr* instruction_; | 3255 CheckedSmiComparisonInstr* instruction_; |
3315 intptr_t try_index_; | 3256 intptr_t try_index_; |
3316 BranchLabels labels_; | 3257 BranchLabels labels_; |
3317 bool merged_; | 3258 bool merged_; |
3318 }; | 3259 }; |
3319 | 3260 |
3320 | 3261 |
3321 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 3262 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
3322 Zone* zone, bool opt) const { | 3263 Zone* zone, |
| 3264 bool opt) const { |
3323 const intptr_t kNumInputs = 2; | 3265 const intptr_t kNumInputs = 2; |
3324 const intptr_t kNumTemps = 1; | 3266 const intptr_t kNumTemps = 1; |
3325 LocationSummary* summary = new(zone) LocationSummary( | 3267 LocationSummary* summary = new (zone) LocationSummary( |
3326 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3268 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
3327 summary->set_in(0, Location::RequiresRegister()); | 3269 summary->set_in(0, Location::RequiresRegister()); |
3328 summary->set_in(1, Location::RequiresRegister()); | 3270 summary->set_in(1, Location::RequiresRegister()); |
3329 summary->set_temp(0, Location::RequiresRegister()); | 3271 summary->set_temp(0, Location::RequiresRegister()); |
3330 summary->set_out(0, Location::RequiresRegister()); | 3272 summary->set_out(0, Location::RequiresRegister()); |
3331 return summary; | 3273 return summary; |
3332 } | 3274 } |
3333 | 3275 |
3334 | 3276 |
3335 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 3277 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
3336 FlowGraphCompiler* compiler, BranchLabels labels) { | 3278 FlowGraphCompiler* compiler, |
| 3279 BranchLabels labels) { |
3337 return EmitSmiComparisonOp(compiler, locs(), kind()); | 3280 return EmitSmiComparisonOp(compiler, locs(), kind()); |
3338 } | 3281 } |
3339 | 3282 |
3340 | 3283 |
3341 #define EMIT_SMI_CHECK \ | 3284 #define EMIT_SMI_CHECK \ |
3342 Register left = locs()->in(0).reg(); \ | 3285 Register left = locs()->in(0).reg(); \ |
3343 Register right = locs()->in(1).reg(); \ | 3286 Register right = locs()->in(1).reg(); \ |
3344 Register temp = locs()->temp(0).reg(); \ | 3287 Register temp = locs()->temp(0).reg(); \ |
3345 intptr_t left_cid = this->left()->Type()->ToCid(); \ | 3288 intptr_t left_cid = this->left()->Type()->ToCid(); \ |
3346 intptr_t right_cid = this->right()->Type()->ToCid(); \ | 3289 intptr_t right_cid = this->right()->Type()->ToCid(); \ |
3347 if (this->left()->definition() == this->right()->definition()) { \ | 3290 if (this->left()->definition() == this->right()->definition()) { \ |
3348 __ tst(left, Operand(kSmiTagMask)); \ | 3291 __ tst(left, Operand(kSmiTagMask)); \ |
3349 } else if (left_cid == kSmiCid) { \ | 3292 } else if (left_cid == kSmiCid) { \ |
3350 __ tst(right, Operand(kSmiTagMask)); \ | 3293 __ tst(right, Operand(kSmiTagMask)); \ |
3351 } else if (right_cid == kSmiCid) { \ | 3294 } else if (right_cid == kSmiCid) { \ |
3352 __ tst(left, Operand(kSmiTagMask)); \ | 3295 __ tst(left, Operand(kSmiTagMask)); \ |
3353 } else { \ | 3296 } else { \ |
3354 __ orr(temp, left, Operand(right)); \ | 3297 __ orr(temp, left, Operand(right)); \ |
3355 __ tst(temp, Operand(kSmiTagMask)); \ | 3298 __ tst(temp, Operand(kSmiTagMask)); \ |
3356 } \ | 3299 } \ |
3357 __ b(slow_path->entry_label(), NE) | 3300 __ b(slow_path->entry_label(), NE) |
3358 | 3301 |
3359 | 3302 |
3360 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3303 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
3361 BranchInstr* branch) { | 3304 BranchInstr* branch) { |
3362 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3305 BranchLabels labels = compiler->CreateBranchLabels(branch); |
3363 CheckedSmiComparisonSlowPath* slow_path = | 3306 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3364 new CheckedSmiComparisonSlowPath(this, | 3307 this, compiler->CurrentTryIndex(), labels, |
3365 compiler->CurrentTryIndex(), | 3308 /* merged = */ true); |
3366 labels, | |
3367 /* merged = */ true); | |
3368 compiler->AddSlowPathCode(slow_path); | 3309 compiler->AddSlowPathCode(slow_path); |
3369 EMIT_SMI_CHECK; | 3310 EMIT_SMI_CHECK; |
3370 Condition true_condition = EmitComparisonCode(compiler, labels); | 3311 Condition true_condition = EmitComparisonCode(compiler, labels); |
3371 EmitBranchOnCondition(compiler, true_condition, labels); | 3312 EmitBranchOnCondition(compiler, true_condition, labels); |
3372 __ Bind(slow_path->exit_label()); | 3313 __ Bind(slow_path->exit_label()); |
3373 } | 3314 } |
3374 | 3315 |
3375 | 3316 |
3376 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3317 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3377 BranchLabels labels = { NULL, NULL, NULL }; | 3318 BranchLabels labels = {NULL, NULL, NULL}; |
3378 CheckedSmiComparisonSlowPath* slow_path = | 3319 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3379 new CheckedSmiComparisonSlowPath(this, | 3320 this, compiler->CurrentTryIndex(), labels, |
3380 compiler->CurrentTryIndex(), | 3321 /* merged = */ false); |
3381 labels, | |
3382 /* merged = */ false); | |
3383 compiler->AddSlowPathCode(slow_path); | 3322 compiler->AddSlowPathCode(slow_path); |
3384 EMIT_SMI_CHECK; | 3323 EMIT_SMI_CHECK; |
3385 Condition true_condition = EmitComparisonCode(compiler, labels); | 3324 Condition true_condition = EmitComparisonCode(compiler, labels); |
3386 Register result = locs()->out(0).reg(); | 3325 Register result = locs()->out(0).reg(); |
3387 __ LoadObject(result, Bool::True(), true_condition); | 3326 __ LoadObject(result, Bool::True(), true_condition); |
3388 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 3327 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
3389 __ Bind(slow_path->exit_label()); | 3328 __ Bind(slow_path->exit_label()); |
3390 } | 3329 } |
3391 #undef EMIT_SMI_CHECK | 3330 #undef EMIT_SMI_CHECK |
3392 | 3331 |
3393 | 3332 |
3394 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 3333 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
3395 bool opt) const { | 3334 bool opt) const { |
3396 const intptr_t kNumInputs = 2; | 3335 const intptr_t kNumInputs = 2; |
3397 // Calculate number of temporaries. | 3336 // Calculate number of temporaries. |
3398 intptr_t num_temps = 0; | 3337 intptr_t num_temps = 0; |
3399 if (op_kind() == Token::kTRUNCDIV) { | 3338 if (op_kind() == Token::kTRUNCDIV) { |
3400 if (RightIsPowerOfTwoConstant()) { | 3339 if (RightIsPowerOfTwoConstant()) { |
3401 num_temps = 1; | 3340 num_temps = 1; |
3402 } else { | 3341 } else { |
3403 num_temps = 2; | 3342 num_temps = 2; |
3404 } | 3343 } |
3405 } else if (op_kind() == Token::kMOD) { | 3344 } else if (op_kind() == Token::kMOD) { |
3406 num_temps = 2; | 3345 num_temps = 2; |
3407 } else if (((op_kind() == Token::kSHL) && can_overflow()) || | 3346 } else if (((op_kind() == Token::kSHL) && can_overflow()) || |
3408 (op_kind() == Token::kSHR)) { | 3347 (op_kind() == Token::kSHR)) { |
3409 num_temps = 1; | 3348 num_temps = 1; |
3410 } | 3349 } |
3411 LocationSummary* summary = new(zone) LocationSummary( | 3350 LocationSummary* summary = new (zone) |
3412 zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 3351 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
3413 if (op_kind() == Token::kTRUNCDIV) { | 3352 if (op_kind() == Token::kTRUNCDIV) { |
3414 summary->set_in(0, Location::RequiresRegister()); | 3353 summary->set_in(0, Location::RequiresRegister()); |
3415 if (RightIsPowerOfTwoConstant()) { | 3354 if (RightIsPowerOfTwoConstant()) { |
3416 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 3355 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
3417 summary->set_in(1, Location::Constant(right_constant)); | 3356 summary->set_in(1, Location::Constant(right_constant)); |
3418 summary->set_temp(0, Location::RequiresRegister()); | 3357 summary->set_temp(0, Location::RequiresRegister()); |
3419 } else { | 3358 } else { |
3420 summary->set_in(1, Location::RequiresRegister()); | 3359 summary->set_in(1, Location::RequiresRegister()); |
3421 summary->set_temp(0, Location::RequiresRegister()); | 3360 summary->set_temp(0, Location::RequiresRegister()); |
3422 summary->set_temp(1, Location::RequiresFpuRegister()); | 3361 summary->set_temp(1, Location::RequiresFpuRegister()); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3549 __ LoadImmediate(IP, imm); | 3488 __ LoadImmediate(IP, imm); |
3550 __ eor(result, left, Operand(IP)); | 3489 __ eor(result, left, Operand(IP)); |
3551 } | 3490 } |
3552 break; | 3491 break; |
3553 } | 3492 } |
3554 case Token::kSHR: { | 3493 case Token::kSHR: { |
3555 // sarl operation masks the count to 5 bits. | 3494 // sarl operation masks the count to 5 bits. |
3556 const intptr_t kCountLimit = 0x1F; | 3495 const intptr_t kCountLimit = 0x1F; |
3557 intptr_t value = Smi::Cast(constant).Value(); | 3496 intptr_t value = Smi::Cast(constant).Value(); |
3558 __ Asr(result, left, | 3497 __ Asr(result, left, |
3559 Operand(Utils::Minimum(value + kSmiTagSize, kCountLimit))); | 3498 Operand(Utils::Minimum(value + kSmiTagSize, kCountLimit))); |
3560 __ SmiTag(result); | 3499 __ SmiTag(result); |
3561 break; | 3500 break; |
3562 } | 3501 } |
3563 | 3502 |
3564 default: | 3503 default: |
3565 UNREACHABLE(); | 3504 UNREACHABLE(); |
3566 break; | 3505 break; |
3567 } | 3506 } |
3568 return; | 3507 return; |
3569 } | 3508 } |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3706 break; | 3645 break; |
3707 } | 3646 } |
3708 } | 3647 } |
3709 | 3648 |
3710 | 3649 |
3711 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler, | 3650 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler, |
3712 BinaryInt32OpInstr* shift_left) { | 3651 BinaryInt32OpInstr* shift_left) { |
3713 const LocationSummary& locs = *shift_left->locs(); | 3652 const LocationSummary& locs = *shift_left->locs(); |
3714 const Register left = locs.in(0).reg(); | 3653 const Register left = locs.in(0).reg(); |
3715 const Register result = locs.out(0).reg(); | 3654 const Register result = locs.out(0).reg(); |
3716 Label* deopt = shift_left->CanDeoptimize() ? | 3655 Label* deopt = shift_left->CanDeoptimize() |
3717 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | 3656 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
3718 : NULL; | 3657 ICData::kDeoptBinarySmiOp) |
| 3658 : NULL; |
3719 ASSERT(locs.in(1).IsConstant()); | 3659 ASSERT(locs.in(1).IsConstant()); |
3720 const Object& constant = locs.in(1).constant(); | 3660 const Object& constant = locs.in(1).constant(); |
3721 ASSERT(constant.IsSmi()); | 3661 ASSERT(constant.IsSmi()); |
3722 // Immediate shift operation takes 5 bits for the count. | 3662 // Immediate shift operation takes 5 bits for the count. |
3723 const intptr_t kCountLimit = 0x1F; | 3663 const intptr_t kCountLimit = 0x1F; |
3724 const intptr_t value = Smi::Cast(constant).Value(); | 3664 const intptr_t value = Smi::Cast(constant).Value(); |
3725 ASSERT((0 < value) && (value < kCountLimit)); | 3665 ASSERT((0 < value) && (value < kCountLimit)); |
3726 if (shift_left->can_overflow()) { | 3666 if (shift_left->can_overflow()) { |
3727 // Check for overflow (preserve left). | 3667 // Check for overflow (preserve left). |
3728 __ Lsl(IP, left, Operand(value)); | 3668 __ Lsl(IP, left, Operand(value)); |
3729 __ cmp(left, Operand(IP, ASR, value)); | 3669 __ cmp(left, Operand(IP, ASR, value)); |
3730 __ b(deopt, NE); // Overflow. | 3670 __ b(deopt, NE); // Overflow. |
3731 } | 3671 } |
3732 // Shift for result now we know there is no overflow. | 3672 // Shift for result now we know there is no overflow. |
3733 __ Lsl(result, left, Operand(value)); | 3673 __ Lsl(result, left, Operand(value)); |
3734 } | 3674 } |
3735 | 3675 |
3736 | 3676 |
3737 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone, | 3677 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone, |
3738 bool opt) const { | 3678 bool opt) const { |
3739 const intptr_t kNumInputs = 2; | 3679 const intptr_t kNumInputs = 2; |
3740 // Calculate number of temporaries. | 3680 // Calculate number of temporaries. |
3741 intptr_t num_temps = 0; | 3681 intptr_t num_temps = 0; |
3742 if (((op_kind() == Token::kSHL) && can_overflow()) || | 3682 if (((op_kind() == Token::kSHL) && can_overflow()) || |
3743 (op_kind() == Token::kSHR)) { | 3683 (op_kind() == Token::kSHR)) { |
3744 num_temps = 1; | 3684 num_temps = 1; |
3745 } | 3685 } |
3746 LocationSummary* summary = new(zone) LocationSummary( | 3686 LocationSummary* summary = new (zone) |
3747 zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 3687 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
3748 summary->set_in(0, Location::RequiresRegister()); | 3688 summary->set_in(0, Location::RequiresRegister()); |
3749 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 3689 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
3750 if (((op_kind() == Token::kSHL) && can_overflow()) || | 3690 if (((op_kind() == Token::kSHL) && can_overflow()) || |
3751 (op_kind() == Token::kSHR)) { | 3691 (op_kind() == Token::kSHR)) { |
3752 summary->set_temp(0, Location::RequiresRegister()); | 3692 summary->set_temp(0, Location::RequiresRegister()); |
3753 } | 3693 } |
3754 // We make use of 3-operand instructions by not requiring result register | 3694 // We make use of 3-operand instructions by not requiring result register |
3755 // to be identical to first input register as on Intel. | 3695 // to be identical to first input register as on Intel. |
3756 summary->set_out(0, Location::RequiresRegister()); | 3696 summary->set_out(0, Location::RequiresRegister()); |
3757 return summary; | 3697 return summary; |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3911 } | 3851 } |
3912 | 3852 |
3913 | 3853 |
3914 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3854 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
3915 bool opt) const { | 3855 bool opt) const { |
3916 intptr_t left_cid = left()->Type()->ToCid(); | 3856 intptr_t left_cid = left()->Type()->ToCid(); |
3917 intptr_t right_cid = right()->Type()->ToCid(); | 3857 intptr_t right_cid = right()->Type()->ToCid(); |
3918 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3858 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
3919 const intptr_t kNumInputs = 2; | 3859 const intptr_t kNumInputs = 2; |
3920 const intptr_t kNumTemps = 0; | 3860 const intptr_t kNumTemps = 0; |
3921 LocationSummary* summary = new(zone) LocationSummary( | 3861 LocationSummary* summary = new (zone) |
3922 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3862 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3923 summary->set_in(0, Location::RequiresRegister()); | 3863 summary->set_in(0, Location::RequiresRegister()); |
3924 summary->set_in(1, Location::RequiresRegister()); | 3864 summary->set_in(1, Location::RequiresRegister()); |
3925 return summary; | 3865 return summary; |
3926 } | 3866 } |
3927 | 3867 |
3928 | 3868 |
3929 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3869 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3930 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3870 Label* deopt = |
3931 ICData::kDeoptBinaryDoubleOp, | 3871 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
3932 licm_hoisted_ ? ICData::kHoisted : 0); | 3872 licm_hoisted_ ? ICData::kHoisted : 0); |
3933 intptr_t left_cid = left()->Type()->ToCid(); | 3873 intptr_t left_cid = left()->Type()->ToCid(); |
3934 intptr_t right_cid = right()->Type()->ToCid(); | 3874 intptr_t right_cid = right()->Type()->ToCid(); |
3935 const Register left = locs()->in(0).reg(); | 3875 const Register left = locs()->in(0).reg(); |
3936 const Register right = locs()->in(1).reg(); | 3876 const Register right = locs()->in(1).reg(); |
3937 if (this->left()->definition() == this->right()->definition()) { | 3877 if (this->left()->definition() == this->right()->definition()) { |
3938 __ tst(left, Operand(kSmiTagMask)); | 3878 __ tst(left, Operand(kSmiTagMask)); |
3939 } else if (left_cid == kSmiCid) { | 3879 } else if (left_cid == kSmiCid) { |
3940 __ tst(right, Operand(kSmiTagMask)); | 3880 __ tst(right, Operand(kSmiTagMask)); |
3941 } else if (right_cid == kSmiCid) { | 3881 } else if (right_cid == kSmiCid) { |
3942 __ tst(left, Operand(kSmiTagMask)); | 3882 __ tst(left, Operand(kSmiTagMask)); |
3943 } else { | 3883 } else { |
3944 __ orr(IP, left, Operand(right)); | 3884 __ orr(IP, left, Operand(right)); |
3945 __ tst(IP, Operand(kSmiTagMask)); | 3885 __ tst(IP, Operand(kSmiTagMask)); |
3946 } | 3886 } |
3947 __ b(deopt, EQ); | 3887 __ b(deopt, EQ); |
3948 } | 3888 } |
3949 | 3889 |
3950 | 3890 |
3951 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, | 3891 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
3952 bool opt) const { | |
3953 const intptr_t kNumInputs = 1; | 3892 const intptr_t kNumInputs = 1; |
3954 const intptr_t kNumTemps = 1; | 3893 const intptr_t kNumTemps = 1; |
3955 LocationSummary* summary = new(zone) LocationSummary( | 3894 LocationSummary* summary = new (zone) LocationSummary( |
3956 zone, kNumInputs, | 3895 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
3957 kNumTemps, | |
3958 LocationSummary::kCallOnSlowPath); | |
3959 summary->set_in(0, Location::RequiresFpuRegister()); | 3896 summary->set_in(0, Location::RequiresFpuRegister()); |
3960 summary->set_temp(0, Location::RequiresRegister()); | 3897 summary->set_temp(0, Location::RequiresRegister()); |
3961 summary->set_out(0, Location::RequiresRegister()); | 3898 summary->set_out(0, Location::RequiresRegister()); |
3962 return summary; | 3899 return summary; |
3963 } | 3900 } |
3964 | 3901 |
3965 | 3902 |
3966 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3903 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3967 const Register out_reg = locs()->out(0).reg(); | 3904 const Register out_reg = locs()->out(0).reg(); |
3968 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 3905 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
3969 | 3906 |
3970 BoxAllocationSlowPath::Allocate( | 3907 BoxAllocationSlowPath::Allocate(compiler, this, |
3971 compiler, | 3908 compiler->BoxClassFor(from_representation()), |
3972 this, | 3909 out_reg, locs()->temp(0).reg()); |
3973 compiler->BoxClassFor(from_representation()), | |
3974 out_reg, | |
3975 locs()->temp(0).reg()); | |
3976 | 3910 |
3977 switch (from_representation()) { | 3911 switch (from_representation()) { |
3978 case kUnboxedDouble: | 3912 case kUnboxedDouble: |
3979 __ StoreDToOffset( | 3913 __ StoreDToOffset(value, out_reg, ValueOffset() - kHeapObjectTag); |
3980 value, out_reg, ValueOffset() - kHeapObjectTag); | |
3981 break; | 3914 break; |
3982 case kUnboxedFloat32x4: | 3915 case kUnboxedFloat32x4: |
3983 case kUnboxedFloat64x2: | 3916 case kUnboxedFloat64x2: |
3984 case kUnboxedInt32x4: | 3917 case kUnboxedInt32x4: |
3985 __ StoreMultipleDToOffset( | 3918 __ StoreMultipleDToOffset(value, 2, out_reg, |
3986 value, 2, out_reg, ValueOffset() - kHeapObjectTag); | 3919 ValueOffset() - kHeapObjectTag); |
3987 break; | 3920 break; |
3988 default: | 3921 default: |
3989 UNREACHABLE(); | 3922 UNREACHABLE(); |
3990 break; | 3923 break; |
3991 } | 3924 } |
3992 } | 3925 } |
3993 | 3926 |
3994 | 3927 |
3995 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, | 3928 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
3996 bool opt) const { | |
3997 const bool needs_temp = CanDeoptimize(); | 3929 const bool needs_temp = CanDeoptimize(); |
3998 const intptr_t kNumInputs = 1; | 3930 const intptr_t kNumInputs = 1; |
3999 const intptr_t kNumTemps = needs_temp ? 1 : 0; | 3931 const intptr_t kNumTemps = needs_temp ? 1 : 0; |
4000 LocationSummary* summary = new(zone) LocationSummary( | 3932 LocationSummary* summary = new (zone) |
4001 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3933 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4002 summary->set_in(0, Location::RequiresRegister()); | 3934 summary->set_in(0, Location::RequiresRegister()); |
4003 if (needs_temp) { | 3935 if (needs_temp) { |
4004 summary->set_temp(0, Location::RequiresRegister()); | 3936 summary->set_temp(0, Location::RequiresRegister()); |
4005 } | 3937 } |
4006 if (representation() == kUnboxedMint) { | 3938 if (representation() == kUnboxedMint) { |
4007 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 3939 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
4008 Location::RequiresRegister())); | 3940 Location::RequiresRegister())); |
4009 } else { | 3941 } else { |
4010 summary->set_out(0, Location::RequiresFpuRegister()); | 3942 summary->set_out(0, Location::RequiresFpuRegister()); |
4011 } | 3943 } |
4012 return summary; | 3944 return summary; |
4013 } | 3945 } |
4014 | 3946 |
4015 | 3947 |
4016 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { | 3948 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |
4017 const Register box = locs()->in(0).reg(); | 3949 const Register box = locs()->in(0).reg(); |
4018 | 3950 |
4019 switch (representation()) { | 3951 switch (representation()) { |
4020 case kUnboxedMint: { | 3952 case kUnboxedMint: { |
4021 PairLocation* result = locs()->out(0).AsPairLocation(); | 3953 PairLocation* result = locs()->out(0).AsPairLocation(); |
4022 __ LoadFieldFromOffset(kWord, | 3954 __ LoadFieldFromOffset(kWord, result->At(0).reg(), box, ValueOffset()); |
4023 result->At(0).reg(), | 3955 __ LoadFieldFromOffset(kWord, result->At(1).reg(), box, |
4024 box, | |
4025 ValueOffset()); | |
4026 __ LoadFieldFromOffset(kWord, | |
4027 result->At(1).reg(), | |
4028 box, | |
4029 ValueOffset() + kWordSize); | 3956 ValueOffset() + kWordSize); |
4030 break; | 3957 break; |
4031 } | 3958 } |
4032 | 3959 |
4033 case kUnboxedDouble: { | 3960 case kUnboxedDouble: { |
4034 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 3961 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
4035 __ LoadDFromOffset( | 3962 __ LoadDFromOffset(result, box, ValueOffset() - kHeapObjectTag); |
4036 result, box, ValueOffset() - kHeapObjectTag); | |
4037 break; | 3963 break; |
4038 } | 3964 } |
4039 | 3965 |
4040 case kUnboxedFloat32x4: | 3966 case kUnboxedFloat32x4: |
4041 case kUnboxedFloat64x2: | 3967 case kUnboxedFloat64x2: |
4042 case kUnboxedInt32x4: { | 3968 case kUnboxedInt32x4: { |
4043 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 3969 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
4044 __ LoadMultipleDFromOffset( | 3970 __ LoadMultipleDFromOffset(result, 2, box, |
4045 result, 2, box, ValueOffset() - kHeapObjectTag); | 3971 ValueOffset() - kHeapObjectTag); |
4046 break; | 3972 break; |
4047 } | 3973 } |
4048 | 3974 |
4049 default: | 3975 default: |
4050 UNREACHABLE(); | 3976 UNREACHABLE(); |
4051 break; | 3977 break; |
4052 } | 3978 } |
4053 } | 3979 } |
4054 | 3980 |
4055 | 3981 |
(...skipping 27 matching lines...) Expand all Loading... |
4083 const intptr_t value_cid = value()->Type()->ToCid(); | 4009 const intptr_t value_cid = value()->Type()->ToCid(); |
4084 const intptr_t box_cid = BoxCid(); | 4010 const intptr_t box_cid = BoxCid(); |
4085 | 4011 |
4086 if (value_cid == box_cid) { | 4012 if (value_cid == box_cid) { |
4087 EmitLoadFromBox(compiler); | 4013 EmitLoadFromBox(compiler); |
4088 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 4014 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
4089 EmitSmiConversion(compiler); | 4015 EmitSmiConversion(compiler); |
4090 } else { | 4016 } else { |
4091 const Register box = locs()->in(0).reg(); | 4017 const Register box = locs()->in(0).reg(); |
4092 const Register temp = locs()->temp(0).reg(); | 4018 const Register temp = locs()->temp(0).reg(); |
4093 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), | 4019 Label* deopt = |
4094 ICData::kDeoptCheckClass); | 4020 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass); |
4095 Label is_smi; | 4021 Label is_smi; |
4096 | 4022 |
4097 if ((value()->Type()->ToNullableCid() == box_cid) && | 4023 if ((value()->Type()->ToNullableCid() == box_cid) && |
4098 value()->Type()->is_nullable()) { | 4024 value()->Type()->is_nullable()) { |
4099 __ CompareObject(box, Object::null_object()); | 4025 __ CompareObject(box, Object::null_object()); |
4100 __ b(deopt, EQ); | 4026 __ b(deopt, EQ); |
4101 } else { | 4027 } else { |
4102 __ tst(box, Operand(kSmiTagMask)); | 4028 __ tst(box, Operand(kSmiTagMask)); |
4103 __ b(CanConvertSmi() ? &is_smi : deopt, EQ); | 4029 __ b(CanConvertSmi() ? &is_smi : deopt, EQ); |
4104 __ CompareClassId(box, box_cid, temp); | 4030 __ CompareClassId(box, box_cid, temp); |
4105 __ b(deopt, NE); | 4031 __ b(deopt, NE); |
4106 } | 4032 } |
4107 | 4033 |
4108 EmitLoadFromBox(compiler); | 4034 EmitLoadFromBox(compiler); |
4109 | 4035 |
4110 if (is_smi.IsLinked()) { | 4036 if (is_smi.IsLinked()) { |
4111 Label done; | 4037 Label done; |
4112 __ b(&done); | 4038 __ b(&done); |
4113 __ Bind(&is_smi); | 4039 __ Bind(&is_smi); |
4114 EmitSmiConversion(compiler); | 4040 EmitSmiConversion(compiler); |
4115 __ Bind(&done); | 4041 __ Bind(&done); |
4116 } | 4042 } |
4117 } | 4043 } |
4118 } | 4044 } |
4119 | 4045 |
4120 | 4046 |
4121 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 4047 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |
4122 bool opt) const { | 4048 bool opt) const { |
4123 ASSERT((from_representation() == kUnboxedInt32) || | 4049 ASSERT((from_representation() == kUnboxedInt32) || |
4124 (from_representation() == kUnboxedUint32)); | 4050 (from_representation() == kUnboxedUint32)); |
4125 const intptr_t kNumInputs = 1; | 4051 const intptr_t kNumInputs = 1; |
4126 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 4052 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
4127 LocationSummary* summary = new(zone) LocationSummary( | 4053 LocationSummary* summary = new (zone) |
4128 zone, | 4054 LocationSummary(zone, kNumInputs, kNumTemps, |
4129 kNumInputs, | 4055 ValueFitsSmi() ? LocationSummary::kNoCall |
4130 kNumTemps, | 4056 : LocationSummary::kCallOnSlowPath); |
4131 ValueFitsSmi() ? LocationSummary::kNoCall | |
4132 : LocationSummary::kCallOnSlowPath); | |
4133 summary->set_in(0, Location::RequiresRegister()); | 4057 summary->set_in(0, Location::RequiresRegister()); |
4134 if (!ValueFitsSmi()) { | 4058 if (!ValueFitsSmi()) { |
4135 summary->set_temp(0, Location::RequiresRegister()); | 4059 summary->set_temp(0, Location::RequiresRegister()); |
4136 } | 4060 } |
4137 summary->set_out(0, Location::RequiresRegister()); | 4061 summary->set_out(0, Location::RequiresRegister()); |
4138 return summary; | 4062 return summary; |
4139 } | 4063 } |
4140 | 4064 |
4141 | 4065 |
4142 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4066 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4143 Register value = locs()->in(0).reg(); | 4067 Register value = locs()->in(0).reg(); |
4144 Register out = locs()->out(0).reg(); | 4068 Register out = locs()->out(0).reg(); |
4145 ASSERT(value != out); | 4069 ASSERT(value != out); |
4146 | 4070 |
4147 __ SmiTag(out, value); | 4071 __ SmiTag(out, value); |
4148 if (!ValueFitsSmi()) { | 4072 if (!ValueFitsSmi()) { |
4149 Register temp = locs()->temp(0).reg(); | 4073 Register temp = locs()->temp(0).reg(); |
4150 Label done; | 4074 Label done; |
4151 if (from_representation() == kUnboxedInt32) { | 4075 if (from_representation() == kUnboxedInt32) { |
4152 __ cmp(value, Operand(out, ASR, 1)); | 4076 __ cmp(value, Operand(out, ASR, 1)); |
4153 } else { | 4077 } else { |
4154 ASSERT(from_representation() == kUnboxedUint32); | 4078 ASSERT(from_representation() == kUnboxedUint32); |
4155 // Note: better to test upper bits instead of comparing with | 4079 // Note: better to test upper bits instead of comparing with |
4156 // kSmiMax as kSmiMax does not fit into immediate operand. | 4080 // kSmiMax as kSmiMax does not fit into immediate operand. |
4157 __ TestImmediate(value, 0xC0000000); | 4081 __ TestImmediate(value, 0xC0000000); |
4158 } | 4082 } |
4159 __ b(&done, EQ); | 4083 __ b(&done, EQ); |
4160 BoxAllocationSlowPath::Allocate( | 4084 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out, |
4161 compiler, | 4085 temp); |
4162 this, | |
4163 compiler->mint_class(), | |
4164 out, | |
4165 temp); | |
4166 if (from_representation() == kUnboxedInt32) { | 4086 if (from_representation() == kUnboxedInt32) { |
4167 __ Asr(temp, value, Operand(kBitsPerWord - 1)); | 4087 __ Asr(temp, value, Operand(kBitsPerWord - 1)); |
4168 } else { | 4088 } else { |
4169 ASSERT(from_representation() == kUnboxedUint32); | 4089 ASSERT(from_representation() == kUnboxedUint32); |
4170 __ eor(temp, temp, Operand(temp)); | 4090 __ eor(temp, temp, Operand(temp)); |
4171 } | 4091 } |
4172 __ StoreToOffset(kWord, | 4092 __ StoreToOffset(kWord, value, out, Mint::value_offset() - kHeapObjectTag); |
4173 value, | 4093 __ StoreToOffset(kWord, temp, out, |
4174 out, | |
4175 Mint::value_offset() - kHeapObjectTag); | |
4176 __ StoreToOffset(kWord, | |
4177 temp, | |
4178 out, | |
4179 Mint::value_offset() - kHeapObjectTag + kWordSize); | 4094 Mint::value_offset() - kHeapObjectTag + kWordSize); |
4180 __ Bind(&done); | 4095 __ Bind(&done); |
4181 } | 4096 } |
4182 } | 4097 } |
4183 | 4098 |
4184 | 4099 |
4185 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, | 4100 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, |
4186 bool opt) const { | 4101 bool opt) const { |
4187 const intptr_t kNumInputs = 1; | 4102 const intptr_t kNumInputs = 1; |
4188 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 4103 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
4189 LocationSummary* summary = new(zone) LocationSummary( | 4104 LocationSummary* summary = new (zone) |
4190 zone, | 4105 LocationSummary(zone, kNumInputs, kNumTemps, |
4191 kNumInputs, | 4106 ValueFitsSmi() ? LocationSummary::kNoCall |
4192 kNumTemps, | 4107 : LocationSummary::kCallOnSlowPath); |
4193 ValueFitsSmi() ? LocationSummary::kNoCall | |
4194 : LocationSummary::kCallOnSlowPath); | |
4195 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 4108 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
4196 Location::RequiresRegister())); | 4109 Location::RequiresRegister())); |
4197 if (!ValueFitsSmi()) { | 4110 if (!ValueFitsSmi()) { |
4198 summary->set_temp(0, Location::RequiresRegister()); | 4111 summary->set_temp(0, Location::RequiresRegister()); |
4199 } | 4112 } |
4200 summary->set_out(0, Location::RequiresRegister()); | 4113 summary->set_out(0, Location::RequiresRegister()); |
4201 return summary; | 4114 return summary; |
4202 } | 4115 } |
4203 | 4116 |
4204 | 4117 |
(...skipping 11 matching lines...) Expand all Loading... |
4216 Register value_hi = value_pair->At(1).reg(); | 4129 Register value_hi = value_pair->At(1).reg(); |
4217 Register tmp = locs()->temp(0).reg(); | 4130 Register tmp = locs()->temp(0).reg(); |
4218 Register out_reg = locs()->out(0).reg(); | 4131 Register out_reg = locs()->out(0).reg(); |
4219 | 4132 |
4220 Label done; | 4133 Label done; |
4221 __ SmiTag(out_reg, value_lo); | 4134 __ SmiTag(out_reg, value_lo); |
4222 __ cmp(value_lo, Operand(out_reg, ASR, kSmiTagSize)); | 4135 __ cmp(value_lo, Operand(out_reg, ASR, kSmiTagSize)); |
4223 __ cmp(value_hi, Operand(out_reg, ASR, 31), EQ); | 4136 __ cmp(value_hi, Operand(out_reg, ASR, 31), EQ); |
4224 __ b(&done, EQ); | 4137 __ b(&done, EQ); |
4225 | 4138 |
4226 BoxAllocationSlowPath::Allocate( | 4139 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), |
4227 compiler, | 4140 out_reg, tmp); |
4228 this, | 4141 __ StoreToOffset(kWord, value_lo, out_reg, |
4229 compiler->mint_class(), | |
4230 out_reg, | |
4231 tmp); | |
4232 __ StoreToOffset(kWord, | |
4233 value_lo, | |
4234 out_reg, | |
4235 Mint::value_offset() - kHeapObjectTag); | 4142 Mint::value_offset() - kHeapObjectTag); |
4236 __ StoreToOffset(kWord, | 4143 __ StoreToOffset(kWord, value_hi, out_reg, |
4237 value_hi, | |
4238 out_reg, | |
4239 Mint::value_offset() - kHeapObjectTag + kWordSize); | 4144 Mint::value_offset() - kHeapObjectTag + kWordSize); |
4240 __ Bind(&done); | 4145 __ Bind(&done); |
4241 } | 4146 } |
4242 | 4147 |
4243 | 4148 |
4244 static void LoadInt32FromMint(FlowGraphCompiler* compiler, | 4149 static void LoadInt32FromMint(FlowGraphCompiler* compiler, |
4245 Register mint, | 4150 Register mint, |
4246 Register result, | 4151 Register result, |
4247 Register temp, | 4152 Register temp, |
4248 Label* deopt) { | 4153 Label* deopt) { |
4249 __ LoadFieldFromOffset(kWord, result, mint, Mint::value_offset()); | 4154 __ LoadFieldFromOffset(kWord, result, mint, Mint::value_offset()); |
4250 if (deopt != NULL) { | 4155 if (deopt != NULL) { |
4251 __ LoadFieldFromOffset(kWord, | 4156 __ LoadFieldFromOffset(kWord, temp, mint, Mint::value_offset() + kWordSize); |
4252 temp, | |
4253 mint, | |
4254 Mint::value_offset() + kWordSize); | |
4255 __ cmp(temp, Operand(result, ASR, kBitsPerWord - 1)); | 4157 __ cmp(temp, Operand(result, ASR, kBitsPerWord - 1)); |
4256 __ b(deopt, NE); | 4158 __ b(deopt, NE); |
4257 } | 4159 } |
4258 } | 4160 } |
4259 | 4161 |
4260 | 4162 |
4261 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 4163 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |
4262 bool opt) const { | 4164 bool opt) const { |
4263 ASSERT((representation() == kUnboxedInt32) || | 4165 ASSERT((representation() == kUnboxedInt32) || |
4264 (representation() == kUnboxedUint32)); | 4166 (representation() == kUnboxedUint32)); |
4265 ASSERT((representation() != kUnboxedUint32) || is_truncating()); | 4167 ASSERT((representation() != kUnboxedUint32) || is_truncating()); |
4266 const intptr_t kNumInputs = 1; | 4168 const intptr_t kNumInputs = 1; |
4267 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; | 4169 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; |
4268 LocationSummary* summary = new(zone) LocationSummary( | 4170 LocationSummary* summary = new (zone) |
4269 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4171 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4270 summary->set_in(0, Location::RequiresRegister()); | 4172 summary->set_in(0, Location::RequiresRegister()); |
4271 if (kNumTemps > 0) { | 4173 if (kNumTemps > 0) { |
4272 summary->set_temp(0, Location::RequiresRegister()); | 4174 summary->set_temp(0, Location::RequiresRegister()); |
4273 } | 4175 } |
4274 summary->set_out(0, Location::RequiresRegister()); | 4176 summary->set_out(0, Location::RequiresRegister()); |
4275 return summary; | 4177 return summary; |
4276 } | 4178 } |
4277 | 4179 |
4278 | 4180 |
4279 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4181 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4280 const intptr_t value_cid = value()->Type()->ToCid(); | 4182 const intptr_t value_cid = value()->Type()->ToCid(); |
4281 const Register value = locs()->in(0).reg(); | 4183 const Register value = locs()->in(0).reg(); |
4282 const Register out = locs()->out(0).reg(); | 4184 const Register out = locs()->out(0).reg(); |
4283 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; | 4185 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; |
4284 Label* deopt = CanDeoptimize() ? | 4186 Label* deopt = |
4285 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL; | 4187 CanDeoptimize() |
| 4188 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) |
| 4189 : NULL; |
4286 Label* out_of_range = !is_truncating() ? deopt : NULL; | 4190 Label* out_of_range = !is_truncating() ? deopt : NULL; |
4287 ASSERT(value != out); | 4191 ASSERT(value != out); |
4288 | 4192 |
4289 if (value_cid == kSmiCid) { | 4193 if (value_cid == kSmiCid) { |
4290 __ SmiUntag(out, value); | 4194 __ SmiUntag(out, value); |
4291 } else if (value_cid == kMintCid) { | 4195 } else if (value_cid == kMintCid) { |
4292 LoadInt32FromMint(compiler, value, out, temp, out_of_range); | 4196 LoadInt32FromMint(compiler, value, out, temp, out_of_range); |
4293 } else if (!CanDeoptimize()) { | 4197 } else if (!CanDeoptimize()) { |
4294 Label done; | 4198 Label done; |
4295 __ SmiUntag(out, value, &done); | 4199 __ SmiUntag(out, value, &done); |
4296 LoadInt32FromMint(compiler, value, out, kNoRegister, NULL); | 4200 LoadInt32FromMint(compiler, value, out, kNoRegister, NULL); |
4297 __ Bind(&done); | 4201 __ Bind(&done); |
4298 } else { | 4202 } else { |
4299 Label done; | 4203 Label done; |
4300 __ SmiUntag(out, value, &done); | 4204 __ SmiUntag(out, value, &done); |
4301 __ CompareClassId(value, kMintCid, temp); | 4205 __ CompareClassId(value, kMintCid, temp); |
4302 __ b(deopt, NE); | 4206 __ b(deopt, NE); |
4303 LoadInt32FromMint(compiler, value, out, temp, out_of_range); | 4207 LoadInt32FromMint(compiler, value, out, temp, out_of_range); |
4304 __ Bind(&done); | 4208 __ Bind(&done); |
4305 } | 4209 } |
4306 } | 4210 } |
4307 | 4211 |
4308 | 4212 |
4309 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 4213 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
4310 bool opt) const { | 4214 bool opt) const { |
4311 const intptr_t kNumInputs = 2; | 4215 const intptr_t kNumInputs = 2; |
4312 const intptr_t kNumTemps = 0; | 4216 const intptr_t kNumTemps = 0; |
4313 LocationSummary* summary = new(zone) LocationSummary( | 4217 LocationSummary* summary = new (zone) |
4314 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4218 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4315 summary->set_in(0, Location::RequiresFpuRegister()); | 4219 summary->set_in(0, Location::RequiresFpuRegister()); |
4316 summary->set_in(1, Location::RequiresFpuRegister()); | 4220 summary->set_in(1, Location::RequiresFpuRegister()); |
4317 summary->set_out(0, Location::RequiresFpuRegister()); | 4221 summary->set_out(0, Location::RequiresFpuRegister()); |
4318 return summary; | 4222 return summary; |
4319 } | 4223 } |
4320 | 4224 |
4321 | 4225 |
4322 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4226 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4323 const DRegister left = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 4227 const DRegister left = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
4324 const DRegister right = EvenDRegisterOf(locs()->in(1).fpu_reg()); | 4228 const DRegister right = EvenDRegisterOf(locs()->in(1).fpu_reg()); |
4325 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 4229 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
4326 switch (op_kind()) { | 4230 switch (op_kind()) { |
4327 case Token::kADD: __ vaddd(result, left, right); break; | 4231 case Token::kADD: |
4328 case Token::kSUB: __ vsubd(result, left, right); break; | 4232 __ vaddd(result, left, right); |
4329 case Token::kMUL: __ vmuld(result, left, right); break; | 4233 break; |
4330 case Token::kDIV: __ vdivd(result, left, right); break; | 4234 case Token::kSUB: |
4331 default: UNREACHABLE(); | 4235 __ vsubd(result, left, right); |
| 4236 break; |
| 4237 case Token::kMUL: |
| 4238 __ vmuld(result, left, right); |
| 4239 break; |
| 4240 case Token::kDIV: |
| 4241 __ vdivd(result, left, right); |
| 4242 break; |
| 4243 default: |
| 4244 UNREACHABLE(); |
4332 } | 4245 } |
4333 } | 4246 } |
4334 | 4247 |
4335 | 4248 |
4336 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 4249 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |
4337 bool opt) const { | 4250 bool opt) const { |
4338 const intptr_t kNumInputs = 1; | 4251 const intptr_t kNumInputs = 1; |
4339 const intptr_t kNumTemps = | 4252 const intptr_t kNumTemps = |
4340 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; | 4253 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; |
4341 LocationSummary* summary = new(zone) LocationSummary( | 4254 LocationSummary* summary = new (zone) |
4342 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4255 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4343 summary->set_in(0, Location::RequiresFpuRegister()); | 4256 summary->set_in(0, Location::RequiresFpuRegister()); |
4344 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 4257 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
4345 summary->set_temp(0, Location::RequiresRegister()); | 4258 summary->set_temp(0, Location::RequiresRegister()); |
4346 } | 4259 } |
4347 summary->set_out(0, Location::RequiresRegister()); | 4260 summary->set_out(0, Location::RequiresRegister()); |
4348 return summary; | 4261 return summary; |
4349 } | 4262 } |
4350 | 4263 |
4351 | 4264 |
4352 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 4265 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
(...skipping 26 matching lines...) Expand all Loading... |
4379 ASSERT(compiler->is_optimizing()); | 4292 ASSERT(compiler->is_optimizing()); |
4380 BranchLabels labels = compiler->CreateBranchLabels(branch); | 4293 BranchLabels labels = compiler->CreateBranchLabels(branch); |
4381 Condition true_condition = EmitComparisonCode(compiler, labels); | 4294 Condition true_condition = EmitComparisonCode(compiler, labels); |
4382 EmitBranchOnCondition(compiler, true_condition, labels); | 4295 EmitBranchOnCondition(compiler, true_condition, labels); |
4383 } | 4296 } |
4384 | 4297 |
4385 | 4298 |
4386 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4299 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4387 ASSERT(compiler->is_optimizing()); | 4300 ASSERT(compiler->is_optimizing()); |
4388 Label is_true, is_false; | 4301 Label is_true, is_false; |
4389 BranchLabels labels = { &is_true, &is_false, &is_false }; | 4302 BranchLabels labels = {&is_true, &is_false, &is_false}; |
4390 Condition true_condition = EmitComparisonCode(compiler, labels); | 4303 Condition true_condition = EmitComparisonCode(compiler, labels); |
4391 const Register result = locs()->out(0).reg(); | 4304 const Register result = locs()->out(0).reg(); |
4392 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { | 4305 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { |
4393 __ LoadObject(result, Bool::True(), true_condition); | 4306 __ LoadObject(result, Bool::True(), true_condition); |
4394 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 4307 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
4395 } else { | 4308 } else { |
4396 ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite); | 4309 ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite); |
4397 EmitBranchOnCondition(compiler, true_condition, labels); | 4310 EmitBranchOnCondition(compiler, true_condition, labels); |
4398 Label done; | 4311 Label done; |
4399 __ Bind(&is_false); | 4312 __ Bind(&is_false); |
4400 __ LoadObject(result, Bool::False()); | 4313 __ LoadObject(result, Bool::False()); |
4401 __ b(&done); | 4314 __ b(&done); |
4402 __ Bind(&is_true); | 4315 __ Bind(&is_true); |
4403 __ LoadObject(result, Bool::True()); | 4316 __ LoadObject(result, Bool::True()); |
4404 __ Bind(&done); | 4317 __ Bind(&done); |
4405 } | 4318 } |
4406 } | 4319 } |
4407 | 4320 |
4408 | 4321 |
4409 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 4322 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
4410 bool opt) const { | 4323 bool opt) const { |
4411 const intptr_t kNumInputs = 2; | 4324 const intptr_t kNumInputs = 2; |
4412 const intptr_t kNumTemps = 0; | 4325 const intptr_t kNumTemps = 0; |
4413 LocationSummary* summary = new(zone) LocationSummary( | 4326 LocationSummary* summary = new (zone) |
4414 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4327 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4415 summary->set_in(0, Location::RequiresFpuRegister()); | 4328 summary->set_in(0, Location::RequiresFpuRegister()); |
4416 summary->set_in(1, Location::RequiresFpuRegister()); | 4329 summary->set_in(1, Location::RequiresFpuRegister()); |
4417 summary->set_out(0, Location::RequiresFpuRegister()); | 4330 summary->set_out(0, Location::RequiresFpuRegister()); |
4418 return summary; | 4331 return summary; |
4419 } | 4332 } |
4420 | 4333 |
4421 | 4334 |
4422 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4335 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4423 const QRegister left = locs()->in(0).fpu_reg(); | 4336 const QRegister left = locs()->in(0).fpu_reg(); |
4424 const QRegister right = locs()->in(1).fpu_reg(); | 4337 const QRegister right = locs()->in(1).fpu_reg(); |
4425 const QRegister result = locs()->out(0).fpu_reg(); | 4338 const QRegister result = locs()->out(0).fpu_reg(); |
4426 | 4339 |
4427 switch (op_kind()) { | 4340 switch (op_kind()) { |
4428 case Token::kADD: __ vaddqs(result, left, right); break; | 4341 case Token::kADD: |
4429 case Token::kSUB: __ vsubqs(result, left, right); break; | 4342 __ vaddqs(result, left, right); |
4430 case Token::kMUL: __ vmulqs(result, left, right); break; | 4343 break; |
4431 case Token::kDIV: __ Vdivqs(result, left, right); break; | 4344 case Token::kSUB: |
4432 default: UNREACHABLE(); | 4345 __ vsubqs(result, left, right); |
| 4346 break; |
| 4347 case Token::kMUL: |
| 4348 __ vmulqs(result, left, right); |
| 4349 break; |
| 4350 case Token::kDIV: |
| 4351 __ Vdivqs(result, left, right); |
| 4352 break; |
| 4353 default: |
| 4354 UNREACHABLE(); |
4433 } | 4355 } |
4434 } | 4356 } |
4435 | 4357 |
4436 | 4358 |
4437 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, | 4359 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, |
4438 bool opt) const { | 4360 bool opt) const { |
4439 const intptr_t kNumInputs = 2; | 4361 const intptr_t kNumInputs = 2; |
4440 const intptr_t kNumTemps = 0; | 4362 const intptr_t kNumTemps = 0; |
4441 LocationSummary* summary = new(zone) LocationSummary( | 4363 LocationSummary* summary = new (zone) |
4442 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4364 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4443 summary->set_in(0, Location::RequiresFpuRegister()); | 4365 summary->set_in(0, Location::RequiresFpuRegister()); |
4444 summary->set_in(1, Location::RequiresFpuRegister()); | 4366 summary->set_in(1, Location::RequiresFpuRegister()); |
4445 summary->set_out(0, Location::RequiresFpuRegister()); | 4367 summary->set_out(0, Location::RequiresFpuRegister()); |
4446 return summary; | 4368 return summary; |
4447 } | 4369 } |
4448 | 4370 |
4449 | 4371 |
4450 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4372 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4451 const QRegister left = locs()->in(0).fpu_reg(); | 4373 const QRegister left = locs()->in(0).fpu_reg(); |
4452 const QRegister right = locs()->in(1).fpu_reg(); | 4374 const QRegister right = locs()->in(1).fpu_reg(); |
(...skipping 18 matching lines...) Expand all Loading... |
4471 __ vsubd(result1, left1, right1); | 4393 __ vsubd(result1, left1, right1); |
4472 break; | 4394 break; |
4473 case Token::kMUL: | 4395 case Token::kMUL: |
4474 __ vmuld(result0, left0, right0); | 4396 __ vmuld(result0, left0, right0); |
4475 __ vmuld(result1, left1, right1); | 4397 __ vmuld(result1, left1, right1); |
4476 break; | 4398 break; |
4477 case Token::kDIV: | 4399 case Token::kDIV: |
4478 __ vdivd(result0, left0, right0); | 4400 __ vdivd(result0, left0, right0); |
4479 __ vdivd(result1, left1, right1); | 4401 __ vdivd(result1, left1, right1); |
4480 break; | 4402 break; |
4481 default: UNREACHABLE(); | 4403 default: |
| 4404 UNREACHABLE(); |
4482 } | 4405 } |
4483 } | 4406 } |
4484 | 4407 |
4485 | 4408 |
4486 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, | 4409 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, |
4487 bool opt) const { | 4410 bool opt) const { |
4488 const intptr_t kNumInputs = 1; | 4411 const intptr_t kNumInputs = 1; |
4489 const intptr_t kNumTemps = 0; | 4412 const intptr_t kNumTemps = 0; |
4490 LocationSummary* summary = new(zone) LocationSummary( | 4413 LocationSummary* summary = new (zone) |
4491 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4414 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4492 // Low (< Q7) Q registers are needed for the vcvtds and vmovs instructions. | 4415 // Low (< Q7) Q registers are needed for the vcvtds and vmovs instructions. |
4493 summary->set_in(0, Location::FpuRegisterLocation(Q5)); | 4416 summary->set_in(0, Location::FpuRegisterLocation(Q5)); |
4494 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 4417 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
4495 return summary; | 4418 return summary; |
4496 } | 4419 } |
4497 | 4420 |
4498 | 4421 |
4499 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4422 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4500 const QRegister value = locs()->in(0).fpu_reg(); | 4423 const QRegister value = locs()->in(0).fpu_reg(); |
4501 const QRegister result = locs()->out(0).fpu_reg(); | 4424 const QRegister result = locs()->out(0).fpu_reg(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4533 __ vcvtds(dresult0, svalue3); | 4456 __ vcvtds(dresult0, svalue3); |
4534 break; | 4457 break; |
4535 case MethodRecognizer::kInt32x4Shuffle: | 4458 case MethodRecognizer::kInt32x4Shuffle: |
4536 case MethodRecognizer::kFloat32x4Shuffle: | 4459 case MethodRecognizer::kFloat32x4Shuffle: |
4537 if (mask_ == 0x00) { | 4460 if (mask_ == 0x00) { |
4538 __ vdup(kWord, result, dvalue0, 0); | 4461 __ vdup(kWord, result, dvalue0, 0); |
4539 } else if (mask_ == 0x55) { | 4462 } else if (mask_ == 0x55) { |
4540 __ vdup(kWord, result, dvalue0, 1); | 4463 __ vdup(kWord, result, dvalue0, 1); |
4541 } else if (mask_ == 0xAA) { | 4464 } else if (mask_ == 0xAA) { |
4542 __ vdup(kWord, result, dvalue1, 0); | 4465 __ vdup(kWord, result, dvalue1, 0); |
4543 } else if (mask_ == 0xFF) { | 4466 } else if (mask_ == 0xFF) { |
4544 __ vdup(kWord, result, dvalue1, 1); | 4467 __ vdup(kWord, result, dvalue1, 1); |
4545 } else { | 4468 } else { |
4546 // TODO(zra): Investigate better instruction sequences for other | 4469 // TODO(zra): Investigate better instruction sequences for other |
4547 // shuffle masks. | 4470 // shuffle masks. |
4548 SRegister svalues[4]; | 4471 SRegister svalues[4]; |
4549 | 4472 |
4550 svalues[0] = EvenSRegisterOf(dtemp0); | 4473 svalues[0] = EvenSRegisterOf(dtemp0); |
4551 svalues[1] = OddSRegisterOf(dtemp0); | 4474 svalues[1] = OddSRegisterOf(dtemp0); |
4552 svalues[2] = EvenSRegisterOf(dtemp1); | 4475 svalues[2] = EvenSRegisterOf(dtemp1); |
4553 svalues[3] = OddSRegisterOf(dtemp1); | 4476 svalues[3] = OddSRegisterOf(dtemp1); |
4554 | 4477 |
4555 __ vmovq(QTMP, value); | 4478 __ vmovq(QTMP, value); |
4556 __ vmovs(sresult0, svalues[mask_ & 0x3]); | 4479 __ vmovs(sresult0, svalues[mask_ & 0x3]); |
4557 __ vmovs(sresult1, svalues[(mask_ >> 2) & 0x3]); | 4480 __ vmovs(sresult1, svalues[(mask_ >> 2) & 0x3]); |
4558 __ vmovs(sresult2, svalues[(mask_ >> 4) & 0x3]); | 4481 __ vmovs(sresult2, svalues[(mask_ >> 4) & 0x3]); |
4559 __ vmovs(sresult3, svalues[(mask_ >> 6) & 0x3]); | 4482 __ vmovs(sresult3, svalues[(mask_ >> 6) & 0x3]); |
4560 } | 4483 } |
4561 break; | 4484 break; |
4562 default: UNREACHABLE(); | 4485 default: |
| 4486 UNREACHABLE(); |
4563 } | 4487 } |
4564 } | 4488 } |
4565 | 4489 |
4566 | 4490 |
4567 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 4491 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |
4568 bool opt) const { | 4492 bool opt) const { |
4569 const intptr_t kNumInputs = 2; | 4493 const intptr_t kNumInputs = 2; |
4570 const intptr_t kNumTemps = 0; | 4494 const intptr_t kNumTemps = 0; |
4571 LocationSummary* summary = new(zone) LocationSummary( | 4495 LocationSummary* summary = new (zone) |
4572 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4496 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4573 // Low (< Q7) Q registers are needed for the vcvtds and vmovs instructions. | 4497 // Low (< Q7) Q registers are needed for the vcvtds and vmovs instructions. |
4574 summary->set_in(0, Location::FpuRegisterLocation(Q4)); | 4498 summary->set_in(0, Location::FpuRegisterLocation(Q4)); |
4575 summary->set_in(1, Location::FpuRegisterLocation(Q5)); | 4499 summary->set_in(1, Location::FpuRegisterLocation(Q5)); |
4576 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 4500 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
4577 return summary; | 4501 return summary; |
4578 } | 4502 } |
4579 | 4503 |
4580 | 4504 |
4581 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4505 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4582 const QRegister left = locs()->in(0).fpu_reg(); | 4506 const QRegister left = locs()->in(0).fpu_reg(); |
(...skipping 26 matching lines...) Expand all Loading... |
4609 right_svalues[0] = EvenSRegisterOf(dright0); | 4533 right_svalues[0] = EvenSRegisterOf(dright0); |
4610 right_svalues[1] = OddSRegisterOf(dright0); | 4534 right_svalues[1] = OddSRegisterOf(dright0); |
4611 right_svalues[2] = EvenSRegisterOf(dright1); | 4535 right_svalues[2] = EvenSRegisterOf(dright1); |
4612 right_svalues[3] = OddSRegisterOf(dright1); | 4536 right_svalues[3] = OddSRegisterOf(dright1); |
4613 | 4537 |
4614 __ vmovs(sresult0, left_svalues[mask_ & 0x3]); | 4538 __ vmovs(sresult0, left_svalues[mask_ & 0x3]); |
4615 __ vmovs(sresult1, left_svalues[(mask_ >> 2) & 0x3]); | 4539 __ vmovs(sresult1, left_svalues[(mask_ >> 2) & 0x3]); |
4616 __ vmovs(sresult2, right_svalues[(mask_ >> 4) & 0x3]); | 4540 __ vmovs(sresult2, right_svalues[(mask_ >> 4) & 0x3]); |
4617 __ vmovs(sresult3, right_svalues[(mask_ >> 6) & 0x3]); | 4541 __ vmovs(sresult3, right_svalues[(mask_ >> 6) & 0x3]); |
4618 break; | 4542 break; |
4619 default: UNREACHABLE(); | 4543 default: |
| 4544 UNREACHABLE(); |
4620 } | 4545 } |
4621 } | 4546 } |
4622 | 4547 |
4623 | 4548 |
4624 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, | 4549 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, |
4625 bool opt) const { | 4550 bool opt) const { |
4626 const intptr_t kNumInputs = 1; | 4551 const intptr_t kNumInputs = 1; |
4627 const intptr_t kNumTemps = 1; | 4552 const intptr_t kNumTemps = 1; |
4628 LocationSummary* summary = new(zone) LocationSummary( | 4553 LocationSummary* summary = new (zone) |
4629 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4554 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4630 summary->set_in(0, Location::FpuRegisterLocation(Q5)); | 4555 summary->set_in(0, Location::FpuRegisterLocation(Q5)); |
4631 summary->set_temp(0, Location::RequiresRegister()); | 4556 summary->set_temp(0, Location::RequiresRegister()); |
4632 summary->set_out(0, Location::RequiresRegister()); | 4557 summary->set_out(0, Location::RequiresRegister()); |
4633 return summary; | 4558 return summary; |
4634 } | 4559 } |
4635 | 4560 |
4636 | 4561 |
4637 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4562 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4638 const QRegister value = locs()->in(0).fpu_reg(); | 4563 const QRegister value = locs()->in(0).fpu_reg(); |
4639 const DRegister dvalue0 = EvenDRegisterOf(value); | 4564 const DRegister dvalue0 = EvenDRegisterOf(value); |
(...skipping 16 matching lines...) Expand all Loading... |
4656 // W lane. | 4581 // W lane. |
4657 __ vmovrs(temp, OddSRegisterOf(dvalue1)); | 4582 __ vmovrs(temp, OddSRegisterOf(dvalue1)); |
4658 __ Lsr(temp, temp, Operand(31)); | 4583 __ Lsr(temp, temp, Operand(31)); |
4659 __ orr(out, out, Operand(temp, LSL, 3)); | 4584 __ orr(out, out, Operand(temp, LSL, 3)); |
4660 // Tag. | 4585 // Tag. |
4661 __ SmiTag(out); | 4586 __ SmiTag(out); |
4662 } | 4587 } |
4663 | 4588 |
4664 | 4589 |
4665 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 4590 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
4666 Zone* zone, bool opt) const { | 4591 Zone* zone, |
| 4592 bool opt) const { |
4667 const intptr_t kNumInputs = 4; | 4593 const intptr_t kNumInputs = 4; |
4668 const intptr_t kNumTemps = 0; | 4594 const intptr_t kNumTemps = 0; |
4669 LocationSummary* summary = new(zone) LocationSummary( | 4595 LocationSummary* summary = new (zone) |
4670 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4596 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4671 summary->set_in(0, Location::RequiresFpuRegister()); | 4597 summary->set_in(0, Location::RequiresFpuRegister()); |
4672 summary->set_in(1, Location::RequiresFpuRegister()); | 4598 summary->set_in(1, Location::RequiresFpuRegister()); |
4673 summary->set_in(2, Location::RequiresFpuRegister()); | 4599 summary->set_in(2, Location::RequiresFpuRegister()); |
4674 summary->set_in(3, Location::RequiresFpuRegister()); | 4600 summary->set_in(3, Location::RequiresFpuRegister()); |
4675 // Low (< 7) Q registers are needed for the vcvtsd instruction. | 4601 // Low (< 7) Q registers are needed for the vcvtsd instruction. |
4676 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 4602 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
4677 return summary; | 4603 return summary; |
4678 } | 4604 } |
4679 | 4605 |
4680 | 4606 |
(...skipping 11 matching lines...) Expand all Loading... |
4692 __ vcvtsd(OddSRegisterOf(dr0), EvenDRegisterOf(q1)); | 4618 __ vcvtsd(OddSRegisterOf(dr0), EvenDRegisterOf(q1)); |
4693 __ vcvtsd(EvenSRegisterOf(dr1), EvenDRegisterOf(q2)); | 4619 __ vcvtsd(EvenSRegisterOf(dr1), EvenDRegisterOf(q2)); |
4694 __ vcvtsd(OddSRegisterOf(dr1), EvenDRegisterOf(q3)); | 4620 __ vcvtsd(OddSRegisterOf(dr1), EvenDRegisterOf(q3)); |
4695 } | 4621 } |
4696 | 4622 |
4697 | 4623 |
4698 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, | 4624 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, |
4699 bool opt) const { | 4625 bool opt) const { |
4700 const intptr_t kNumInputs = 0; | 4626 const intptr_t kNumInputs = 0; |
4701 const intptr_t kNumTemps = 0; | 4627 const intptr_t kNumTemps = 0; |
4702 LocationSummary* summary = new(zone) LocationSummary( | 4628 LocationSummary* summary = new (zone) |
4703 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4629 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4704 summary->set_out(0, Location::RequiresFpuRegister()); | 4630 summary->set_out(0, Location::RequiresFpuRegister()); |
4705 return summary; | 4631 return summary; |
4706 } | 4632 } |
4707 | 4633 |
4708 | 4634 |
4709 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4635 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4710 const QRegister q = locs()->out(0).fpu_reg(); | 4636 const QRegister q = locs()->out(0).fpu_reg(); |
4711 __ veorq(q, q, q); | 4637 __ veorq(q, q, q); |
4712 } | 4638 } |
4713 | 4639 |
4714 | 4640 |
4715 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, | 4641 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, |
4716 bool opt) const { | 4642 bool opt) const { |
4717 const intptr_t kNumInputs = 1; | 4643 const intptr_t kNumInputs = 1; |
4718 const intptr_t kNumTemps = 0; | 4644 const intptr_t kNumTemps = 0; |
4719 LocationSummary* summary = new(zone) LocationSummary( | 4645 LocationSummary* summary = new (zone) |
4720 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4646 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4721 summary->set_in(0, Location::RequiresFpuRegister()); | 4647 summary->set_in(0, Location::RequiresFpuRegister()); |
4722 summary->set_out(0, Location::RequiresFpuRegister()); | 4648 summary->set_out(0, Location::RequiresFpuRegister()); |
4723 return summary; | 4649 return summary; |
4724 } | 4650 } |
4725 | 4651 |
4726 | 4652 |
4727 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4653 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4728 const QRegister value = locs()->in(0).fpu_reg(); | 4654 const QRegister value = locs()->in(0).fpu_reg(); |
4729 const QRegister result = locs()->out(0).fpu_reg(); | 4655 const QRegister result = locs()->out(0).fpu_reg(); |
4730 | 4656 |
4731 const DRegister dvalue0 = EvenDRegisterOf(value); | 4657 const DRegister dvalue0 = EvenDRegisterOf(value); |
4732 | 4658 |
4733 // Convert to Float32. | 4659 // Convert to Float32. |
4734 __ vcvtsd(STMP, dvalue0); | 4660 __ vcvtsd(STMP, dvalue0); |
4735 | 4661 |
4736 // Splat across all lanes. | 4662 // Splat across all lanes. |
4737 __ vdup(kWord, result, DTMP, 0); | 4663 __ vdup(kWord, result, DTMP, 0); |
4738 } | 4664 } |
4739 | 4665 |
4740 | 4666 |
4741 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, | 4667 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, |
4742 bool opt) const { | 4668 bool opt) const { |
4743 const intptr_t kNumInputs = 2; | 4669 const intptr_t kNumInputs = 2; |
4744 const intptr_t kNumTemps = 0; | 4670 const intptr_t kNumTemps = 0; |
4745 LocationSummary* summary = new(zone) LocationSummary( | 4671 LocationSummary* summary = new (zone) |
4746 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4672 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4747 summary->set_in(0, Location::RequiresFpuRegister()); | 4673 summary->set_in(0, Location::RequiresFpuRegister()); |
4748 summary->set_in(1, Location::RequiresFpuRegister()); | 4674 summary->set_in(1, Location::RequiresFpuRegister()); |
4749 summary->set_out(0, Location::RequiresFpuRegister()); | 4675 summary->set_out(0, Location::RequiresFpuRegister()); |
4750 return summary; | 4676 return summary; |
4751 } | 4677 } |
4752 | 4678 |
4753 | 4679 |
4754 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4680 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4755 const QRegister left = locs()->in(0).fpu_reg(); | 4681 const QRegister left = locs()->in(0).fpu_reg(); |
4756 const QRegister right = locs()->in(1).fpu_reg(); | 4682 const QRegister right = locs()->in(1).fpu_reg(); |
(...skipping 14 matching lines...) Expand all Loading... |
4771 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: | 4697 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: |
4772 __ vcgeqs(result, left, right); | 4698 __ vcgeqs(result, left, right); |
4773 break; | 4699 break; |
4774 case MethodRecognizer::kFloat32x4LessThan: | 4700 case MethodRecognizer::kFloat32x4LessThan: |
4775 __ vcgtqs(result, right, left); | 4701 __ vcgtqs(result, right, left); |
4776 break; | 4702 break; |
4777 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 4703 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
4778 __ vcgeqs(result, right, left); | 4704 __ vcgeqs(result, right, left); |
4779 break; | 4705 break; |
4780 | 4706 |
4781 default: UNREACHABLE(); | 4707 default: |
| 4708 UNREACHABLE(); |
4782 } | 4709 } |
4783 } | 4710 } |
4784 | 4711 |
4785 | 4712 |
4786 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, | 4713 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, |
4787 bool opt) const { | 4714 bool opt) const { |
4788 const intptr_t kNumInputs = 2; | 4715 const intptr_t kNumInputs = 2; |
4789 const intptr_t kNumTemps = 0; | 4716 const intptr_t kNumTemps = 0; |
4790 LocationSummary* summary = new(zone) LocationSummary( | 4717 LocationSummary* summary = new (zone) |
4791 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4718 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4792 summary->set_in(0, Location::RequiresFpuRegister()); | 4719 summary->set_in(0, Location::RequiresFpuRegister()); |
4793 summary->set_in(1, Location::RequiresFpuRegister()); | 4720 summary->set_in(1, Location::RequiresFpuRegister()); |
4794 summary->set_out(0, Location::RequiresFpuRegister()); | 4721 summary->set_out(0, Location::RequiresFpuRegister()); |
4795 return summary; | 4722 return summary; |
4796 } | 4723 } |
4797 | 4724 |
4798 | 4725 |
4799 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4726 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4800 const QRegister left = locs()->in(0).fpu_reg(); | 4727 const QRegister left = locs()->in(0).fpu_reg(); |
4801 const QRegister right = locs()->in(1).fpu_reg(); | 4728 const QRegister right = locs()->in(1).fpu_reg(); |
4802 const QRegister result = locs()->out(0).fpu_reg(); | 4729 const QRegister result = locs()->out(0).fpu_reg(); |
4803 | 4730 |
4804 switch (op_kind()) { | 4731 switch (op_kind()) { |
4805 case MethodRecognizer::kFloat32x4Min: | 4732 case MethodRecognizer::kFloat32x4Min: |
4806 __ vminqs(result, left, right); | 4733 __ vminqs(result, left, right); |
4807 break; | 4734 break; |
4808 case MethodRecognizer::kFloat32x4Max: | 4735 case MethodRecognizer::kFloat32x4Max: |
4809 __ vmaxqs(result, left, right); | 4736 __ vmaxqs(result, left, right); |
4810 break; | 4737 break; |
4811 default: UNREACHABLE(); | 4738 default: |
| 4739 UNREACHABLE(); |
4812 } | 4740 } |
4813 } | 4741 } |
4814 | 4742 |
4815 | 4743 |
4816 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, | 4744 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, |
4817 bool opt) const { | 4745 bool opt) const { |
4818 const intptr_t kNumInputs = 1; | 4746 const intptr_t kNumInputs = 1; |
4819 const intptr_t kNumTemps = 1; | 4747 const intptr_t kNumTemps = 1; |
4820 LocationSummary* summary = new(zone) LocationSummary( | 4748 LocationSummary* summary = new (zone) |
4821 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4749 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4822 summary->set_in(0, Location::RequiresFpuRegister()); | 4750 summary->set_in(0, Location::RequiresFpuRegister()); |
4823 summary->set_out(0, Location::RequiresFpuRegister()); | 4751 summary->set_out(0, Location::RequiresFpuRegister()); |
4824 summary->set_temp(0, Location::RequiresFpuRegister()); | 4752 summary->set_temp(0, Location::RequiresFpuRegister()); |
4825 return summary; | 4753 return summary; |
4826 } | 4754 } |
4827 | 4755 |
4828 | 4756 |
4829 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4757 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4830 const QRegister left = locs()->in(0).fpu_reg(); | 4758 const QRegister left = locs()->in(0).fpu_reg(); |
4831 const QRegister result = locs()->out(0).fpu_reg(); | 4759 const QRegister result = locs()->out(0).fpu_reg(); |
4832 const QRegister temp = locs()->temp(0).fpu_reg(); | 4760 const QRegister temp = locs()->temp(0).fpu_reg(); |
4833 | 4761 |
4834 switch (op_kind()) { | 4762 switch (op_kind()) { |
4835 case MethodRecognizer::kFloat32x4Sqrt: | 4763 case MethodRecognizer::kFloat32x4Sqrt: |
4836 __ Vsqrtqs(result, left, temp); | 4764 __ Vsqrtqs(result, left, temp); |
4837 break; | 4765 break; |
4838 case MethodRecognizer::kFloat32x4Reciprocal: | 4766 case MethodRecognizer::kFloat32x4Reciprocal: |
4839 __ Vreciprocalqs(result, left); | 4767 __ Vreciprocalqs(result, left); |
4840 break; | 4768 break; |
4841 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 4769 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
4842 __ VreciprocalSqrtqs(result, left); | 4770 __ VreciprocalSqrtqs(result, left); |
4843 break; | 4771 break; |
4844 default: UNREACHABLE(); | 4772 default: |
| 4773 UNREACHABLE(); |
4845 } | 4774 } |
4846 } | 4775 } |
4847 | 4776 |
4848 | 4777 |
4849 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, | 4778 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, |
4850 bool opt) const { | 4779 bool opt) const { |
4851 const intptr_t kNumInputs = 2; | 4780 const intptr_t kNumInputs = 2; |
4852 const intptr_t kNumTemps = 0; | 4781 const intptr_t kNumTemps = 0; |
4853 LocationSummary* summary = new(zone) LocationSummary( | 4782 LocationSummary* summary = new (zone) |
4854 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4783 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4855 summary->set_in(0, Location::RequiresFpuRegister()); | 4784 summary->set_in(0, Location::RequiresFpuRegister()); |
4856 summary->set_in(1, Location::RequiresFpuRegister()); | 4785 summary->set_in(1, Location::RequiresFpuRegister()); |
4857 summary->set_out(0, Location::RequiresFpuRegister()); | 4786 summary->set_out(0, Location::RequiresFpuRegister()); |
4858 return summary; | 4787 return summary; |
4859 } | 4788 } |
4860 | 4789 |
4861 | 4790 |
4862 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4791 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4863 const QRegister left = locs()->in(0).fpu_reg(); | 4792 const QRegister left = locs()->in(0).fpu_reg(); |
4864 const QRegister right = locs()->in(1).fpu_reg(); | 4793 const QRegister right = locs()->in(1).fpu_reg(); |
4865 const QRegister result = locs()->out(0).fpu_reg(); | 4794 const QRegister result = locs()->out(0).fpu_reg(); |
4866 | 4795 |
4867 switch (op_kind()) { | 4796 switch (op_kind()) { |
4868 case MethodRecognizer::kFloat32x4Scale: | 4797 case MethodRecognizer::kFloat32x4Scale: |
4869 __ vcvtsd(STMP, EvenDRegisterOf(left)); | 4798 __ vcvtsd(STMP, EvenDRegisterOf(left)); |
4870 __ vdup(kWord, result, DTMP, 0); | 4799 __ vdup(kWord, result, DTMP, 0); |
4871 __ vmulqs(result, result, right); | 4800 __ vmulqs(result, result, right); |
4872 break; | 4801 break; |
4873 default: UNREACHABLE(); | 4802 default: |
| 4803 UNREACHABLE(); |
4874 } | 4804 } |
4875 } | 4805 } |
4876 | 4806 |
4877 | 4807 |
4878 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4808 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, |
4879 bool opt) const { | 4809 bool opt) const { |
4880 const intptr_t kNumInputs = 1; | 4810 const intptr_t kNumInputs = 1; |
4881 const intptr_t kNumTemps = 0; | 4811 const intptr_t kNumTemps = 0; |
4882 LocationSummary* summary = new(zone) LocationSummary( | 4812 LocationSummary* summary = new (zone) |
4883 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4813 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4884 summary->set_in(0, Location::RequiresFpuRegister()); | 4814 summary->set_in(0, Location::RequiresFpuRegister()); |
4885 summary->set_out(0, Location::RequiresFpuRegister()); | 4815 summary->set_out(0, Location::RequiresFpuRegister()); |
4886 return summary; | 4816 return summary; |
4887 } | 4817 } |
4888 | 4818 |
4889 | 4819 |
4890 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4820 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4891 const QRegister left = locs()->in(0).fpu_reg(); | 4821 const QRegister left = locs()->in(0).fpu_reg(); |
4892 const QRegister result = locs()->out(0).fpu_reg(); | 4822 const QRegister result = locs()->out(0).fpu_reg(); |
4893 | 4823 |
4894 switch (op_kind()) { | 4824 switch (op_kind()) { |
4895 case MethodRecognizer::kFloat32x4Negate: | 4825 case MethodRecognizer::kFloat32x4Negate: |
4896 __ vnegqs(result, left); | 4826 __ vnegqs(result, left); |
4897 break; | 4827 break; |
4898 case MethodRecognizer::kFloat32x4Absolute: | 4828 case MethodRecognizer::kFloat32x4Absolute: |
4899 __ vabsqs(result, left); | 4829 __ vabsqs(result, left); |
4900 break; | 4830 break; |
4901 default: UNREACHABLE(); | 4831 default: |
| 4832 UNREACHABLE(); |
4902 } | 4833 } |
4903 } | 4834 } |
4904 | 4835 |
4905 | 4836 |
4906 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, | 4837 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, |
4907 bool opt) const { | 4838 bool opt) const { |
4908 const intptr_t kNumInputs = 3; | 4839 const intptr_t kNumInputs = 3; |
4909 const intptr_t kNumTemps = 0; | 4840 const intptr_t kNumTemps = 0; |
4910 LocationSummary* summary = new(zone) LocationSummary( | 4841 LocationSummary* summary = new (zone) |
4911 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4842 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4912 summary->set_in(0, Location::RequiresFpuRegister()); | 4843 summary->set_in(0, Location::RequiresFpuRegister()); |
4913 summary->set_in(1, Location::RequiresFpuRegister()); | 4844 summary->set_in(1, Location::RequiresFpuRegister()); |
4914 summary->set_in(2, Location::RequiresFpuRegister()); | 4845 summary->set_in(2, Location::RequiresFpuRegister()); |
4915 summary->set_out(0, Location::RequiresFpuRegister()); | 4846 summary->set_out(0, Location::RequiresFpuRegister()); |
4916 return summary; | 4847 return summary; |
4917 } | 4848 } |
4918 | 4849 |
4919 | 4850 |
4920 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4851 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4921 const QRegister left = locs()->in(0).fpu_reg(); | 4852 const QRegister left = locs()->in(0).fpu_reg(); |
4922 const QRegister lower = locs()->in(1).fpu_reg(); | 4853 const QRegister lower = locs()->in(1).fpu_reg(); |
4923 const QRegister upper = locs()->in(2).fpu_reg(); | 4854 const QRegister upper = locs()->in(2).fpu_reg(); |
4924 const QRegister result = locs()->out(0).fpu_reg(); | 4855 const QRegister result = locs()->out(0).fpu_reg(); |
4925 __ vminqs(result, left, upper); | 4856 __ vminqs(result, left, upper); |
4926 __ vmaxqs(result, result, lower); | 4857 __ vmaxqs(result, result, lower); |
4927 } | 4858 } |
4928 | 4859 |
4929 | 4860 |
4930 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, | 4861 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, |
4931 bool opt) const { | 4862 bool opt) const { |
4932 const intptr_t kNumInputs = 2; | 4863 const intptr_t kNumInputs = 2; |
4933 const intptr_t kNumTemps = 0; | 4864 const intptr_t kNumTemps = 0; |
4934 LocationSummary* summary = new(zone) LocationSummary( | 4865 LocationSummary* summary = new (zone) |
4935 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4866 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4936 summary->set_in(0, Location::RequiresFpuRegister()); | 4867 summary->set_in(0, Location::RequiresFpuRegister()); |
4937 summary->set_in(1, Location::RequiresFpuRegister()); | 4868 summary->set_in(1, Location::RequiresFpuRegister()); |
4938 // Low (< 7) Q registers are needed for the vmovs instruction. | 4869 // Low (< 7) Q registers are needed for the vmovs instruction. |
4939 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 4870 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
4940 return summary; | 4871 return summary; |
4941 } | 4872 } |
4942 | 4873 |
4943 | 4874 |
4944 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4875 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4945 const QRegister replacement = locs()->in(0).fpu_reg(); | 4876 const QRegister replacement = locs()->in(0).fpu_reg(); |
(...skipping 18 matching lines...) Expand all Loading... |
4964 break; | 4895 break; |
4965 case MethodRecognizer::kFloat32x4WithY: | 4896 case MethodRecognizer::kFloat32x4WithY: |
4966 __ vmovs(sresult1, STMP); | 4897 __ vmovs(sresult1, STMP); |
4967 break; | 4898 break; |
4968 case MethodRecognizer::kFloat32x4WithZ: | 4899 case MethodRecognizer::kFloat32x4WithZ: |
4969 __ vmovs(sresult2, STMP); | 4900 __ vmovs(sresult2, STMP); |
4970 break; | 4901 break; |
4971 case MethodRecognizer::kFloat32x4WithW: | 4902 case MethodRecognizer::kFloat32x4WithW: |
4972 __ vmovs(sresult3, STMP); | 4903 __ vmovs(sresult3, STMP); |
4973 break; | 4904 break; |
4974 default: UNREACHABLE(); | 4905 default: |
| 4906 UNREACHABLE(); |
4975 } | 4907 } |
4976 } | 4908 } |
4977 | 4909 |
4978 | 4910 |
4979 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, | 4911 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, |
4980 bool opt) const { | 4912 bool opt) const { |
4981 const intptr_t kNumInputs = 1; | 4913 const intptr_t kNumInputs = 1; |
4982 const intptr_t kNumTemps = 0; | 4914 const intptr_t kNumTemps = 0; |
4983 LocationSummary* summary = new(zone) LocationSummary( | 4915 LocationSummary* summary = new (zone) |
4984 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4916 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4985 summary->set_in(0, Location::RequiresFpuRegister()); | 4917 summary->set_in(0, Location::RequiresFpuRegister()); |
4986 summary->set_out(0, Location::RequiresFpuRegister()); | 4918 summary->set_out(0, Location::RequiresFpuRegister()); |
4987 return summary; | 4919 return summary; |
4988 } | 4920 } |
4989 | 4921 |
4990 | 4922 |
4991 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4923 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4992 const QRegister value = locs()->in(0).fpu_reg(); | 4924 const QRegister value = locs()->in(0).fpu_reg(); |
4993 const QRegister result = locs()->out(0).fpu_reg(); | 4925 const QRegister result = locs()->out(0).fpu_reg(); |
4994 | 4926 |
4995 if (value != result) { | 4927 if (value != result) { |
4996 __ vmovq(result, value); | 4928 __ vmovq(result, value); |
4997 } | 4929 } |
4998 } | 4930 } |
4999 | 4931 |
5000 | 4932 |
5001 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 4933 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |
5002 bool opt) const { | 4934 bool opt) const { |
5003 const intptr_t kNumInputs = 1; | 4935 const intptr_t kNumInputs = 1; |
5004 const intptr_t kNumTemps = 0; | 4936 const intptr_t kNumTemps = 0; |
5005 LocationSummary* summary = new(zone) LocationSummary( | 4937 LocationSummary* summary = new (zone) |
5006 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4938 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5007 summary->set_in(0, Location::RequiresFpuRegister()); | 4939 summary->set_in(0, Location::RequiresFpuRegister()); |
5008 summary->set_out(0, Location::RequiresFpuRegister()); | 4940 summary->set_out(0, Location::RequiresFpuRegister()); |
5009 return summary; | 4941 return summary; |
5010 } | 4942 } |
5011 | 4943 |
5012 | 4944 |
5013 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4945 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5014 const QRegister value = locs()->in(0).fpu_reg(); | 4946 const QRegister value = locs()->in(0).fpu_reg(); |
5015 | 4947 |
5016 const DRegister dvalue0 = EvenDRegisterOf(value); | 4948 const DRegister dvalue0 = EvenDRegisterOf(value); |
5017 const DRegister dvalue1 = OddDRegisterOf(value); | 4949 const DRegister dvalue1 = OddDRegisterOf(value); |
5018 | 4950 |
5019 const QRegister result = locs()->out(0).fpu_reg(); | 4951 const QRegister result = locs()->out(0).fpu_reg(); |
5020 | 4952 |
5021 const DRegister dresult0 = EvenDRegisterOf(result); | 4953 const DRegister dresult0 = EvenDRegisterOf(result); |
5022 | 4954 |
5023 switch (op_kind()) { | 4955 switch (op_kind()) { |
5024 case MethodRecognizer::kFloat64x2GetX: | 4956 case MethodRecognizer::kFloat64x2GetX: |
5025 __ vmovd(dresult0, dvalue0); | 4957 __ vmovd(dresult0, dvalue0); |
5026 break; | 4958 break; |
5027 case MethodRecognizer::kFloat64x2GetY: | 4959 case MethodRecognizer::kFloat64x2GetY: |
5028 __ vmovd(dresult0, dvalue1); | 4960 __ vmovd(dresult0, dvalue1); |
5029 break; | 4961 break; |
5030 default: UNREACHABLE(); | 4962 default: |
| 4963 UNREACHABLE(); |
5031 } | 4964 } |
5032 } | 4965 } |
5033 | 4966 |
5034 | 4967 |
5035 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 4968 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |
5036 bool opt) const { | 4969 bool opt) const { |
5037 const intptr_t kNumInputs = 0; | 4970 const intptr_t kNumInputs = 0; |
5038 const intptr_t kNumTemps = 0; | 4971 const intptr_t kNumTemps = 0; |
5039 LocationSummary* summary = new(zone) LocationSummary( | 4972 LocationSummary* summary = new (zone) |
5040 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4973 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5041 summary->set_out(0, Location::RequiresFpuRegister()); | 4974 summary->set_out(0, Location::RequiresFpuRegister()); |
5042 return summary; | 4975 return summary; |
5043 } | 4976 } |
5044 | 4977 |
5045 | 4978 |
5046 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4979 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5047 const QRegister q = locs()->out(0).fpu_reg(); | 4980 const QRegister q = locs()->out(0).fpu_reg(); |
5048 __ veorq(q, q, q); | 4981 __ veorq(q, q, q); |
5049 } | 4982 } |
5050 | 4983 |
5051 | 4984 |
5052 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 4985 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |
5053 bool opt) const { | 4986 bool opt) const { |
5054 const intptr_t kNumInputs = 1; | 4987 const intptr_t kNumInputs = 1; |
5055 const intptr_t kNumTemps = 0; | 4988 const intptr_t kNumTemps = 0; |
5056 LocationSummary* summary = new(zone) LocationSummary( | 4989 LocationSummary* summary = new (zone) |
5057 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4990 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5058 summary->set_in(0, Location::RequiresFpuRegister()); | 4991 summary->set_in(0, Location::RequiresFpuRegister()); |
5059 summary->set_out(0, Location::RequiresFpuRegister()); | 4992 summary->set_out(0, Location::RequiresFpuRegister()); |
5060 return summary; | 4993 return summary; |
5061 } | 4994 } |
5062 | 4995 |
5063 | 4996 |
5064 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4997 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5065 const QRegister value = locs()->in(0).fpu_reg(); | 4998 const QRegister value = locs()->in(0).fpu_reg(); |
5066 | 4999 |
5067 const DRegister dvalue = EvenDRegisterOf(value); | 5000 const DRegister dvalue = EvenDRegisterOf(value); |
5068 | 5001 |
5069 const QRegister result = locs()->out(0).fpu_reg(); | 5002 const QRegister result = locs()->out(0).fpu_reg(); |
5070 | 5003 |
5071 const DRegister dresult0 = EvenDRegisterOf(result); | 5004 const DRegister dresult0 = EvenDRegisterOf(result); |
5072 const DRegister dresult1 = OddDRegisterOf(result); | 5005 const DRegister dresult1 = OddDRegisterOf(result); |
5073 | 5006 |
5074 // Splat across all lanes. | 5007 // Splat across all lanes. |
5075 __ vmovd(dresult0, dvalue); | 5008 __ vmovd(dresult0, dvalue); |
5076 __ vmovd(dresult1, dvalue); | 5009 __ vmovd(dresult1, dvalue); |
5077 } | 5010 } |
5078 | 5011 |
5079 | 5012 |
5080 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 5013 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
5081 Zone* zone, bool opt) const { | 5014 Zone* zone, |
| 5015 bool opt) const { |
5082 const intptr_t kNumInputs = 2; | 5016 const intptr_t kNumInputs = 2; |
5083 const intptr_t kNumTemps = 0; | 5017 const intptr_t kNumTemps = 0; |
5084 LocationSummary* summary = new(zone) LocationSummary( | 5018 LocationSummary* summary = new (zone) |
5085 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5019 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5086 summary->set_in(0, Location::RequiresFpuRegister()); | 5020 summary->set_in(0, Location::RequiresFpuRegister()); |
5087 summary->set_in(1, Location::RequiresFpuRegister()); | 5021 summary->set_in(1, Location::RequiresFpuRegister()); |
5088 summary->set_out(0, Location::RequiresFpuRegister()); | 5022 summary->set_out(0, Location::RequiresFpuRegister()); |
5089 return summary; | 5023 return summary; |
5090 } | 5024 } |
5091 | 5025 |
5092 | 5026 |
5093 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5027 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5094 const QRegister q0 = locs()->in(0).fpu_reg(); | 5028 const QRegister q0 = locs()->in(0).fpu_reg(); |
5095 const QRegister q1 = locs()->in(1).fpu_reg(); | 5029 const QRegister q1 = locs()->in(1).fpu_reg(); |
5096 const QRegister r = locs()->out(0).fpu_reg(); | 5030 const QRegister r = locs()->out(0).fpu_reg(); |
5097 | 5031 |
5098 const DRegister d0 = EvenDRegisterOf(q0); | 5032 const DRegister d0 = EvenDRegisterOf(q0); |
5099 const DRegister d1 = EvenDRegisterOf(q1); | 5033 const DRegister d1 = EvenDRegisterOf(q1); |
5100 | 5034 |
5101 const DRegister dr0 = EvenDRegisterOf(r); | 5035 const DRegister dr0 = EvenDRegisterOf(r); |
5102 const DRegister dr1 = OddDRegisterOf(r); | 5036 const DRegister dr1 = OddDRegisterOf(r); |
5103 | 5037 |
5104 __ vmovd(dr0, d0); | 5038 __ vmovd(dr0, d0); |
5105 __ vmovd(dr1, d1); | 5039 __ vmovd(dr1, d1); |
5106 } | 5040 } |
5107 | 5041 |
5108 | 5042 |
5109 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 5043 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
5110 Zone* zone, bool opt) const { | 5044 Zone* zone, |
| 5045 bool opt) const { |
5111 const intptr_t kNumInputs = 1; | 5046 const intptr_t kNumInputs = 1; |
5112 const intptr_t kNumTemps = 0; | 5047 const intptr_t kNumTemps = 0; |
5113 LocationSummary* summary = new(zone) LocationSummary( | 5048 LocationSummary* summary = new (zone) |
5114 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5049 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5115 summary->set_in(0, Location::RequiresFpuRegister()); | 5050 summary->set_in(0, Location::RequiresFpuRegister()); |
5116 // Low (< 7) Q registers are needed for the vcvtsd instruction. | 5051 // Low (< 7) Q registers are needed for the vcvtsd instruction. |
5117 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 5052 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
5118 return summary; | 5053 return summary; |
5119 } | 5054 } |
5120 | 5055 |
5121 | 5056 |
5122 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5057 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5123 const QRegister q = locs()->in(0).fpu_reg(); | 5058 const QRegister q = locs()->in(0).fpu_reg(); |
5124 const QRegister r = locs()->out(0).fpu_reg(); | 5059 const QRegister r = locs()->out(0).fpu_reg(); |
5125 | 5060 |
5126 const DRegister dq0 = EvenDRegisterOf(q); | 5061 const DRegister dq0 = EvenDRegisterOf(q); |
5127 const DRegister dq1 = OddDRegisterOf(q); | 5062 const DRegister dq1 = OddDRegisterOf(q); |
5128 | 5063 |
5129 const DRegister dr0 = EvenDRegisterOf(r); | 5064 const DRegister dr0 = EvenDRegisterOf(r); |
5130 | 5065 |
5131 // Zero register. | 5066 // Zero register. |
5132 __ veorq(r, r, r); | 5067 __ veorq(r, r, r); |
5133 // Set X lane. | 5068 // Set X lane. |
5134 __ vcvtsd(EvenSRegisterOf(dr0), dq0); | 5069 __ vcvtsd(EvenSRegisterOf(dr0), dq0); |
5135 // Set Y lane. | 5070 // Set Y lane. |
5136 __ vcvtsd(OddSRegisterOf(dr0), dq1); | 5071 __ vcvtsd(OddSRegisterOf(dr0), dq1); |
5137 } | 5072 } |
5138 | 5073 |
5139 | 5074 |
5140 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 5075 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
5141 Zone* zone, bool opt) const { | 5076 Zone* zone, |
| 5077 bool opt) const { |
5142 const intptr_t kNumInputs = 1; | 5078 const intptr_t kNumInputs = 1; |
5143 const intptr_t kNumTemps = 0; | 5079 const intptr_t kNumTemps = 0; |
5144 LocationSummary* summary = new(zone) LocationSummary( | 5080 LocationSummary* summary = new (zone) |
5145 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5081 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5146 summary->set_in(0, Location::RequiresFpuRegister()); | 5082 summary->set_in(0, Location::RequiresFpuRegister()); |
5147 // Low (< 7) Q registers are needed for the vcvtsd instruction. | 5083 // Low (< 7) Q registers are needed for the vcvtsd instruction. |
5148 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 5084 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
5149 return summary; | 5085 return summary; |
5150 } | 5086 } |
5151 | 5087 |
5152 | 5088 |
5153 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5089 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5154 const QRegister q = locs()->in(0).fpu_reg(); | 5090 const QRegister q = locs()->in(0).fpu_reg(); |
5155 const QRegister r = locs()->out(0).fpu_reg(); | 5091 const QRegister r = locs()->out(0).fpu_reg(); |
5156 | 5092 |
5157 const DRegister dq0 = EvenDRegisterOf(q); | 5093 const DRegister dq0 = EvenDRegisterOf(q); |
5158 | 5094 |
5159 const DRegister dr0 = EvenDRegisterOf(r); | 5095 const DRegister dr0 = EvenDRegisterOf(r); |
5160 const DRegister dr1 = OddDRegisterOf(r); | 5096 const DRegister dr1 = OddDRegisterOf(r); |
5161 | 5097 |
5162 // Set X. | 5098 // Set X. |
5163 __ vcvtds(dr0, EvenSRegisterOf(dq0)); | 5099 __ vcvtds(dr0, EvenSRegisterOf(dq0)); |
5164 // Set Y. | 5100 // Set Y. |
5165 __ vcvtds(dr1, OddSRegisterOf(dq0)); | 5101 __ vcvtds(dr1, OddSRegisterOf(dq0)); |
5166 } | 5102 } |
5167 | 5103 |
5168 | 5104 |
5169 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, | 5105 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, |
5170 bool opt) const { | 5106 bool opt) const { |
5171 const intptr_t kNumInputs = 1; | 5107 const intptr_t kNumInputs = 1; |
5172 const intptr_t kNumTemps = 0; | 5108 const intptr_t kNumTemps = 0; |
5173 LocationSummary* summary = new(zone) LocationSummary( | 5109 LocationSummary* summary = new (zone) |
5174 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5110 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5175 | 5111 |
5176 if (representation() == kTagged) { | 5112 if (representation() == kTagged) { |
5177 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 5113 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |
5178 // Grabbing the S components means we need a low (< 7) Q. | 5114 // Grabbing the S components means we need a low (< 7) Q. |
5179 summary->set_in(0, Location::FpuRegisterLocation(Q6)); | 5115 summary->set_in(0, Location::FpuRegisterLocation(Q6)); |
5180 summary->set_out(0, Location::RequiresRegister()); | 5116 summary->set_out(0, Location::RequiresRegister()); |
5181 } else { | 5117 } else { |
5182 summary->set_in(0, Location::RequiresFpuRegister()); | 5118 summary->set_in(0, Location::RequiresFpuRegister()); |
5183 summary->set_out(0, Location::RequiresFpuRegister()); | 5119 summary->set_out(0, Location::RequiresFpuRegister()); |
5184 } | 5120 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5220 __ vnegd(dresult1, dvalue1); | 5156 __ vnegd(dresult1, dvalue1); |
5221 break; | 5157 break; |
5222 case MethodRecognizer::kFloat64x2Abs: | 5158 case MethodRecognizer::kFloat64x2Abs: |
5223 __ vabsd(dresult0, dvalue0); | 5159 __ vabsd(dresult0, dvalue0); |
5224 __ vabsd(dresult1, dvalue1); | 5160 __ vabsd(dresult1, dvalue1); |
5225 break; | 5161 break; |
5226 case MethodRecognizer::kFloat64x2Sqrt: | 5162 case MethodRecognizer::kFloat64x2Sqrt: |
5227 __ vsqrtd(dresult0, dvalue0); | 5163 __ vsqrtd(dresult0, dvalue0); |
5228 __ vsqrtd(dresult1, dvalue1); | 5164 __ vsqrtd(dresult1, dvalue1); |
5229 break; | 5165 break; |
5230 default: UNREACHABLE(); | 5166 default: |
| 5167 UNREACHABLE(); |
5231 } | 5168 } |
5232 } | 5169 } |
5233 | 5170 |
5234 | 5171 |
5235 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, | 5172 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, |
5236 bool opt) const { | 5173 bool opt) const { |
5237 const intptr_t kNumInputs = 2; | 5174 const intptr_t kNumInputs = 2; |
5238 const intptr_t kNumTemps = 0; | 5175 const intptr_t kNumTemps = 0; |
5239 LocationSummary* summary = new(zone) LocationSummary( | 5176 LocationSummary* summary = new (zone) |
5240 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5177 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5241 summary->set_in(0, Location::RequiresFpuRegister()); | 5178 summary->set_in(0, Location::RequiresFpuRegister()); |
5242 summary->set_in(1, Location::RequiresFpuRegister()); | 5179 summary->set_in(1, Location::RequiresFpuRegister()); |
5243 summary->set_out(0, Location::SameAsFirstInput()); | 5180 summary->set_out(0, Location::SameAsFirstInput()); |
5244 return summary; | 5181 return summary; |
5245 } | 5182 } |
5246 | 5183 |
5247 | 5184 |
5248 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5185 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5249 const QRegister left = locs()->in(0).fpu_reg(); | 5186 const QRegister left = locs()->in(0).fpu_reg(); |
5250 const DRegister left0 = EvenDRegisterOf(left); | 5187 const DRegister left0 = EvenDRegisterOf(left); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5293 __ Bind(&g0); | 5230 __ Bind(&g0); |
5294 // Y lane. | 5231 // Y lane. |
5295 Label g1; | 5232 Label g1; |
5296 __ vcmpd(left1, right1); | 5233 __ vcmpd(left1, right1); |
5297 __ vmstat(); | 5234 __ vmstat(); |
5298 __ b(&g1, GT); | 5235 __ b(&g1, GT); |
5299 __ vmovd(left1, right1); | 5236 __ vmovd(left1, right1); |
5300 __ Bind(&g1); | 5237 __ Bind(&g1); |
5301 break; | 5238 break; |
5302 } | 5239 } |
5303 default: UNREACHABLE(); | 5240 default: |
| 5241 UNREACHABLE(); |
5304 } | 5242 } |
5305 } | 5243 } |
5306 | 5244 |
5307 | 5245 |
5308 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary( | 5246 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, |
5309 Zone* zone, bool opt) const { | 5247 bool opt) const { |
5310 const intptr_t kNumInputs = 4; | 5248 const intptr_t kNumInputs = 4; |
5311 const intptr_t kNumTemps = 0; | 5249 const intptr_t kNumTemps = 0; |
5312 LocationSummary* summary = new(zone) LocationSummary( | 5250 LocationSummary* summary = new (zone) |
5313 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5251 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5314 summary->set_in(0, Location::RequiresRegister()); | 5252 summary->set_in(0, Location::RequiresRegister()); |
5315 summary->set_in(1, Location::RequiresRegister()); | 5253 summary->set_in(1, Location::RequiresRegister()); |
5316 summary->set_in(2, Location::RequiresRegister()); | 5254 summary->set_in(2, Location::RequiresRegister()); |
5317 summary->set_in(3, Location::RequiresRegister()); | 5255 summary->set_in(3, Location::RequiresRegister()); |
5318 summary->set_out(0, Location::RequiresRegister()); | 5256 summary->set_out(0, Location::RequiresRegister()); |
5319 return summary; | 5257 return summary; |
5320 } | 5258 } |
5321 | 5259 |
5322 | 5260 |
5323 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5261 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5324 const Register v0 = locs()->in(0).reg(); | 5262 const Register v0 = locs()->in(0).reg(); |
5325 const Register v1 = locs()->in(1).reg(); | 5263 const Register v1 = locs()->in(1).reg(); |
5326 const Register v2 = locs()->in(2).reg(); | 5264 const Register v2 = locs()->in(2).reg(); |
5327 const Register v3 = locs()->in(3).reg(); | 5265 const Register v3 = locs()->in(3).reg(); |
5328 const QRegister result = locs()->out(0).fpu_reg(); | 5266 const QRegister result = locs()->out(0).fpu_reg(); |
5329 const DRegister dresult0 = EvenDRegisterOf(result); | 5267 const DRegister dresult0 = EvenDRegisterOf(result); |
5330 const DRegister dresult1 = OddDRegisterOf(result); | 5268 const DRegister dresult1 = OddDRegisterOf(result); |
5331 __ veorq(result, result, result); | 5269 __ veorq(result, result, result); |
5332 __ vmovdrr(dresult0, v0, v1); | 5270 __ vmovdrr(dresult0, v0, v1); |
5333 __ vmovdrr(dresult1, v2, v3); | 5271 __ vmovdrr(dresult1, v2, v3); |
5334 } | 5272 } |
5335 | 5273 |
5336 | 5274 |
5337 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 5275 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
5338 Zone* zone, bool opt) const { | 5276 Zone* zone, |
| 5277 bool opt) const { |
5339 const intptr_t kNumInputs = 4; | 5278 const intptr_t kNumInputs = 4; |
5340 const intptr_t kNumTemps = 1; | 5279 const intptr_t kNumTemps = 1; |
5341 LocationSummary* summary = new(zone) LocationSummary( | 5280 LocationSummary* summary = new (zone) |
5342 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5281 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5343 summary->set_in(0, Location::RequiresRegister()); | 5282 summary->set_in(0, Location::RequiresRegister()); |
5344 summary->set_in(1, Location::RequiresRegister()); | 5283 summary->set_in(1, Location::RequiresRegister()); |
5345 summary->set_in(2, Location::RequiresRegister()); | 5284 summary->set_in(2, Location::RequiresRegister()); |
5346 summary->set_in(3, Location::RequiresRegister()); | 5285 summary->set_in(3, Location::RequiresRegister()); |
5347 summary->set_temp(0, Location::RequiresRegister()); | 5286 summary->set_temp(0, Location::RequiresRegister()); |
5348 summary->set_out(0, Location::RequiresRegister()); | 5287 summary->set_out(0, Location::RequiresRegister()); |
5349 return summary; | 5288 return summary; |
5350 } | 5289 } |
5351 | 5290 |
5352 | 5291 |
(...skipping 22 matching lines...) Expand all Loading... |
5375 | 5314 |
5376 __ cmp(v3, Operand(IP)); | 5315 __ cmp(v3, Operand(IP)); |
5377 __ vmovdr(dresult1, 1, temp, EQ); | 5316 __ vmovdr(dresult1, 1, temp, EQ); |
5378 } | 5317 } |
5379 | 5318 |
5380 | 5319 |
5381 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, | 5320 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, |
5382 bool opt) const { | 5321 bool opt) const { |
5383 const intptr_t kNumInputs = 1; | 5322 const intptr_t kNumInputs = 1; |
5384 const intptr_t kNumTemps = 0; | 5323 const intptr_t kNumTemps = 0; |
5385 LocationSummary* summary = new(zone) LocationSummary( | 5324 LocationSummary* summary = new (zone) |
5386 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5325 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5387 // Low (< 7) Q registers are needed for the vmovrs instruction. | 5326 // Low (< 7) Q registers are needed for the vmovrs instruction. |
5388 summary->set_in(0, Location::FpuRegisterLocation(Q6)); | 5327 summary->set_in(0, Location::FpuRegisterLocation(Q6)); |
5389 summary->set_out(0, Location::RequiresRegister()); | 5328 summary->set_out(0, Location::RequiresRegister()); |
5390 return summary; | 5329 return summary; |
5391 } | 5330 } |
5392 | 5331 |
5393 | 5332 |
5394 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5333 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5395 const QRegister value = locs()->in(0).fpu_reg(); | 5334 const QRegister value = locs()->in(0).fpu_reg(); |
5396 const Register result = locs()->out(0).reg(); | 5335 const Register result = locs()->out(0).reg(); |
(...skipping 11 matching lines...) Expand all Loading... |
5408 break; | 5347 break; |
5409 case MethodRecognizer::kInt32x4GetFlagY: | 5348 case MethodRecognizer::kInt32x4GetFlagY: |
5410 __ vmovrs(result, svalue1); | 5349 __ vmovrs(result, svalue1); |
5411 break; | 5350 break; |
5412 case MethodRecognizer::kInt32x4GetFlagZ: | 5351 case MethodRecognizer::kInt32x4GetFlagZ: |
5413 __ vmovrs(result, svalue2); | 5352 __ vmovrs(result, svalue2); |
5414 break; | 5353 break; |
5415 case MethodRecognizer::kInt32x4GetFlagW: | 5354 case MethodRecognizer::kInt32x4GetFlagW: |
5416 __ vmovrs(result, svalue3); | 5355 __ vmovrs(result, svalue3); |
5417 break; | 5356 break; |
5418 default: UNREACHABLE(); | 5357 default: |
| 5358 UNREACHABLE(); |
5419 } | 5359 } |
5420 | 5360 |
5421 __ tst(result, Operand(result)); | 5361 __ tst(result, Operand(result)); |
5422 __ LoadObject(result, Bool::True(), NE); | 5362 __ LoadObject(result, Bool::True(), NE); |
5423 __ LoadObject(result, Bool::False(), EQ); | 5363 __ LoadObject(result, Bool::False(), EQ); |
5424 } | 5364 } |
5425 | 5365 |
5426 | 5366 |
5427 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, | 5367 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, |
5428 bool opt) const { | 5368 bool opt) const { |
5429 const intptr_t kNumInputs = 3; | 5369 const intptr_t kNumInputs = 3; |
5430 const intptr_t kNumTemps = 1; | 5370 const intptr_t kNumTemps = 1; |
5431 LocationSummary* summary = new(zone) LocationSummary( | 5371 LocationSummary* summary = new (zone) |
5432 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5372 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5433 summary->set_in(0, Location::RequiresFpuRegister()); | 5373 summary->set_in(0, Location::RequiresFpuRegister()); |
5434 summary->set_in(1, Location::RequiresFpuRegister()); | 5374 summary->set_in(1, Location::RequiresFpuRegister()); |
5435 summary->set_in(2, Location::RequiresFpuRegister()); | 5375 summary->set_in(2, Location::RequiresFpuRegister()); |
5436 summary->set_temp(0, Location::RequiresFpuRegister()); | 5376 summary->set_temp(0, Location::RequiresFpuRegister()); |
5437 summary->set_out(0, Location::RequiresFpuRegister()); | 5377 summary->set_out(0, Location::RequiresFpuRegister()); |
5438 return summary; | 5378 return summary; |
5439 } | 5379 } |
5440 | 5380 |
5441 | 5381 |
5442 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5382 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(...skipping 13 matching lines...) Expand all Loading... |
5456 __ vandq(temp, temp, falseValue); | 5396 __ vandq(temp, temp, falseValue); |
5457 // out = mask | temp. | 5397 // out = mask | temp. |
5458 __ vorrq(out, mask, temp); | 5398 __ vorrq(out, mask, temp); |
5459 } | 5399 } |
5460 | 5400 |
5461 | 5401 |
5462 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, | 5402 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, |
5463 bool opt) const { | 5403 bool opt) const { |
5464 const intptr_t kNumInputs = 2; | 5404 const intptr_t kNumInputs = 2; |
5465 const intptr_t kNumTemps = 0; | 5405 const intptr_t kNumTemps = 0; |
5466 LocationSummary* summary = new(zone) LocationSummary( | 5406 LocationSummary* summary = new (zone) |
5467 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5407 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5468 summary->set_in(0, Location::RequiresFpuRegister()); | 5408 summary->set_in(0, Location::RequiresFpuRegister()); |
5469 summary->set_in(1, Location::RequiresRegister()); | 5409 summary->set_in(1, Location::RequiresRegister()); |
5470 summary->set_out(0, Location::RequiresFpuRegister()); | 5410 summary->set_out(0, Location::RequiresFpuRegister()); |
5471 return summary; | 5411 return summary; |
5472 } | 5412 } |
5473 | 5413 |
5474 | 5414 |
5475 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5415 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5476 const QRegister mask = locs()->in(0).fpu_reg(); | 5416 const QRegister mask = locs()->in(0).fpu_reg(); |
5477 const Register flag = locs()->in(1).reg(); | 5417 const Register flag = locs()->in(1).reg(); |
(...skipping 15 matching lines...) Expand all Loading... |
5493 break; | 5433 break; |
5494 case MethodRecognizer::kInt32x4WithFlagY: | 5434 case MethodRecognizer::kInt32x4WithFlagY: |
5495 __ vmovdr(dresult0, 1, TMP); | 5435 __ vmovdr(dresult0, 1, TMP); |
5496 break; | 5436 break; |
5497 case MethodRecognizer::kInt32x4WithFlagZ: | 5437 case MethodRecognizer::kInt32x4WithFlagZ: |
5498 __ vmovdr(dresult1, 0, TMP); | 5438 __ vmovdr(dresult1, 0, TMP); |
5499 break; | 5439 break; |
5500 case MethodRecognizer::kInt32x4WithFlagW: | 5440 case MethodRecognizer::kInt32x4WithFlagW: |
5501 __ vmovdr(dresult1, 1, TMP); | 5441 __ vmovdr(dresult1, 1, TMP); |
5502 break; | 5442 break; |
5503 default: UNREACHABLE(); | 5443 default: |
| 5444 UNREACHABLE(); |
5504 } | 5445 } |
5505 } | 5446 } |
5506 | 5447 |
5507 | 5448 |
5508 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, | 5449 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, |
5509 bool opt) const { | 5450 bool opt) const { |
5510 const intptr_t kNumInputs = 1; | 5451 const intptr_t kNumInputs = 1; |
5511 const intptr_t kNumTemps = 0; | 5452 const intptr_t kNumTemps = 0; |
5512 LocationSummary* summary = new(zone) LocationSummary( | 5453 LocationSummary* summary = new (zone) |
5513 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5454 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5514 summary->set_in(0, Location::RequiresFpuRegister()); | 5455 summary->set_in(0, Location::RequiresFpuRegister()); |
5515 summary->set_out(0, Location::RequiresFpuRegister()); | 5456 summary->set_out(0, Location::RequiresFpuRegister()); |
5516 return summary; | 5457 return summary; |
5517 } | 5458 } |
5518 | 5459 |
5519 | 5460 |
5520 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5461 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5521 const QRegister value = locs()->in(0).fpu_reg(); | 5462 const QRegister value = locs()->in(0).fpu_reg(); |
5522 const QRegister result = locs()->out(0).fpu_reg(); | 5463 const QRegister result = locs()->out(0).fpu_reg(); |
5523 | 5464 |
5524 if (value != result) { | 5465 if (value != result) { |
5525 __ vmovq(result, value); | 5466 __ vmovq(result, value); |
5526 } | 5467 } |
5527 } | 5468 } |
5528 | 5469 |
5529 | 5470 |
5530 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, | 5471 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, |
5531 bool opt) const { | 5472 bool opt) const { |
5532 const intptr_t kNumInputs = 2; | 5473 const intptr_t kNumInputs = 2; |
5533 const intptr_t kNumTemps = 0; | 5474 const intptr_t kNumTemps = 0; |
5534 LocationSummary* summary = new(zone) LocationSummary( | 5475 LocationSummary* summary = new (zone) |
5535 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5476 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5536 summary->set_in(0, Location::RequiresFpuRegister()); | 5477 summary->set_in(0, Location::RequiresFpuRegister()); |
5537 summary->set_in(1, Location::RequiresFpuRegister()); | 5478 summary->set_in(1, Location::RequiresFpuRegister()); |
5538 summary->set_out(0, Location::RequiresFpuRegister()); | 5479 summary->set_out(0, Location::RequiresFpuRegister()); |
5539 return summary; | 5480 return summary; |
5540 } | 5481 } |
5541 | 5482 |
5542 | 5483 |
5543 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5484 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5544 const QRegister left = locs()->in(0).fpu_reg(); | 5485 const QRegister left = locs()->in(0).fpu_reg(); |
5545 const QRegister right = locs()->in(1).fpu_reg(); | 5486 const QRegister right = locs()->in(1).fpu_reg(); |
5546 const QRegister result = locs()->out(0).fpu_reg(); | 5487 const QRegister result = locs()->out(0).fpu_reg(); |
5547 switch (op_kind()) { | 5488 switch (op_kind()) { |
5548 case Token::kBIT_AND: __ vandq(result, left, right); break; | 5489 case Token::kBIT_AND: |
5549 case Token::kBIT_OR: __ vorrq(result, left, right); break; | 5490 __ vandq(result, left, right); |
5550 case Token::kBIT_XOR: __ veorq(result, left, right); break; | 5491 break; |
5551 case Token::kADD: __ vaddqi(kWord, result, left, right); break; | 5492 case Token::kBIT_OR: |
5552 case Token::kSUB: __ vsubqi(kWord, result, left, right); break; | 5493 __ vorrq(result, left, right); |
5553 default: UNREACHABLE(); | 5494 break; |
| 5495 case Token::kBIT_XOR: |
| 5496 __ veorq(result, left, right); |
| 5497 break; |
| 5498 case Token::kADD: |
| 5499 __ vaddqi(kWord, result, left, right); |
| 5500 break; |
| 5501 case Token::kSUB: |
| 5502 __ vsubqi(kWord, result, left, right); |
| 5503 break; |
| 5504 default: |
| 5505 UNREACHABLE(); |
5554 } | 5506 } |
5555 } | 5507 } |
5556 | 5508 |
5557 | 5509 |
5558 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 5510 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |
5559 bool opt) const { | 5511 bool opt) const { |
5560 ASSERT((kind() == MathUnaryInstr::kSqrt) || | 5512 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
5561 (kind() == MathUnaryInstr::kDoubleSquare)); | 5513 (kind() == MathUnaryInstr::kDoubleSquare)); |
5562 const intptr_t kNumInputs = 1; | 5514 const intptr_t kNumInputs = 1; |
5563 const intptr_t kNumTemps = 0; | 5515 const intptr_t kNumTemps = 0; |
5564 LocationSummary* summary = new(zone) LocationSummary( | 5516 LocationSummary* summary = new (zone) |
5565 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5517 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5566 summary->set_in(0, Location::RequiresFpuRegister()); | 5518 summary->set_in(0, Location::RequiresFpuRegister()); |
5567 summary->set_out(0, Location::RequiresFpuRegister()); | 5519 summary->set_out(0, Location::RequiresFpuRegister()); |
5568 return summary; | 5520 return summary; |
5569 } | 5521 } |
5570 | 5522 |
5571 | 5523 |
5572 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5524 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5573 if (kind() == MathUnaryInstr::kSqrt) { | 5525 if (kind() == MathUnaryInstr::kSqrt) { |
5574 const DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 5526 const DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
5575 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5527 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
5576 __ vsqrtd(result, val); | 5528 __ vsqrtd(result, val); |
5577 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 5529 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
5578 const DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 5530 const DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
5579 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5531 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
5580 __ vmuld(result, val, val); | 5532 __ vmuld(result, val, val); |
5581 } else { | 5533 } else { |
5582 UNREACHABLE(); | 5534 UNREACHABLE(); |
5583 } | 5535 } |
5584 } | 5536 } |
5585 | 5537 |
5586 | 5538 |
5587 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 5539 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |
5588 Zone* zone, bool opt) const { | 5540 Zone* zone, |
| 5541 bool opt) const { |
5589 const intptr_t kNumTemps = 0; | 5542 const intptr_t kNumTemps = 0; |
5590 LocationSummary* summary = new(zone) LocationSummary( | 5543 LocationSummary* summary = new (zone) |
5591 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5544 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
5592 summary->set_in(0, Location::RegisterLocation(R0)); | 5545 summary->set_in(0, Location::RegisterLocation(R0)); |
5593 summary->set_in(1, Location::RegisterLocation(R1)); | 5546 summary->set_in(1, Location::RegisterLocation(R1)); |
5594 summary->set_in(2, Location::RegisterLocation(R2)); | 5547 summary->set_in(2, Location::RegisterLocation(R2)); |
5595 summary->set_in(3, Location::RegisterLocation(R3)); | 5548 summary->set_in(3, Location::RegisterLocation(R3)); |
5596 summary->set_out(0, Location::RegisterLocation(R0)); | 5549 summary->set_out(0, Location::RegisterLocation(R0)); |
5597 return summary; | 5550 return summary; |
5598 } | 5551 } |
5599 | 5552 |
5600 | 5553 |
5601 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 5554 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |
5602 FlowGraphCompiler* compiler) { | 5555 FlowGraphCompiler* compiler) { |
5603 | |
5604 // Call the function. | 5556 // Call the function. |
5605 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 5557 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |
5606 } | 5558 } |
5607 | 5559 |
5608 | 5560 |
5609 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 5561 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |
5610 bool opt) const { | 5562 bool opt) const { |
5611 if (result_cid() == kDoubleCid) { | 5563 if (result_cid() == kDoubleCid) { |
5612 const intptr_t kNumInputs = 2; | 5564 const intptr_t kNumInputs = 2; |
5613 const intptr_t kNumTemps = 1; | 5565 const intptr_t kNumTemps = 1; |
5614 LocationSummary* summary = new(zone) LocationSummary( | 5566 LocationSummary* summary = new (zone) |
5615 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5567 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5616 summary->set_in(0, Location::RequiresFpuRegister()); | 5568 summary->set_in(0, Location::RequiresFpuRegister()); |
5617 summary->set_in(1, Location::RequiresFpuRegister()); | 5569 summary->set_in(1, Location::RequiresFpuRegister()); |
5618 // Reuse the left register so that code can be made shorter. | 5570 // Reuse the left register so that code can be made shorter. |
5619 summary->set_out(0, Location::SameAsFirstInput()); | 5571 summary->set_out(0, Location::SameAsFirstInput()); |
5620 summary->set_temp(0, Location::RequiresRegister()); | 5572 summary->set_temp(0, Location::RequiresRegister()); |
5621 return summary; | 5573 return summary; |
5622 } | 5574 } |
5623 ASSERT(result_cid() == kSmiCid); | 5575 ASSERT(result_cid() == kSmiCid); |
5624 const intptr_t kNumInputs = 2; | 5576 const intptr_t kNumInputs = 2; |
5625 const intptr_t kNumTemps = 0; | 5577 const intptr_t kNumTemps = 0; |
5626 LocationSummary* summary = new(zone) LocationSummary( | 5578 LocationSummary* summary = new (zone) |
5627 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5579 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5628 summary->set_in(0, Location::RequiresRegister()); | 5580 summary->set_in(0, Location::RequiresRegister()); |
5629 summary->set_in(1, Location::RequiresRegister()); | 5581 summary->set_in(1, Location::RequiresRegister()); |
5630 // Reuse the left register so that code can be made shorter. | 5582 // Reuse the left register so that code can be made shorter. |
5631 summary->set_out(0, Location::SameAsFirstInput()); | 5583 summary->set_out(0, Location::SameAsFirstInput()); |
5632 return summary; | 5584 return summary; |
5633 } | 5585 } |
5634 | 5586 |
5635 | 5587 |
5636 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5588 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5637 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 5589 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5689 } else { | 5641 } else { |
5690 __ mov(result, Operand(right), LT); | 5642 __ mov(result, Operand(right), LT); |
5691 } | 5643 } |
5692 } | 5644 } |
5693 | 5645 |
5694 | 5646 |
5695 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 5647 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |
5696 bool opt) const { | 5648 bool opt) const { |
5697 const intptr_t kNumInputs = 1; | 5649 const intptr_t kNumInputs = 1; |
5698 const intptr_t kNumTemps = 0; | 5650 const intptr_t kNumTemps = 0; |
5699 LocationSummary* summary = new(zone) LocationSummary( | 5651 LocationSummary* summary = new (zone) |
5700 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5652 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5701 summary->set_in(0, Location::RequiresRegister()); | 5653 summary->set_in(0, Location::RequiresRegister()); |
5702 // We make use of 3-operand instructions by not requiring result register | 5654 // We make use of 3-operand instructions by not requiring result register |
5703 // to be identical to first input register as on Intel. | 5655 // to be identical to first input register as on Intel. |
5704 summary->set_out(0, Location::RequiresRegister()); | 5656 summary->set_out(0, Location::RequiresRegister()); |
5705 return summary; | 5657 return summary; |
5706 } | 5658 } |
5707 | 5659 |
5708 | 5660 |
5709 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5661 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5710 const Register value = locs()->in(0).reg(); | 5662 const Register value = locs()->in(0).reg(); |
(...skipping 13 matching lines...) Expand all Loading... |
5724 default: | 5676 default: |
5725 UNREACHABLE(); | 5677 UNREACHABLE(); |
5726 } | 5678 } |
5727 } | 5679 } |
5728 | 5680 |
5729 | 5681 |
5730 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 5682 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
5731 bool opt) const { | 5683 bool opt) const { |
5732 const intptr_t kNumInputs = 1; | 5684 const intptr_t kNumInputs = 1; |
5733 const intptr_t kNumTemps = 0; | 5685 const intptr_t kNumTemps = 0; |
5734 LocationSummary* summary = new(zone) LocationSummary( | 5686 LocationSummary* summary = new (zone) |
5735 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5687 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5736 summary->set_in(0, Location::RequiresFpuRegister()); | 5688 summary->set_in(0, Location::RequiresFpuRegister()); |
5737 summary->set_out(0, Location::RequiresFpuRegister()); | 5689 summary->set_out(0, Location::RequiresFpuRegister()); |
5738 return summary; | 5690 return summary; |
5739 } | 5691 } |
5740 | 5692 |
5741 | 5693 |
5742 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5694 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5743 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5695 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
5744 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 5696 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
5745 __ vnegd(result, value); | 5697 __ vnegd(result, value); |
5746 } | 5698 } |
5747 | 5699 |
5748 | 5700 |
5749 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 5701 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |
5750 bool opt) const { | 5702 bool opt) const { |
5751 const intptr_t kNumInputs = 1; | 5703 const intptr_t kNumInputs = 1; |
5752 const intptr_t kNumTemps = 0; | 5704 const intptr_t kNumTemps = 0; |
5753 LocationSummary* result = new(zone) LocationSummary( | 5705 LocationSummary* result = new (zone) |
5754 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5706 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5755 result->set_in(0, Location::RequiresRegister()); | 5707 result->set_in(0, Location::RequiresRegister()); |
5756 result->set_out(0, Location::RequiresFpuRegister()); | 5708 result->set_out(0, Location::RequiresFpuRegister()); |
5757 return result; | 5709 return result; |
5758 } | 5710 } |
5759 | 5711 |
5760 | 5712 |
5761 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5713 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5762 const Register value = locs()->in(0).reg(); | 5714 const Register value = locs()->in(0).reg(); |
5763 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5715 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
5764 __ vmovdr(DTMP, 0, value); | 5716 __ vmovdr(DTMP, 0, value); |
5765 __ vcvtdi(result, STMP); | 5717 __ vcvtdi(result, STMP); |
5766 } | 5718 } |
5767 | 5719 |
5768 | 5720 |
5769 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 5721 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |
5770 bool opt) const { | 5722 bool opt) const { |
5771 const intptr_t kNumInputs = 1; | 5723 const intptr_t kNumInputs = 1; |
5772 const intptr_t kNumTemps = 0; | 5724 const intptr_t kNumTemps = 0; |
5773 LocationSummary* result = new(zone) LocationSummary( | 5725 LocationSummary* result = new (zone) |
5774 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5726 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5775 result->set_in(0, Location::RequiresRegister()); | 5727 result->set_in(0, Location::RequiresRegister()); |
5776 result->set_out(0, Location::RequiresFpuRegister()); | 5728 result->set_out(0, Location::RequiresFpuRegister()); |
5777 return result; | 5729 return result; |
5778 } | 5730 } |
5779 | 5731 |
5780 | 5732 |
5781 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5733 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5782 const Register value = locs()->in(0).reg(); | 5734 const Register value = locs()->in(0).reg(); |
5783 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5735 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
5784 __ SmiUntag(IP, value); | 5736 __ SmiUntag(IP, value); |
(...skipping 11 matching lines...) Expand all Loading... |
5796 | 5748 |
5797 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5749 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5798 UNIMPLEMENTED(); | 5750 UNIMPLEMENTED(); |
5799 } | 5751 } |
5800 | 5752 |
5801 | 5753 |
5802 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 5754 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |
5803 bool opt) const { | 5755 bool opt) const { |
5804 const intptr_t kNumInputs = 1; | 5756 const intptr_t kNumInputs = 1; |
5805 const intptr_t kNumTemps = 0; | 5757 const intptr_t kNumTemps = 0; |
5806 LocationSummary* result = new(zone) LocationSummary( | 5758 LocationSummary* result = new (zone) |
5807 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5759 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
5808 result->set_in(0, Location::RegisterLocation(R1)); | 5760 result->set_in(0, Location::RegisterLocation(R1)); |
5809 result->set_out(0, Location::RegisterLocation(R0)); | 5761 result->set_out(0, Location::RegisterLocation(R0)); |
5810 return result; | 5762 return result; |
5811 } | 5763 } |
5812 | 5764 |
5813 | 5765 |
5814 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5766 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5815 const Register result = locs()->out(0).reg(); | 5767 const Register result = locs()->out(0).reg(); |
5816 const Register value_obj = locs()->in(0).reg(); | 5768 const Register value_obj = locs()->in(0).reg(); |
5817 ASSERT(result == R0); | 5769 ASSERT(result == R0); |
(...skipping 17 matching lines...) Expand all Loading... |
5835 __ b(&done, PL); | 5787 __ b(&done, PL); |
5836 | 5788 |
5837 __ Bind(&do_call); | 5789 __ Bind(&do_call); |
5838 __ Push(value_obj); | 5790 __ Push(value_obj); |
5839 ASSERT(instance_call()->HasICData()); | 5791 ASSERT(instance_call()->HasICData()); |
5840 const ICData& ic_data = *instance_call()->ic_data(); | 5792 const ICData& ic_data = *instance_call()->ic_data(); |
5841 ASSERT((ic_data.NumberOfChecks() == 1)); | 5793 ASSERT((ic_data.NumberOfChecks() == 1)); |
5842 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 5794 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
5843 | 5795 |
5844 const intptr_t kNumberOfArguments = 1; | 5796 const intptr_t kNumberOfArguments = 1; |
5845 compiler->GenerateStaticCall(deopt_id(), | 5797 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, |
5846 instance_call()->token_pos(), | |
5847 target, | |
5848 kNumberOfArguments, | 5798 kNumberOfArguments, |
5849 Object::null_array(), // No argument names., | 5799 Object::null_array(), // No argument names., |
5850 locs(), | 5800 locs(), ICData::Handle()); |
5851 ICData::Handle()); | |
5852 __ Bind(&done); | 5801 __ Bind(&done); |
5853 } | 5802 } |
5854 | 5803 |
5855 | 5804 |
5856 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 5805 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |
5857 bool opt) const { | 5806 bool opt) const { |
5858 const intptr_t kNumInputs = 1; | 5807 const intptr_t kNumInputs = 1; |
5859 const intptr_t kNumTemps = 0; | 5808 const intptr_t kNumTemps = 0; |
5860 LocationSummary* result = new(zone) LocationSummary( | 5809 LocationSummary* result = new (zone) |
5861 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5810 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5862 result->set_in(0, Location::RequiresFpuRegister()); | 5811 result->set_in(0, Location::RequiresFpuRegister()); |
5863 result->set_out(0, Location::RequiresRegister()); | 5812 result->set_out(0, Location::RequiresRegister()); |
5864 return result; | 5813 return result; |
5865 } | 5814 } |
5866 | 5815 |
5867 | 5816 |
5868 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5817 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5869 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 5818 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
5870 const Register result = locs()->out(0).reg(); | 5819 const Register result = locs()->out(0).reg(); |
5871 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 5820 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
(...skipping 21 matching lines...) Expand all Loading... |
5893 | 5842 |
5894 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5843 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5895 UNIMPLEMENTED(); | 5844 UNIMPLEMENTED(); |
5896 } | 5845 } |
5897 | 5846 |
5898 | 5847 |
5899 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 5848 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |
5900 bool opt) const { | 5849 bool opt) const { |
5901 const intptr_t kNumInputs = 1; | 5850 const intptr_t kNumInputs = 1; |
5902 const intptr_t kNumTemps = 0; | 5851 const intptr_t kNumTemps = 0; |
5903 LocationSummary* result = new(zone) LocationSummary( | 5852 LocationSummary* result = new (zone) |
5904 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5853 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5905 // Low (<= Q7) Q registers are needed for the conversion instructions. | 5854 // Low (<= Q7) Q registers are needed for the conversion instructions. |
5906 result->set_in(0, Location::RequiresFpuRegister()); | 5855 result->set_in(0, Location::RequiresFpuRegister()); |
5907 result->set_out(0, Location::FpuRegisterLocation(Q7)); | 5856 result->set_out(0, Location::FpuRegisterLocation(Q7)); |
5908 return result; | 5857 return result; |
5909 } | 5858 } |
5910 | 5859 |
5911 | 5860 |
5912 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5861 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5913 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 5862 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
5914 const SRegister result = | 5863 const SRegister result = |
5915 EvenSRegisterOf(EvenDRegisterOf(locs()->out(0).fpu_reg())); | 5864 EvenSRegisterOf(EvenDRegisterOf(locs()->out(0).fpu_reg())); |
5916 __ vcvtsd(result, value); | 5865 __ vcvtsd(result, value); |
5917 } | 5866 } |
5918 | 5867 |
5919 | 5868 |
5920 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 5869 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |
5921 bool opt) const { | 5870 bool opt) const { |
5922 const intptr_t kNumInputs = 1; | 5871 const intptr_t kNumInputs = 1; |
5923 const intptr_t kNumTemps = 0; | 5872 const intptr_t kNumTemps = 0; |
5924 LocationSummary* result = new(zone) LocationSummary( | 5873 LocationSummary* result = new (zone) |
5925 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5874 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5926 // Low (<= Q7) Q registers are needed for the conversion instructions. | 5875 // Low (<= Q7) Q registers are needed for the conversion instructions. |
5927 result->set_in(0, Location::FpuRegisterLocation(Q7)); | 5876 result->set_in(0, Location::FpuRegisterLocation(Q7)); |
5928 result->set_out(0, Location::RequiresFpuRegister()); | 5877 result->set_out(0, Location::RequiresFpuRegister()); |
5929 return result; | 5878 return result; |
5930 } | 5879 } |
5931 | 5880 |
5932 | 5881 |
5933 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5882 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5934 const SRegister value = | 5883 const SRegister value = |
5935 EvenSRegisterOf(EvenDRegisterOf(locs()->in(0).fpu_reg())); | 5884 EvenSRegisterOf(EvenDRegisterOf(locs()->in(0).fpu_reg())); |
5936 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5885 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
5937 __ vcvtds(result, value); | 5886 __ vcvtds(result, value); |
5938 } | 5887 } |
5939 | 5888 |
5940 | 5889 |
5941 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 5890 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |
5942 bool opt) const { | 5891 bool opt) const { |
5943 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 5892 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
5944 const intptr_t kNumTemps = | 5893 const intptr_t kNumTemps = |
5945 (TargetCPUFeatures::hardfp_supported()) ? | 5894 (TargetCPUFeatures::hardfp_supported()) |
5946 ((recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0) : 4; | 5895 ? ((recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0) |
5947 LocationSummary* result = new(zone) LocationSummary( | 5896 : 4; |
5948 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5897 LocationSummary* result = new (zone) |
| 5898 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
5949 result->set_in(0, Location::FpuRegisterLocation(Q0)); | 5899 result->set_in(0, Location::FpuRegisterLocation(Q0)); |
5950 if (InputCount() == 2) { | 5900 if (InputCount() == 2) { |
5951 result->set_in(1, Location::FpuRegisterLocation(Q1)); | 5901 result->set_in(1, Location::FpuRegisterLocation(Q1)); |
5952 } | 5902 } |
5953 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5903 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
5954 result->set_temp(0, Location::RegisterLocation(R2)); | 5904 result->set_temp(0, Location::RegisterLocation(R2)); |
5955 if (!TargetCPUFeatures::hardfp_supported()) { | 5905 if (!TargetCPUFeatures::hardfp_supported()) { |
5956 result->set_temp(1, Location::RegisterLocation(R0)); | 5906 result->set_temp(1, Location::RegisterLocation(R0)); |
5957 result->set_temp(2, Location::RegisterLocation(R1)); | 5907 result->set_temp(2, Location::RegisterLocation(R1)); |
5958 result->set_temp(3, Location::RegisterLocation(R3)); | 5908 result->set_temp(3, Location::RegisterLocation(R3)); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5997 const DRegister saved_base = OddDRegisterOf(locs->in(0).fpu_reg()); | 5947 const DRegister saved_base = OddDRegisterOf(locs->in(0).fpu_reg()); |
5998 ASSERT((base == result) && (result != saved_base)); | 5948 ASSERT((base == result) && (result != saved_base)); |
5999 | 5949 |
6000 Label skip_call, try_sqrt, check_base, return_nan; | 5950 Label skip_call, try_sqrt, check_base, return_nan; |
6001 __ vmovd(saved_base, base); | 5951 __ vmovd(saved_base, base); |
6002 __ LoadDImmediate(result, 1.0, temp); | 5952 __ LoadDImmediate(result, 1.0, temp); |
6003 // exponent == 0.0 -> return 1.0; | 5953 // exponent == 0.0 -> return 1.0; |
6004 __ vcmpdz(exp); | 5954 __ vcmpdz(exp); |
6005 __ vmstat(); | 5955 __ vmstat(); |
6006 __ b(&check_base, VS); // NaN -> check base. | 5956 __ b(&check_base, VS); // NaN -> check base. |
6007 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. | 5957 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. |
6008 | 5958 |
6009 // exponent == 1.0 ? | 5959 // exponent == 1.0 ? |
6010 __ vcmpd(exp, result); | 5960 __ vcmpd(exp, result); |
6011 __ vmstat(); | 5961 __ vmstat(); |
6012 Label return_base; | 5962 Label return_base; |
6013 __ b(&return_base, EQ); | 5963 __ b(&return_base, EQ); |
6014 | 5964 |
6015 // exponent == 2.0 ? | 5965 // exponent == 2.0 ? |
6016 __ LoadDImmediate(DTMP, 2.0, temp); | 5966 __ LoadDImmediate(DTMP, 2.0, temp); |
6017 __ vcmpd(exp, DTMP); | 5967 __ vcmpd(exp, DTMP); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6127 __ vmovdrr(D1, R2, R3); | 6077 __ vmovdrr(D1, R2, R3); |
6128 } | 6078 } |
6129 } | 6079 } |
6130 | 6080 |
6131 | 6081 |
6132 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 6082 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |
6133 bool opt) const { | 6083 bool opt) const { |
6134 // Only use this instruction in optimized code. | 6084 // Only use this instruction in optimized code. |
6135 ASSERT(opt); | 6085 ASSERT(opt); |
6136 const intptr_t kNumInputs = 1; | 6086 const intptr_t kNumInputs = 1; |
6137 LocationSummary* summary = new(zone) LocationSummary( | 6087 LocationSummary* summary = |
6138 zone, kNumInputs, 0, LocationSummary::kNoCall); | 6088 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
6139 if (representation() == kUnboxedDouble) { | 6089 if (representation() == kUnboxedDouble) { |
6140 if (index() == 0) { | 6090 if (index() == 0) { |
6141 summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), | 6091 summary->set_in( |
6142 Location::Any())); | 6092 0, Location::Pair(Location::RequiresFpuRegister(), Location::Any())); |
6143 } else { | 6093 } else { |
6144 ASSERT(index() == 1); | 6094 ASSERT(index() == 1); |
6145 summary->set_in(0, Location::Pair(Location::Any(), | 6095 summary->set_in( |
6146 Location::RequiresFpuRegister())); | 6096 0, Location::Pair(Location::Any(), Location::RequiresFpuRegister())); |
6147 } | 6097 } |
6148 summary->set_out(0, Location::RequiresFpuRegister()); | 6098 summary->set_out(0, Location::RequiresFpuRegister()); |
6149 } else { | 6099 } else { |
6150 ASSERT(representation() == kTagged); | 6100 ASSERT(representation() == kTagged); |
6151 if (index() == 0) { | 6101 if (index() == 0) { |
6152 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6102 summary->set_in( |
6153 Location::Any())); | 6103 0, Location::Pair(Location::RequiresRegister(), Location::Any())); |
6154 } else { | 6104 } else { |
6155 ASSERT(index() == 1); | 6105 ASSERT(index() == 1); |
6156 summary->set_in(0, Location::Pair(Location::Any(), | 6106 summary->set_in( |
6157 Location::RequiresRegister())); | 6107 0, Location::Pair(Location::Any(), Location::RequiresRegister())); |
6158 } | 6108 } |
6159 summary->set_out(0, Location::RequiresRegister()); | 6109 summary->set_out(0, Location::RequiresRegister()); |
6160 } | 6110 } |
6161 return summary; | 6111 return summary; |
6162 } | 6112 } |
6163 | 6113 |
6164 | 6114 |
6165 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6115 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6166 ASSERT(locs()->in(0).IsPairLocation()); | 6116 ASSERT(locs()->in(0).IsPairLocation()); |
6167 PairLocation* pair = locs()->in(0).AsPairLocation(); | 6117 PairLocation* pair = locs()->in(0).AsPairLocation(); |
6168 Location in_loc = pair->At(index()); | 6118 Location in_loc = pair->At(index()); |
6169 if (representation() == kUnboxedDouble) { | 6119 if (representation() == kUnboxedDouble) { |
6170 const QRegister out = locs()->out(0).fpu_reg(); | 6120 const QRegister out = locs()->out(0).fpu_reg(); |
6171 const QRegister in = in_loc.fpu_reg(); | 6121 const QRegister in = in_loc.fpu_reg(); |
6172 __ vmovq(out, in); | 6122 __ vmovq(out, in); |
6173 } else { | 6123 } else { |
6174 ASSERT(representation() == kTagged); | 6124 ASSERT(representation() == kTagged); |
6175 const Register out = locs()->out(0).reg(); | 6125 const Register out = locs()->out(0).reg(); |
6176 const Register in = in_loc.reg(); | 6126 const Register in = in_loc.reg(); |
6177 __ mov(out, Operand(in)); | 6127 __ mov(out, Operand(in)); |
6178 } | 6128 } |
6179 } | 6129 } |
6180 | 6130 |
6181 | 6131 |
6182 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, | 6132 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, |
6183 bool opt) const { | 6133 bool opt) const { |
6184 if (kind() == MergedMathInstr::kTruncDivMod) { | 6134 if (kind() == MergedMathInstr::kTruncDivMod) { |
6185 const intptr_t kNumInputs = 2; | 6135 const intptr_t kNumInputs = 2; |
6186 const intptr_t kNumTemps = 2; | 6136 const intptr_t kNumTemps = 2; |
6187 LocationSummary* summary = new(zone) LocationSummary( | 6137 LocationSummary* summary = new (zone) |
6188 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6138 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6189 summary->set_in(0, Location::RequiresRegister()); | 6139 summary->set_in(0, Location::RequiresRegister()); |
6190 summary->set_in(1, Location::RequiresRegister()); | 6140 summary->set_in(1, Location::RequiresRegister()); |
6191 summary->set_temp(0, Location::RequiresRegister()); | 6141 summary->set_temp(0, Location::RequiresRegister()); |
6192 summary->set_temp(1, Location::RequiresFpuRegister()); | 6142 summary->set_temp(1, Location::RequiresFpuRegister()); |
6193 // Output is a pair of registers. | 6143 // Output is a pair of registers. |
6194 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6144 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
6195 Location::RequiresRegister())); | 6145 Location::RequiresRegister())); |
6196 return summary; | 6146 return summary; |
6197 } | 6147 } |
6198 UNIMPLEMENTED(); | 6148 UNIMPLEMENTED(); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6255 return; | 6205 return; |
6256 } | 6206 } |
6257 if (kind() == MergedMathInstr::kSinCos) { | 6207 if (kind() == MergedMathInstr::kSinCos) { |
6258 UNIMPLEMENTED(); | 6208 UNIMPLEMENTED(); |
6259 } | 6209 } |
6260 UNIMPLEMENTED(); | 6210 UNIMPLEMENTED(); |
6261 } | 6211 } |
6262 | 6212 |
6263 | 6213 |
6264 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 6214 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
6265 Zone* zone, bool opt) const { | 6215 Zone* zone, |
| 6216 bool opt) const { |
6266 return MakeCallSummary(zone); | 6217 return MakeCallSummary(zone); |
6267 } | 6218 } |
6268 | 6219 |
6269 | 6220 |
6270 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, | 6221 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
6271 bool opt) const { | |
6272 comparison()->InitializeLocationSummary(zone, opt); | 6222 comparison()->InitializeLocationSummary(zone, opt); |
6273 // Branches don't produce a result. | 6223 // Branches don't produce a result. |
6274 comparison()->locs()->set_out(0, Location::NoLocation()); | 6224 comparison()->locs()->set_out(0, Location::NoLocation()); |
6275 return comparison()->locs(); | 6225 return comparison()->locs(); |
6276 } | 6226 } |
6277 | 6227 |
6278 | 6228 |
6279 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6229 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6280 comparison()->EmitBranchCode(compiler, this); | 6230 comparison()->EmitBranchCode(compiler, this); |
6281 } | 6231 } |
6282 | 6232 |
6283 | 6233 |
6284 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 6234 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
6285 bool opt) const { | 6235 bool opt) const { |
6286 const intptr_t kNumInputs = 1; | 6236 const intptr_t kNumInputs = 1; |
6287 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); | 6237 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); |
6288 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 6238 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
6289 LocationSummary* summary = new(zone) LocationSummary( | 6239 LocationSummary* summary = new (zone) |
6290 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6240 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6291 summary->set_in(0, Location::RequiresRegister()); | 6241 summary->set_in(0, Location::RequiresRegister()); |
6292 if (!IsNullCheck()) { | 6242 if (!IsNullCheck()) { |
6293 summary->set_temp(0, Location::RequiresRegister()); | 6243 summary->set_temp(0, Location::RequiresRegister()); |
6294 if (need_mask_temp) { | 6244 if (need_mask_temp) { |
6295 summary->set_temp(1, Location::RequiresRegister()); | 6245 summary->set_temp(1, Location::RequiresRegister()); |
6296 } | 6246 } |
6297 } | 6247 } |
6298 return summary; | 6248 return summary; |
6299 } | 6249 } |
6300 | 6250 |
6301 | 6251 |
6302 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6252 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6303 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 6253 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass, |
6304 ICData::kDeoptCheckClass, | |
6305 licm_hoisted_ ? ICData::kHoisted : 0); | 6254 licm_hoisted_ ? ICData::kHoisted : 0); |
6306 if (IsNullCheck()) { | 6255 if (IsNullCheck()) { |
6307 __ CompareObject(locs()->in(0).reg(), Object::null_object()); | 6256 __ CompareObject(locs()->in(0).reg(), Object::null_object()); |
6308 ASSERT(DeoptIfNull() || DeoptIfNotNull()); | 6257 ASSERT(DeoptIfNull() || DeoptIfNotNull()); |
6309 Condition cond = DeoptIfNull() ? EQ : NE; | 6258 Condition cond = DeoptIfNull() ? EQ : NE; |
6310 __ b(deopt, cond); | 6259 __ b(deopt, cond); |
6311 return; | 6260 return; |
6312 } | 6261 } |
6313 | 6262 |
6314 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 6263 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
(...skipping 21 matching lines...) Expand all Loading... |
6336 // Only need mask if there are missing numbers in the range. | 6285 // Only need mask if there are missing numbers in the range. |
6337 ASSERT(cids_.length() > 2); | 6286 ASSERT(cids_.length() > 2); |
6338 Register mask_reg = locs()->temp(1).reg(); | 6287 Register mask_reg = locs()->temp(1).reg(); |
6339 __ LoadImmediate(mask_reg, 1); | 6288 __ LoadImmediate(mask_reg, 1); |
6340 __ Lsl(mask_reg, mask_reg, temp); | 6289 __ Lsl(mask_reg, mask_reg, temp); |
6341 __ TestImmediate(mask_reg, mask); | 6290 __ TestImmediate(mask_reg, mask); |
6342 __ b(deopt, EQ); | 6291 __ b(deopt, EQ); |
6343 } | 6292 } |
6344 } else { | 6293 } else { |
6345 GrowableArray<CidTarget> sorted_ic_data; | 6294 GrowableArray<CidTarget> sorted_ic_data; |
6346 FlowGraphCompiler::SortICDataByCount(unary_checks(), | 6295 FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data, |
6347 &sorted_ic_data, | |
6348 /* drop_smi = */ true); | 6296 /* drop_smi = */ true); |
6349 const intptr_t num_checks = sorted_ic_data.length(); | 6297 const intptr_t num_checks = sorted_ic_data.length(); |
6350 for (intptr_t i = 0; i < num_checks; i++) { | 6298 for (intptr_t i = 0; i < num_checks; i++) { |
6351 const intptr_t cid = sorted_ic_data[i].cid; | 6299 const intptr_t cid = sorted_ic_data[i].cid; |
6352 ASSERT(cid != kSmiCid); | 6300 ASSERT(cid != kSmiCid); |
6353 __ CompareImmediate(temp, cid); | 6301 __ CompareImmediate(temp, cid); |
6354 if (i == (num_checks - 1)) { | 6302 if (i == (num_checks - 1)) { |
6355 __ b(deopt, NE); | 6303 __ b(deopt, NE); |
6356 } else { | 6304 } else { |
6357 __ b(&is_ok, EQ); | 6305 __ b(&is_ok, EQ); |
6358 } | 6306 } |
6359 } | 6307 } |
6360 } | 6308 } |
6361 __ Bind(&is_ok); | 6309 __ Bind(&is_ok); |
6362 } | 6310 } |
6363 | 6311 |
6364 | 6312 |
6365 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 6313 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
6366 bool opt) const { | 6314 bool opt) const { |
6367 const intptr_t kNumInputs = 1; | 6315 const intptr_t kNumInputs = 1; |
6368 const intptr_t kNumTemps = 0; | 6316 const intptr_t kNumTemps = 0; |
6369 LocationSummary* summary = new(zone) LocationSummary( | 6317 LocationSummary* summary = new (zone) |
6370 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6318 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6371 summary->set_in(0, Location::RequiresRegister()); | 6319 summary->set_in(0, Location::RequiresRegister()); |
6372 return summary; | 6320 return summary; |
6373 } | 6321 } |
6374 | 6322 |
6375 | 6323 |
6376 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6324 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6377 const Register value = locs()->in(0).reg(); | 6325 const Register value = locs()->in(0).reg(); |
6378 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 6326 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, |
6379 ICData::kDeoptCheckSmi, | |
6380 licm_hoisted_ ? ICData::kHoisted : 0); | 6327 licm_hoisted_ ? ICData::kHoisted : 0); |
6381 __ BranchIfNotSmi(value, deopt); | 6328 __ BranchIfNotSmi(value, deopt); |
6382 } | 6329 } |
6383 | 6330 |
6384 | 6331 |
6385 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 6332 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
6386 bool opt) const { | 6333 bool opt) const { |
6387 const intptr_t kNumInputs = 1; | 6334 const intptr_t kNumInputs = 1; |
6388 const intptr_t kNumTemps = 0; | 6335 const intptr_t kNumTemps = 0; |
6389 LocationSummary* summary = new(zone) LocationSummary( | 6336 LocationSummary* summary = new (zone) |
6390 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6337 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6391 summary->set_in(0, Location::RequiresRegister()); | 6338 summary->set_in(0, Location::RequiresRegister()); |
6392 return summary; | 6339 return summary; |
6393 } | 6340 } |
6394 | 6341 |
6395 | 6342 |
6396 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6343 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6397 Register value = locs()->in(0).reg(); | 6344 Register value = locs()->in(0).reg(); |
6398 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 6345 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
6399 __ CompareImmediate(value, Smi::RawValue(cid_)); | 6346 __ CompareImmediate(value, Smi::RawValue(cid_)); |
6400 __ b(deopt, NE); | 6347 __ b(deopt, NE); |
6401 } | 6348 } |
6402 | 6349 |
6403 | 6350 |
6404 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, | 6351 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, |
6405 bool opt) const { | 6352 bool opt) const { |
6406 const intptr_t kNumInputs = 2; | 6353 const intptr_t kNumInputs = 2; |
6407 const intptr_t kNumTemps = 0; | 6354 const intptr_t kNumTemps = 0; |
6408 LocationSummary* locs = new(zone) LocationSummary( | 6355 LocationSummary* locs = new (zone) LocationSummary( |
6409 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 6356 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
6410 locs->set_in(kLengthPos, Location::RequiresRegister()); | 6357 locs->set_in(kLengthPos, Location::RequiresRegister()); |
6411 locs->set_in(kIndexPos, Location::RequiresRegister()); | 6358 locs->set_in(kIndexPos, Location::RequiresRegister()); |
6412 return locs; | 6359 return locs; |
6413 } | 6360 } |
6414 | 6361 |
6415 | 6362 |
6416 class RangeErrorSlowPath : public SlowPathCode { | 6363 class RangeErrorSlowPath : public SlowPathCode { |
6417 public: | 6364 public: |
6418 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) | 6365 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) |
6419 : instruction_(instruction), try_index_(try_index) { } | 6366 : instruction_(instruction), try_index_(try_index) {} |
6420 | 6367 |
6421 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 6368 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
6422 if (Assembler::EmittingComments()) { | 6369 if (Assembler::EmittingComments()) { |
6423 __ Comment("slow path check bound operation"); | 6370 __ Comment("slow path check bound operation"); |
6424 } | 6371 } |
6425 __ Bind(entry_label()); | 6372 __ Bind(entry_label()); |
6426 LocationSummary* locs = instruction_->locs(); | 6373 LocationSummary* locs = instruction_->locs(); |
6427 __ Push(locs->in(0).reg()); | 6374 __ Push(locs->in(0).reg()); |
6428 __ Push(locs->in(1).reg()); | 6375 __ Push(locs->in(1).reg()); |
6429 __ CallRuntime(kRangeErrorRuntimeEntry, 2); | 6376 __ CallRuntime(kRangeErrorRuntimeEntry, 2); |
6430 compiler->pc_descriptors_list()->AddDescriptor( | 6377 compiler->pc_descriptors_list()->AddDescriptor( |
6431 RawPcDescriptors::kOther, | 6378 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), |
6432 compiler->assembler()->CodeSize(), | 6379 instruction_->deopt_id(), instruction_->token_pos(), try_index_); |
6433 instruction_->deopt_id(), | |
6434 instruction_->token_pos(), | |
6435 try_index_); | |
6436 compiler->RecordSafepoint(locs, 2); | 6380 compiler->RecordSafepoint(locs, 2); |
6437 __ bkpt(0); | 6381 __ bkpt(0); |
6438 } | 6382 } |
6439 | 6383 |
6440 private: | 6384 private: |
6441 GenericCheckBoundInstr* instruction_; | 6385 GenericCheckBoundInstr* instruction_; |
6442 intptr_t try_index_; | 6386 intptr_t try_index_; |
6443 }; | 6387 }; |
6444 | 6388 |
6445 | 6389 |
(...skipping 12 matching lines...) Expand all Loading... |
6458 } | 6402 } |
6459 __ cmp(index, Operand(length)); | 6403 __ cmp(index, Operand(length)); |
6460 __ b(slow_path->entry_label(), CS); | 6404 __ b(slow_path->entry_label(), CS); |
6461 } | 6405 } |
6462 | 6406 |
6463 | 6407 |
6464 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 6408 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
6465 bool opt) const { | 6409 bool opt) const { |
6466 const intptr_t kNumInputs = 2; | 6410 const intptr_t kNumInputs = 2; |
6467 const intptr_t kNumTemps = 0; | 6411 const intptr_t kNumTemps = 0; |
6468 LocationSummary* locs = new(zone) LocationSummary( | 6412 LocationSummary* locs = new (zone) |
6469 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6413 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6470 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 6414 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
6471 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 6415 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
6472 return locs; | 6416 return locs; |
6473 } | 6417 } |
6474 | 6418 |
6475 | 6419 |
6476 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6420 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6477 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 6421 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |
6478 flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 6422 flags |= licm_hoisted_ ? ICData::kHoisted : 0; |
6479 Label* deopt = compiler->AddDeoptStub( | 6423 Label* deopt = |
6480 deopt_id(), | 6424 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); |
6481 ICData::kDeoptCheckArrayBound, | |
6482 flags); | |
6483 | 6425 |
6484 Location length_loc = locs()->in(kLengthPos); | 6426 Location length_loc = locs()->in(kLengthPos); |
6485 Location index_loc = locs()->in(kIndexPos); | 6427 Location index_loc = locs()->in(kIndexPos); |
6486 | 6428 |
6487 if (length_loc.IsConstant() && index_loc.IsConstant()) { | 6429 if (length_loc.IsConstant() && index_loc.IsConstant()) { |
6488 ASSERT((Smi::Cast(length_loc.constant()).Value() <= | 6430 ASSERT((Smi::Cast(length_loc.constant()).Value() <= |
6489 Smi::Cast(index_loc.constant()).Value()) || | 6431 Smi::Cast(index_loc.constant()).Value()) || |
6490 (Smi::Cast(index_loc.constant()).Value() < 0)); | 6432 (Smi::Cast(index_loc.constant()).Value() < 0)); |
6491 // Unconditionally deoptimize for constant bounds checks because they | 6433 // Unconditionally deoptimize for constant bounds checks because they |
6492 // only occur only when index is out-of-bounds. | 6434 // only occur only when index is out-of-bounds. |
(...skipping 29 matching lines...) Expand all Loading... |
6522 __ cmp(index, Operand(length)); | 6464 __ cmp(index, Operand(length)); |
6523 __ b(deopt, CS); | 6465 __ b(deopt, CS); |
6524 } | 6466 } |
6525 } | 6467 } |
6526 | 6468 |
6527 | 6469 |
6528 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, | 6470 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, |
6529 bool opt) const { | 6471 bool opt) const { |
6530 const intptr_t kNumInputs = 2; | 6472 const intptr_t kNumInputs = 2; |
6531 const intptr_t kNumTemps = 0; | 6473 const intptr_t kNumTemps = 0; |
6532 LocationSummary* summary = new(zone) LocationSummary( | 6474 LocationSummary* summary = new (zone) |
6533 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6475 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6534 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6476 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
6535 Location::RequiresRegister())); | 6477 Location::RequiresRegister())); |
6536 summary->set_in(1, Location::Pair(Location::RequiresRegister(), | 6478 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
6537 Location::RequiresRegister())); | 6479 Location::RequiresRegister())); |
6538 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6480 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
6539 Location::RequiresRegister())); | 6481 Location::RequiresRegister())); |
6540 return summary; | 6482 return summary; |
6541 } | 6483 } |
6542 | 6484 |
6543 | 6485 |
(...skipping 17 matching lines...) Expand all Loading... |
6561 __ and_(out_lo, left_lo, Operand(right_lo)); | 6503 __ and_(out_lo, left_lo, Operand(right_lo)); |
6562 __ and_(out_hi, left_hi, Operand(right_hi)); | 6504 __ and_(out_hi, left_hi, Operand(right_hi)); |
6563 break; | 6505 break; |
6564 } | 6506 } |
6565 case Token::kBIT_OR: { | 6507 case Token::kBIT_OR: { |
6566 __ orr(out_lo, left_lo, Operand(right_lo)); | 6508 __ orr(out_lo, left_lo, Operand(right_lo)); |
6567 __ orr(out_hi, left_hi, Operand(right_hi)); | 6509 __ orr(out_hi, left_hi, Operand(right_hi)); |
6568 break; | 6510 break; |
6569 } | 6511 } |
6570 case Token::kBIT_XOR: { | 6512 case Token::kBIT_XOR: { |
6571 __ eor(out_lo, left_lo, Operand(right_lo)); | 6513 __ eor(out_lo, left_lo, Operand(right_lo)); |
6572 __ eor(out_hi, left_hi, Operand(right_hi)); | 6514 __ eor(out_hi, left_hi, Operand(right_hi)); |
6573 break; | 6515 break; |
6574 } | 6516 } |
6575 case Token::kADD: | 6517 case Token::kADD: |
6576 case Token::kSUB: { | 6518 case Token::kSUB: { |
6577 if (op_kind() == Token::kADD) { | 6519 if (op_kind() == Token::kADD) { |
6578 __ adds(out_lo, left_lo, Operand(right_lo)); | 6520 __ adds(out_lo, left_lo, Operand(right_lo)); |
6579 __ adcs(out_hi, left_hi, Operand(right_hi)); | 6521 __ adcs(out_hi, left_hi, Operand(right_hi)); |
6580 } else { | 6522 } else { |
6581 ASSERT(op_kind() == Token::kSUB); | 6523 ASSERT(op_kind() == Token::kSUB); |
6582 __ subs(out_lo, left_lo, Operand(right_lo)); | 6524 __ subs(out_lo, left_lo, Operand(right_lo)); |
6583 __ sbcs(out_hi, left_hi, Operand(right_hi)); | 6525 __ sbcs(out_hi, left_hi, Operand(right_hi)); |
(...skipping 18 matching lines...) Expand all Loading... |
6602 default: | 6544 default: |
6603 UNREACHABLE(); | 6545 UNREACHABLE(); |
6604 } | 6546 } |
6605 } | 6547 } |
6606 | 6548 |
6607 | 6549 |
6608 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, | 6550 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, |
6609 bool opt) const { | 6551 bool opt) const { |
6610 const intptr_t kNumInputs = 2; | 6552 const intptr_t kNumInputs = 2; |
6611 const intptr_t kNumTemps = 0; | 6553 const intptr_t kNumTemps = 0; |
6612 LocationSummary* summary = new(zone) LocationSummary( | 6554 LocationSummary* summary = new (zone) |
6613 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6555 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6614 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6556 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
6615 Location::RequiresRegister())); | 6557 Location::RequiresRegister())); |
6616 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); | 6558 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); |
6617 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6559 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
6618 Location::RequiresRegister())); | 6560 Location::RequiresRegister())); |
6619 return summary; | 6561 return summary; |
6620 } | 6562 } |
6621 | 6563 |
6622 | 6564 |
6623 static const intptr_t kMintShiftCountLimit = 63; | 6565 static const intptr_t kMintShiftCountLimit = 63; |
6624 | 6566 |
6625 bool ShiftMintOpInstr::has_shift_count_check() const { | 6567 bool ShiftMintOpInstr::has_shift_count_check() const { |
6626 return !RangeUtils::IsWithin( | 6568 return !RangeUtils::IsWithin(right()->definition()->range(), 0, |
6627 right()->definition()->range(), 0, kMintShiftCountLimit); | 6569 kMintShiftCountLimit); |
6628 } | 6570 } |
6629 | 6571 |
6630 | 6572 |
6631 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6573 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6632 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 6574 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
6633 Register left_lo = left_pair->At(0).reg(); | 6575 Register left_lo = left_pair->At(0).reg(); |
6634 Register left_hi = left_pair->At(1).reg(); | 6576 Register left_hi = left_pair->At(1).reg(); |
6635 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6577 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
6636 Register out_lo = out_pair->At(0).reg(); | 6578 Register out_lo = out_pair->At(0).reg(); |
6637 Register out_hi = out_pair->At(1).reg(); | 6579 Register out_hi = out_pair->At(1).reg(); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6747 UNREACHABLE(); | 6689 UNREACHABLE(); |
6748 } | 6690 } |
6749 } | 6691 } |
6750 } | 6692 } |
6751 | 6693 |
6752 | 6694 |
6753 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, | 6695 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, |
6754 bool opt) const { | 6696 bool opt) const { |
6755 const intptr_t kNumInputs = 1; | 6697 const intptr_t kNumInputs = 1; |
6756 const intptr_t kNumTemps = 0; | 6698 const intptr_t kNumTemps = 0; |
6757 LocationSummary* summary = new(zone) LocationSummary( | 6699 LocationSummary* summary = new (zone) |
6758 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6700 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6759 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6701 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
6760 Location::RequiresRegister())); | 6702 Location::RequiresRegister())); |
6761 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6703 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
6762 Location::RequiresRegister())); | 6704 Location::RequiresRegister())); |
6763 return summary; | 6705 return summary; |
6764 } | 6706 } |
6765 | 6707 |
6766 | 6708 |
6767 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6709 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6768 ASSERT(op_kind() == Token::kBIT_NOT); | 6710 ASSERT(op_kind() == Token::kBIT_NOT); |
(...skipping 21 matching lines...) Expand all Loading... |
6790 | 6732 |
6791 CompileType UnaryUint32OpInstr::ComputeType() const { | 6733 CompileType UnaryUint32OpInstr::ComputeType() const { |
6792 return CompileType::Int(); | 6734 return CompileType::Int(); |
6793 } | 6735 } |
6794 | 6736 |
6795 | 6737 |
6796 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 6738 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
6797 bool opt) const { | 6739 bool opt) const { |
6798 const intptr_t kNumInputs = 2; | 6740 const intptr_t kNumInputs = 2; |
6799 const intptr_t kNumTemps = 0; | 6741 const intptr_t kNumTemps = 0; |
6800 LocationSummary* summary = new(zone) LocationSummary( | 6742 LocationSummary* summary = new (zone) |
6801 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6743 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6802 summary->set_in(0, Location::RequiresRegister()); | 6744 summary->set_in(0, Location::RequiresRegister()); |
6803 summary->set_in(1, Location::RequiresRegister()); | 6745 summary->set_in(1, Location::RequiresRegister()); |
6804 summary->set_out(0, Location::RequiresRegister()); | 6746 summary->set_out(0, Location::RequiresRegister()); |
6805 return summary; | 6747 return summary; |
6806 } | 6748 } |
6807 | 6749 |
6808 | 6750 |
6809 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6751 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6810 Register left = locs()->in(0).reg(); | 6752 Register left = locs()->in(0).reg(); |
6811 Register right = locs()->in(1).reg(); | 6753 Register right = locs()->in(1).reg(); |
(...skipping 21 matching lines...) Expand all Loading... |
6833 default: | 6775 default: |
6834 UNREACHABLE(); | 6776 UNREACHABLE(); |
6835 } | 6777 } |
6836 } | 6778 } |
6837 | 6779 |
6838 | 6780 |
6839 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, | 6781 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, |
6840 bool opt) const { | 6782 bool opt) const { |
6841 const intptr_t kNumInputs = 2; | 6783 const intptr_t kNumInputs = 2; |
6842 const intptr_t kNumTemps = 1; | 6784 const intptr_t kNumTemps = 1; |
6843 LocationSummary* summary = new(zone) LocationSummary( | 6785 LocationSummary* summary = new (zone) |
6844 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6786 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6845 summary->set_in(0, Location::RequiresRegister()); | 6787 summary->set_in(0, Location::RequiresRegister()); |
6846 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 6788 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
6847 summary->set_temp(0, Location::RequiresRegister()); | 6789 summary->set_temp(0, Location::RequiresRegister()); |
6848 summary->set_out(0, Location::RequiresRegister()); | 6790 summary->set_out(0, Location::RequiresRegister()); |
6849 return summary; | 6791 return summary; |
6850 } | 6792 } |
6851 | 6793 |
6852 | 6794 |
6853 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6795 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6854 const intptr_t kShifterLimit = 31; | 6796 const intptr_t kShifterLimit = 31; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6903 default: | 6845 default: |
6904 UNREACHABLE(); | 6846 UNREACHABLE(); |
6905 } | 6847 } |
6906 } | 6848 } |
6907 | 6849 |
6908 | 6850 |
6909 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 6851 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
6910 bool opt) const { | 6852 bool opt) const { |
6911 const intptr_t kNumInputs = 1; | 6853 const intptr_t kNumInputs = 1; |
6912 const intptr_t kNumTemps = 0; | 6854 const intptr_t kNumTemps = 0; |
6913 LocationSummary* summary = new(zone) LocationSummary( | 6855 LocationSummary* summary = new (zone) |
6914 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6856 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6915 summary->set_in(0, Location::RequiresRegister()); | 6857 summary->set_in(0, Location::RequiresRegister()); |
6916 summary->set_out(0, Location::RequiresRegister()); | 6858 summary->set_out(0, Location::RequiresRegister()); |
6917 return summary; | 6859 return summary; |
6918 } | 6860 } |
6919 | 6861 |
6920 | 6862 |
6921 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6863 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6922 Register left = locs()->in(0).reg(); | 6864 Register left = locs()->in(0).reg(); |
6923 Register out = locs()->out(0).reg(); | 6865 Register out = locs()->out(0).reg(); |
6924 ASSERT(left != out); | 6866 ASSERT(left != out); |
6925 | 6867 |
6926 ASSERT(op_kind() == Token::kBIT_NOT); | 6868 ASSERT(op_kind() == Token::kBIT_NOT); |
6927 | 6869 |
6928 __ mvn(out, Operand(left)); | 6870 __ mvn(out, Operand(left)); |
6929 } | 6871 } |
6930 | 6872 |
6931 | 6873 |
6932 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 6874 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |
6933 bool opt) const { | 6875 bool opt) const { |
6934 const intptr_t kNumInputs = 1; | 6876 const intptr_t kNumInputs = 1; |
6935 const intptr_t kNumTemps = 0; | 6877 const intptr_t kNumTemps = 0; |
6936 LocationSummary* summary = new(zone) LocationSummary( | 6878 LocationSummary* summary = new (zone) |
6937 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6879 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6938 if (from() == kUnboxedMint) { | 6880 if (from() == kUnboxedMint) { |
6939 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 6881 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
6940 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6882 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
6941 Location::RequiresRegister())); | 6883 Location::RequiresRegister())); |
6942 summary->set_out(0, Location::RequiresRegister()); | 6884 summary->set_out(0, Location::RequiresRegister()); |
6943 } else if (to() == kUnboxedMint) { | 6885 } else if (to() == kUnboxedMint) { |
6944 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 6886 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
6945 summary->set_in(0, Location::RequiresRegister()); | 6887 summary->set_in(0, Location::RequiresRegister()); |
6946 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6888 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
6947 Location::RequiresRegister())); | 6889 Location::RequiresRegister())); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6998 } else { | 6940 } else { |
6999 ASSERT(from() == kUnboxedInt32); | 6941 ASSERT(from() == kUnboxedInt32); |
7000 __ mov(out_hi, Operand(in, ASR, kBitsPerWord - 1)); | 6942 __ mov(out_hi, Operand(in, ASR, kBitsPerWord - 1)); |
7001 } | 6943 } |
7002 } else { | 6944 } else { |
7003 UNREACHABLE(); | 6945 UNREACHABLE(); |
7004 } | 6946 } |
7005 } | 6947 } |
7006 | 6948 |
7007 | 6949 |
7008 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, | 6950 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
7009 bool opt) const { | 6951 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
7010 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
7011 } | 6952 } |
7012 | 6953 |
7013 | 6954 |
7014 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6955 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
7015 compiler->GenerateRuntimeCall(token_pos(), | 6956 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, |
7016 deopt_id(), | |
7017 kThrowRuntimeEntry, | |
7018 1, | |
7019 locs()); | 6957 locs()); |
7020 __ bkpt(0); | 6958 __ bkpt(0); |
7021 } | 6959 } |
7022 | 6960 |
7023 | 6961 |
7024 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, | 6962 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
7025 bool opt) const { | 6963 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
7026 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
7027 } | 6964 } |
7028 | 6965 |
7029 | 6966 |
7030 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6967 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
7031 compiler->SetNeedsStacktrace(catch_try_index()); | 6968 compiler->SetNeedsStacktrace(catch_try_index()); |
7032 compiler->GenerateRuntimeCall(token_pos(), | 6969 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, |
7033 deopt_id(), | 6970 2, locs()); |
7034 kReThrowRuntimeEntry, | |
7035 2, | |
7036 locs()); | |
7037 __ bkpt(0); | 6971 __ bkpt(0); |
7038 } | 6972 } |
7039 | 6973 |
7040 | 6974 |
7041 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, | 6975 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
7042 bool opt) const { | 6976 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
7043 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
7044 } | 6977 } |
7045 | 6978 |
7046 | 6979 |
7047 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6980 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
7048 __ Stop(message()); | 6981 __ Stop(message()); |
7049 } | 6982 } |
7050 | 6983 |
7051 | 6984 |
7052 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6985 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
7053 if (!compiler->CanFallThroughTo(normal_entry())) { | 6986 if (!compiler->CanFallThroughTo(normal_entry())) { |
7054 __ b(compiler->GetJumpLabel(normal_entry())); | 6987 __ b(compiler->GetJumpLabel(normal_entry())); |
7055 } | 6988 } |
7056 } | 6989 } |
7057 | 6990 |
7058 | 6991 |
7059 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, | 6992 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
7060 bool opt) const { | 6993 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
7061 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
7062 } | 6994 } |
7063 | 6995 |
7064 | 6996 |
7065 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6997 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
7066 if (!compiler->is_optimizing()) { | 6998 if (!compiler->is_optimizing()) { |
7067 if (FLAG_reorder_basic_blocks) { | 6999 if (FLAG_reorder_basic_blocks) { |
7068 compiler->EmitEdgeCounter(block()->preorder_number()); | 7000 compiler->EmitEdgeCounter(block()->preorder_number()); |
7069 } | 7001 } |
7070 // Add a deoptimization descriptor for deoptimizing instructions that | 7002 // Add a deoptimization descriptor for deoptimizing instructions that |
7071 // may be inserted before this instruction. | 7003 // may be inserted before this instruction. |
7072 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 7004 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), |
7073 GetDeoptId(), | |
7074 TokenPosition::kNoSource); | 7005 TokenPosition::kNoSource); |
7075 } | 7006 } |
7076 if (HasParallelMove()) { | 7007 if (HasParallelMove()) { |
7077 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 7008 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
7078 } | 7009 } |
7079 | 7010 |
7080 // We can fall through if the successor is the next block in the list. | 7011 // We can fall through if the successor is the next block in the list. |
7081 // Otherwise, we need a jump. | 7012 // Otherwise, we need a jump. |
7082 if (!compiler->CanFallThroughTo(successor())) { | 7013 if (!compiler->CanFallThroughTo(successor())) { |
7083 __ b(compiler->GetJumpLabel(successor())); | 7014 __ b(compiler->GetJumpLabel(successor())); |
7084 } | 7015 } |
7085 } | 7016 } |
7086 | 7017 |
7087 | 7018 |
7088 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 7019 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |
7089 bool opt) const { | 7020 bool opt) const { |
7090 const intptr_t kNumInputs = 1; | 7021 const intptr_t kNumInputs = 1; |
7091 const intptr_t kNumTemps = 1; | 7022 const intptr_t kNumTemps = 1; |
7092 | 7023 |
7093 LocationSummary* summary = new(zone) LocationSummary( | 7024 LocationSummary* summary = new (zone) |
7094 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 7025 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
7095 | 7026 |
7096 summary->set_in(0, Location::RequiresRegister()); | 7027 summary->set_in(0, Location::RequiresRegister()); |
7097 summary->set_temp(0, Location::RequiresRegister()); | 7028 summary->set_temp(0, Location::RequiresRegister()); |
7098 | 7029 |
7099 return summary; | 7030 return summary; |
7100 } | 7031 } |
7101 | 7032 |
7102 | 7033 |
7103 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 7034 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
7104 Register target_address_reg = locs()->temp_slot(0)->reg(); | 7035 Register target_address_reg = locs()->temp_slot(0)->reg(); |
7105 | 7036 |
7106 // Offset is relative to entry pc. | 7037 // Offset is relative to entry pc. |
7107 const intptr_t entry_to_pc_offset = __ CodeSize() + Instr::kPCReadOffset; | 7038 const intptr_t entry_to_pc_offset = __ CodeSize() + Instr::kPCReadOffset; |
7108 __ mov(target_address_reg, Operand(PC)); | 7039 __ mov(target_address_reg, Operand(PC)); |
7109 __ AddImmediate(target_address_reg, target_address_reg, -entry_to_pc_offset); | 7040 __ AddImmediate(target_address_reg, target_address_reg, -entry_to_pc_offset); |
7110 // Add the offset. | 7041 // Add the offset. |
7111 Register offset_reg = locs()->in(0).reg(); | 7042 Register offset_reg = locs()->in(0).reg(); |
7112 Operand offset_opr = | 7043 Operand offset_opr = (offset()->definition()->representation() == kTagged) |
7113 (offset()->definition()->representation() == kTagged) ? | 7044 ? Operand(offset_reg, ASR, kSmiTagSize) |
7114 Operand(offset_reg, ASR, kSmiTagSize) : | 7045 : Operand(offset_reg); |
7115 Operand(offset_reg); | |
7116 __ add(target_address_reg, target_address_reg, offset_opr); | 7046 __ add(target_address_reg, target_address_reg, offset_opr); |
7117 | 7047 |
7118 // Jump to the absolute address. | 7048 // Jump to the absolute address. |
7119 __ bx(target_address_reg); | 7049 __ bx(target_address_reg); |
7120 } | 7050 } |
7121 | 7051 |
7122 | 7052 |
7123 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, | 7053 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, |
7124 bool opt) const { | 7054 bool opt) const { |
7125 const intptr_t kNumInputs = 2; | 7055 const intptr_t kNumInputs = 2; |
7126 const intptr_t kNumTemps = 0; | 7056 const intptr_t kNumTemps = 0; |
7127 if (needs_number_check()) { | 7057 if (needs_number_check()) { |
7128 LocationSummary* locs = new(zone) LocationSummary( | 7058 LocationSummary* locs = new (zone) |
7129 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 7059 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
7130 locs->set_in(0, Location::RegisterLocation(R0)); | 7060 locs->set_in(0, Location::RegisterLocation(R0)); |
7131 locs->set_in(1, Location::RegisterLocation(R1)); | 7061 locs->set_in(1, Location::RegisterLocation(R1)); |
7132 locs->set_out(0, Location::RegisterLocation(R0)); | 7062 locs->set_out(0, Location::RegisterLocation(R0)); |
7133 return locs; | 7063 return locs; |
7134 } | 7064 } |
7135 LocationSummary* locs = new(zone) LocationSummary( | 7065 LocationSummary* locs = new (zone) |
7136 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 7066 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
7137 | 7067 |
7138 // If a constant has more than one use, make sure it is loaded in register | 7068 // If a constant has more than one use, make sure it is loaded in register |
7139 // so that multiple immediate loads can be avoided. | 7069 // so that multiple immediate loads can be avoided. |
7140 ConstantInstr* constant = left()->definition()->AsConstant(); | 7070 ConstantInstr* constant = left()->definition()->AsConstant(); |
7141 if ((constant != NULL) && !left()->IsSingleUse()) { | 7071 if ((constant != NULL) && !left()->IsSingleUse()) { |
7142 locs->set_in(0, Location::RequiresRegister()); | 7072 locs->set_in(0, Location::RequiresRegister()); |
7143 } else { | 7073 } else { |
7144 locs->set_in(0, Location::RegisterOrConstant(left())); | 7074 locs->set_in(0, Location::RegisterOrConstant(left())); |
7145 } | 7075 } |
7146 | 7076 |
7147 constant = right()->definition()->AsConstant(); | 7077 constant = right()->definition()->AsConstant(); |
7148 if ((constant != NULL) && !right()->IsSingleUse()) { | 7078 if ((constant != NULL) && !right()->IsSingleUse()) { |
7149 locs->set_in(1, Location::RequiresRegister()); | 7079 locs->set_in(1, Location::RequiresRegister()); |
7150 } else { | 7080 } else { |
7151 // Only one of the inputs can be a constant. Choose register if the first | 7081 // Only one of the inputs can be a constant. Choose register if the first |
7152 // one is a constant. | 7082 // one is a constant. |
7153 locs->set_in(1, locs->in(0).IsConstant() | 7083 locs->set_in(1, locs->in(0).IsConstant() |
7154 ? Location::RequiresRegister() | 7084 ? Location::RequiresRegister() |
7155 : Location::RegisterOrConstant(right())); | 7085 : Location::RegisterOrConstant(right())); |
7156 } | 7086 } |
7157 locs->set_out(0, Location::RequiresRegister()); | 7087 locs->set_out(0, Location::RequiresRegister()); |
7158 return locs; | 7088 return locs; |
7159 } | 7089 } |
7160 | 7090 |
7161 | 7091 |
7162 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 7092 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
7163 BranchLabels labels) { | 7093 BranchLabels labels) { |
7164 Location left = locs()->in(0); | 7094 Location left = locs()->in(0); |
7165 Location right = locs()->in(1); | 7095 Location right = locs()->in(1); |
7166 ASSERT(!left.IsConstant() || !right.IsConstant()); | 7096 ASSERT(!left.IsConstant() || !right.IsConstant()); |
7167 Condition true_condition; | 7097 Condition true_condition; |
7168 if (left.IsConstant()) { | 7098 if (left.IsConstant()) { |
7169 true_condition = compiler->EmitEqualityRegConstCompare(right.reg(), | 7099 true_condition = compiler->EmitEqualityRegConstCompare( |
7170 left.constant(), | 7100 right.reg(), left.constant(), needs_number_check(), token_pos()); |
7171 needs_number_check(), | |
7172 token_pos()); | |
7173 } else if (right.IsConstant()) { | 7101 } else if (right.IsConstant()) { |
7174 true_condition = compiler->EmitEqualityRegConstCompare(left.reg(), | 7102 true_condition = compiler->EmitEqualityRegConstCompare( |
7175 right.constant(), | 7103 left.reg(), right.constant(), needs_number_check(), token_pos()); |
7176 needs_number_check(), | |
7177 token_pos()); | |
7178 } else { | 7104 } else { |
7179 true_condition = compiler->EmitEqualityRegRegCompare(left.reg(), | 7105 true_condition = compiler->EmitEqualityRegRegCompare( |
7180 right.reg(), | 7106 left.reg(), right.reg(), needs_number_check(), token_pos()); |
7181 needs_number_check(), | |
7182 token_pos()); | |
7183 } | 7107 } |
7184 if (kind() != Token::kEQ_STRICT) { | 7108 if (kind() != Token::kEQ_STRICT) { |
7185 ASSERT(kind() == Token::kNE_STRICT); | 7109 ASSERT(kind() == Token::kNE_STRICT); |
7186 true_condition = NegateCondition(true_condition); | 7110 true_condition = NegateCondition(true_condition); |
7187 } | 7111 } |
7188 return true_condition; | 7112 return true_condition; |
7189 } | 7113 } |
7190 | 7114 |
7191 | 7115 |
7192 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 7116 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
7193 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 7117 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
7194 | 7118 |
7195 // The ARM code does not use true- and false-labels here. | 7119 // The ARM code does not use true- and false-labels here. |
7196 BranchLabels labels = { NULL, NULL, NULL }; | 7120 BranchLabels labels = {NULL, NULL, NULL}; |
7197 Condition true_condition = EmitComparisonCode(compiler, labels); | 7121 Condition true_condition = EmitComparisonCode(compiler, labels); |
7198 | 7122 |
7199 const Register result = locs()->out(0).reg(); | 7123 const Register result = locs()->out(0).reg(); |
7200 __ LoadObject(result, Bool::True(), true_condition); | 7124 __ LoadObject(result, Bool::True(), true_condition); |
7201 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 7125 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
7202 } | 7126 } |
7203 | 7127 |
7204 | 7128 |
7205 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 7129 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
7206 BranchInstr* branch) { | 7130 BranchInstr* branch) { |
7207 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 7131 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
7208 | 7132 |
7209 BranchLabels labels = compiler->CreateBranchLabels(branch); | 7133 BranchLabels labels = compiler->CreateBranchLabels(branch); |
7210 Condition true_condition = EmitComparisonCode(compiler, labels); | 7134 Condition true_condition = EmitComparisonCode(compiler, labels); |
7211 EmitBranchOnCondition(compiler, true_condition, labels); | 7135 EmitBranchOnCondition(compiler, true_condition, labels); |
7212 } | 7136 } |
7213 | 7137 |
7214 | 7138 |
7215 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 7139 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
7216 bool opt) const { | 7140 bool opt) const { |
7217 return LocationSummary::Make(zone, | 7141 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
7218 1, | |
7219 Location::RequiresRegister(), | |
7220 LocationSummary::kNoCall); | 7142 LocationSummary::kNoCall); |
7221 } | 7143 } |
7222 | 7144 |
7223 | 7145 |
7224 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 7146 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
7225 const Register value = locs()->in(0).reg(); | 7147 const Register value = locs()->in(0).reg(); |
7226 const Register result = locs()->out(0).reg(); | 7148 const Register result = locs()->out(0).reg(); |
7227 | 7149 |
7228 __ LoadObject(result, Bool::True()); | 7150 __ LoadObject(result, Bool::True()); |
7229 __ cmp(result, Operand(value)); | 7151 __ cmp(result, Operand(value)); |
7230 __ LoadObject(result, Bool::False(), EQ); | 7152 __ LoadObject(result, Bool::False(), EQ); |
7231 } | 7153 } |
7232 | 7154 |
7233 | 7155 |
7234 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 7156 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
7235 bool opt) const { | 7157 bool opt) const { |
7236 return MakeCallSummary(zone); | 7158 return MakeCallSummary(zone); |
7237 } | 7159 } |
7238 | 7160 |
7239 | 7161 |
7240 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 7162 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
7241 const Code& stub = Code::ZoneHandle( | 7163 const Code& stub = Code::ZoneHandle( |
7242 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 7164 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |
7243 const StubEntry stub_entry(stub); | 7165 const StubEntry stub_entry(stub); |
7244 compiler->GenerateCall(token_pos(), | 7166 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, |
7245 stub_entry, | |
7246 RawPcDescriptors::kOther, | |
7247 locs()); | 7167 locs()); |
7248 compiler->AddStubCallTarget(stub); | 7168 compiler->AddStubCallTarget(stub); |
7249 __ Drop(ArgumentCount()); // Discard arguments. | 7169 __ Drop(ArgumentCount()); // Discard arguments. |
7250 } | 7170 } |
7251 | 7171 |
7252 | 7172 |
7253 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 7173 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
7254 ASSERT(!compiler->is_optimizing()); | 7174 ASSERT(!compiler->is_optimizing()); |
7255 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); | 7175 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); |
7256 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); | 7176 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); |
7257 compiler->RecordSafepoint(locs()); | 7177 compiler->RecordSafepoint(locs()); |
7258 } | 7178 } |
7259 | 7179 |
7260 | 7180 |
7261 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary( | 7181 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary(Zone* zone, |
7262 Zone* zone, bool opt) const { | 7182 bool opt) const { |
7263 const intptr_t kNumInputs = 1; | 7183 const intptr_t kNumInputs = 1; |
7264 const intptr_t kNumTemps = 0; | 7184 const intptr_t kNumTemps = 0; |
7265 LocationSummary* locs = new(zone) LocationSummary( | 7185 LocationSummary* locs = new (zone) |
7266 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 7186 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
7267 locs->set_in(0, Location::RegisterLocation(R0)); | 7187 locs->set_in(0, Location::RegisterLocation(R0)); |
7268 locs->set_out(0, Location::RegisterLocation(R0)); | 7188 locs->set_out(0, Location::RegisterLocation(R0)); |
7269 return locs; | 7189 return locs; |
7270 } | 7190 } |
7271 | 7191 |
7272 | 7192 |
7273 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 7193 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
7274 const Register typed_data = locs()->in(0).reg(); | 7194 const Register typed_data = locs()->in(0).reg(); |
7275 const Register result = locs()->out(0).reg(); | 7195 const Register result = locs()->out(0).reg(); |
7276 __ PushObject(Object::null_object()); | 7196 __ PushObject(Object::null_object()); |
7277 __ Push(typed_data); | 7197 __ Push(typed_data); |
7278 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, | 7198 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
7279 deopt_id(), | 7199 kGrowRegExpStackRuntimeEntry, 1, locs()); |
7280 kGrowRegExpStackRuntimeEntry, | |
7281 1, | |
7282 locs()); | |
7283 __ Drop(1); | 7200 __ Drop(1); |
7284 __ Pop(result); | 7201 __ Pop(result); |
7285 } | 7202 } |
7286 | 7203 |
7287 | 7204 |
7288 } // namespace dart | 7205 } // namespace dart |
7289 | 7206 |
7290 #endif // defined TARGET_ARCH_ARM | 7207 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |