OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "vm/symbols.h" | 22 #include "vm/symbols.h" |
23 | 23 |
24 #define __ compiler->assembler()-> | 24 #define __ compiler->assembler()-> |
25 #define Z (compiler->zone()) | 25 #define Z (compiler->zone()) |
26 | 26 |
27 namespace dart { | 27 namespace dart { |
28 | 28 |
29 // Generic summary for call instructions that have all arguments pushed | 29 // Generic summary for call instructions that have all arguments pushed |
30 // on the stack and return the result in a fixed register R0. | 30 // on the stack and return the result in a fixed register R0. |
31 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { | 31 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { |
32 LocationSummary* result = new(zone) LocationSummary( | 32 LocationSummary* result = |
33 zone, 0, 0, LocationSummary::kCall); | 33 new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
34 result->set_out(0, Location::RegisterLocation(R0)); | 34 result->set_out(0, Location::RegisterLocation(R0)); |
35 return result; | 35 return result; |
36 } | 36 } |
37 | 37 |
38 | 38 |
39 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, | 39 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, |
40 bool opt) const { | 40 bool opt) const { |
41 const intptr_t kNumInputs = 1; | 41 const intptr_t kNumInputs = 1; |
42 const intptr_t kNumTemps = 0; | 42 const intptr_t kNumTemps = 0; |
43 LocationSummary* locs = new(zone) LocationSummary( | 43 LocationSummary* locs = new (zone) |
44 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 44 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
45 locs->set_in(0, Location::AnyOrConstant(value())); | 45 locs->set_in(0, Location::AnyOrConstant(value())); |
46 return locs; | 46 return locs; |
47 } | 47 } |
48 | 48 |
49 | 49 |
50 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 50 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
51 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 51 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
52 // where PushArgument is handled by BindInstr::EmitNativeCode. | 52 // where PushArgument is handled by BindInstr::EmitNativeCode. |
53 if (compiler->is_optimizing()) { | 53 if (compiler->is_optimizing()) { |
54 Location value = locs()->in(0); | 54 Location value = locs()->in(0); |
55 if (value.IsRegister()) { | 55 if (value.IsRegister()) { |
56 __ Push(value.reg()); | 56 __ Push(value.reg()); |
57 } else if (value.IsConstant()) { | 57 } else if (value.IsConstant()) { |
58 __ PushObject(value.constant()); | 58 __ PushObject(value.constant()); |
59 } else { | 59 } else { |
60 ASSERT(value.IsStackSlot()); | 60 ASSERT(value.IsStackSlot()); |
61 const intptr_t value_offset = value.ToStackSlotOffset(); | 61 const intptr_t value_offset = value.ToStackSlotOffset(); |
62 __ LoadFromOffset(TMP, value.base_reg(), value_offset); | 62 __ LoadFromOffset(TMP, value.base_reg(), value_offset); |
63 __ Push(TMP); | 63 __ Push(TMP); |
64 } | 64 } |
65 } | 65 } |
66 } | 66 } |
67 | 67 |
68 | 68 |
69 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, | 69 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
70 bool opt) const { | |
71 const intptr_t kNumInputs = 1; | 70 const intptr_t kNumInputs = 1; |
72 const intptr_t kNumTemps = 0; | 71 const intptr_t kNumTemps = 0; |
73 LocationSummary* locs = new(zone) LocationSummary( | 72 LocationSummary* locs = new (zone) |
74 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 73 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
75 locs->set_in(0, Location::RegisterLocation(R0)); | 74 locs->set_in(0, Location::RegisterLocation(R0)); |
76 return locs; | 75 return locs; |
77 } | 76 } |
78 | 77 |
79 | 78 |
80 // Attempt optimized compilation at return instruction instead of at the entry. | 79 // Attempt optimized compilation at return instruction instead of at the entry. |
81 // The entry needs to be patchable, no inlined objects are allowed in the area | 80 // The entry needs to be patchable, no inlined objects are allowed in the area |
82 // that will be overwritten by the patch instructions: a branch macro sequence. | 81 // that will be overwritten by the patch instructions: a branch macro sequence. |
83 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 82 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
84 const Register result = locs()->in(0).reg(); | 83 const Register result = locs()->in(0).reg(); |
(...skipping 21 matching lines...) Expand all Loading... |
106 __ LeaveDartFrame(); // Disallows constant pool use. | 105 __ LeaveDartFrame(); // Disallows constant pool use. |
107 __ ret(); | 106 __ ret(); |
108 // This ReturnInstr may be emitted out of order by the optimizer. The next | 107 // This ReturnInstr may be emitted out of order by the optimizer. The next |
109 // block may be a target expecting a properly set constant pool pointer. | 108 // block may be a target expecting a properly set constant pool pointer. |
110 __ set_constant_pool_allowed(true); | 109 __ set_constant_pool_allowed(true); |
111 } | 110 } |
112 | 111 |
113 | 112 |
114 static Condition NegateCondition(Condition condition) { | 113 static Condition NegateCondition(Condition condition) { |
115 switch (condition) { | 114 switch (condition) { |
116 case EQ: return NE; | 115 case EQ: |
117 case NE: return EQ; | 116 return NE; |
118 case LT: return GE; | 117 case NE: |
119 case LE: return GT; | 118 return EQ; |
120 case GT: return LE; | 119 case LT: |
121 case GE: return LT; | 120 return GE; |
122 case CC: return CS; | 121 case LE: |
123 case LS: return HI; | 122 return GT; |
124 case HI: return LS; | 123 case GT: |
125 case CS: return CC; | 124 return LE; |
126 case VS: return VC; | 125 case GE: |
127 case VC: return VS; | 126 return LT; |
| 127 case CC: |
| 128 return CS; |
| 129 case LS: |
| 130 return HI; |
| 131 case HI: |
| 132 return LS; |
| 133 case CS: |
| 134 return CC; |
| 135 case VS: |
| 136 return VC; |
| 137 case VC: |
| 138 return VS; |
128 default: | 139 default: |
129 UNREACHABLE(); | 140 UNREACHABLE(); |
130 return EQ; | 141 return EQ; |
131 } | 142 } |
132 } | 143 } |
133 | 144 |
134 | 145 |
135 // Detect pattern when one value is zero and another is a power of 2. | 146 // Detect pattern when one value is zero and another is a power of 2. |
136 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 147 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
137 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 148 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
138 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 149 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
139 } | 150 } |
140 | 151 |
141 | 152 |
142 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, | 153 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, |
143 bool opt) const { | 154 bool opt) const { |
144 comparison()->InitializeLocationSummary(zone, opt); | 155 comparison()->InitializeLocationSummary(zone, opt); |
145 return comparison()->locs(); | 156 return comparison()->locs(); |
146 } | 157 } |
147 | 158 |
148 | 159 |
149 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 160 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
150 const Register result = locs()->out(0).reg(); | 161 const Register result = locs()->out(0).reg(); |
151 | 162 |
152 Location left = locs()->in(0); | 163 Location left = locs()->in(0); |
153 Location right = locs()->in(1); | 164 Location right = locs()->in(1); |
154 ASSERT(!left.IsConstant() || !right.IsConstant()); | 165 ASSERT(!left.IsConstant() || !right.IsConstant()); |
155 | 166 |
156 // Emit comparison code. This must not overwrite the result register. | 167 // Emit comparison code. This must not overwrite the result register. |
157 BranchLabels labels = { NULL, NULL, NULL }; | 168 BranchLabels labels = {NULL, NULL, NULL}; |
158 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 169 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
159 | 170 |
160 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 171 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
161 | 172 |
162 intptr_t true_value = if_true_; | 173 intptr_t true_value = if_true_; |
163 intptr_t false_value = if_false_; | 174 intptr_t false_value = if_false_; |
164 | 175 |
165 if (is_power_of_two_kind) { | 176 if (is_power_of_two_kind) { |
166 if (true_value == 0) { | 177 if (true_value == 0) { |
167 // We need to have zero in result on true_condition. | 178 // We need to have zero in result on true_condition. |
(...skipping 11 matching lines...) Expand all Loading... |
179 } | 190 } |
180 | 191 |
181 __ cset(result, true_condition); | 192 __ cset(result, true_condition); |
182 | 193 |
183 if (is_power_of_two_kind) { | 194 if (is_power_of_two_kind) { |
184 const intptr_t shift = | 195 const intptr_t shift = |
185 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); | 196 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
186 __ LslImmediate(result, result, shift + kSmiTagSize); | 197 __ LslImmediate(result, result, shift + kSmiTagSize); |
187 } else { | 198 } else { |
188 __ sub(result, result, Operand(1)); | 199 __ sub(result, result, Operand(1)); |
189 const int64_t val = | 200 const int64_t val = Smi::RawValue(true_value) - Smi::RawValue(false_value); |
190 Smi::RawValue(true_value) - Smi::RawValue(false_value); | |
191 __ AndImmediate(result, result, val); | 201 __ AndImmediate(result, result, val); |
192 if (false_value != 0) { | 202 if (false_value != 0) { |
193 __ AddImmediate(result, result, Smi::RawValue(false_value)); | 203 __ AddImmediate(result, result, Smi::RawValue(false_value)); |
194 } | 204 } |
195 } | 205 } |
196 } | 206 } |
197 | 207 |
198 | 208 |
199 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 209 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |
200 bool opt) const { | 210 bool opt) const { |
201 const intptr_t kNumInputs = 1; | 211 const intptr_t kNumInputs = 1; |
202 const intptr_t kNumTemps = 0; | 212 const intptr_t kNumTemps = 0; |
203 LocationSummary* summary = new(zone) LocationSummary( | 213 LocationSummary* summary = new (zone) |
204 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 214 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
205 summary->set_in(0, Location::RegisterLocation(R0)); // Function. | 215 summary->set_in(0, Location::RegisterLocation(R0)); // Function. |
206 summary->set_out(0, Location::RegisterLocation(R0)); | 216 summary->set_out(0, Location::RegisterLocation(R0)); |
207 return summary; | 217 return summary; |
208 } | 218 } |
209 | 219 |
210 | 220 |
211 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 221 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
212 // Load arguments descriptor in R4. | 222 // Load arguments descriptor in R4. |
213 int argument_count = ArgumentCount(); | 223 int argument_count = ArgumentCount(); |
214 const Array& arguments_descriptor = | 224 const Array& arguments_descriptor = Array::ZoneHandle( |
215 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 225 ArgumentsDescriptor::New(argument_count, argument_names())); |
216 argument_names())); | |
217 __ LoadObject(R4, arguments_descriptor); | 226 __ LoadObject(R4, arguments_descriptor); |
218 | 227 |
219 // R4: Arguments descriptor. | 228 // R4: Arguments descriptor. |
220 // R0: Function. | 229 // R0: Function. |
221 ASSERT(locs()->in(0).reg() == R0); | 230 ASSERT(locs()->in(0).reg() == R0); |
222 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset()); | 231 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset()); |
223 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset()); | 232 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset()); |
224 | 233 |
225 // R2: instructions. | 234 // R2: instructions. |
226 // R5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). | 235 // R5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). |
227 __ LoadImmediate(R5, 0); | 236 __ LoadImmediate(R5, 0); |
228 //?? | 237 //?? |
229 __ blr(R2); | 238 __ blr(R2); |
230 compiler->RecordSafepoint(locs()); | 239 compiler->RecordSafepoint(locs()); |
231 // Marks either the continuation point in unoptimized code or the | 240 // Marks either the continuation point in unoptimized code or the |
232 // deoptimization point in optimized code, after call. | 241 // deoptimization point in optimized code, after call. |
233 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); | 242 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); |
234 if (compiler->is_optimizing()) { | 243 if (compiler->is_optimizing()) { |
235 compiler->AddDeoptIndexAtCall(deopt_id_after); | 244 compiler->AddDeoptIndexAtCall(deopt_id_after); |
236 } | 245 } |
237 // Add deoptimization continuation point after the call and before the | 246 // Add deoptimization continuation point after the call and before the |
238 // arguments are removed. | 247 // arguments are removed. |
239 // In optimized code this descriptor is needed for exception handling. | 248 // In optimized code this descriptor is needed for exception handling. |
240 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 249 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, |
241 deopt_id_after, | |
242 token_pos()); | 250 token_pos()); |
243 __ Drop(argument_count); | 251 __ Drop(argument_count); |
244 } | 252 } |
245 | 253 |
246 | 254 |
247 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 255 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
248 bool opt) const { | 256 bool opt) const { |
249 return LocationSummary::Make(zone, | 257 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), |
250 0, | |
251 Location::RequiresRegister(), | |
252 LocationSummary::kNoCall); | 258 LocationSummary::kNoCall); |
253 } | 259 } |
254 | 260 |
255 | 261 |
256 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 262 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
257 const Register result = locs()->out(0).reg(); | 263 const Register result = locs()->out(0).reg(); |
258 __ LoadFromOffset(result, FP, local().index() * kWordSize); | 264 __ LoadFromOffset(result, FP, local().index() * kWordSize); |
259 } | 265 } |
260 | 266 |
261 | 267 |
262 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 268 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |
263 bool opt) const { | 269 bool opt) const { |
264 return LocationSummary::Make(zone, | 270 return LocationSummary::Make(zone, 1, Location::SameAsFirstInput(), |
265 1, | |
266 Location::SameAsFirstInput(), | |
267 LocationSummary::kNoCall); | 271 LocationSummary::kNoCall); |
268 } | 272 } |
269 | 273 |
270 | 274 |
271 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 275 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
272 const Register value = locs()->in(0).reg(); | 276 const Register value = locs()->in(0).reg(); |
273 const Register result = locs()->out(0).reg(); | 277 const Register result = locs()->out(0).reg(); |
274 ASSERT(result == value); // Assert that register assignment is correct. | 278 ASSERT(result == value); // Assert that register assignment is correct. |
275 __ StoreToOffset(value, FP, local().index() * kWordSize); | 279 __ StoreToOffset(value, FP, local().index() * kWordSize); |
276 } | 280 } |
277 | 281 |
278 | 282 |
279 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 283 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |
280 bool opt) const { | 284 bool opt) const { |
281 return LocationSummary::Make(zone, | 285 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), |
282 0, | |
283 Location::RequiresRegister(), | |
284 LocationSummary::kNoCall); | 286 LocationSummary::kNoCall); |
285 } | 287 } |
286 | 288 |
287 | 289 |
288 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 290 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
289 // The register allocator drops constant definitions that have no uses. | 291 // The register allocator drops constant definitions that have no uses. |
290 if (!locs()->out(0).IsInvalid()) { | 292 if (!locs()->out(0).IsInvalid()) { |
291 const Register result = locs()->out(0).reg(); | 293 const Register result = locs()->out(0).reg(); |
292 __ LoadObject(result, value()); | 294 __ LoadObject(result, value()); |
293 } | 295 } |
294 } | 296 } |
295 | 297 |
296 | 298 |
297 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 299 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
298 bool opt) const { | 300 bool opt) const { |
299 const intptr_t kNumInputs = 0; | 301 const intptr_t kNumInputs = 0; |
300 const Location out = (representation_ == kUnboxedInt32) ? | 302 const Location out = (representation_ == kUnboxedInt32) |
301 Location::RequiresRegister() : Location::RequiresFpuRegister(); | 303 ? Location::RequiresRegister() |
302 return LocationSummary::Make(zone, | 304 : Location::RequiresFpuRegister(); |
303 kNumInputs, | 305 return LocationSummary::Make(zone, kNumInputs, out, LocationSummary::kNoCall); |
304 out, | |
305 LocationSummary::kNoCall); | |
306 } | 306 } |
307 | 307 |
308 | 308 |
309 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 309 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
310 if (!locs()->out(0).IsInvalid()) { | 310 if (!locs()->out(0).IsInvalid()) { |
311 switch (representation_) { | 311 switch (representation_) { |
312 case kUnboxedDouble: | 312 case kUnboxedDouble: |
313 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { | 313 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { |
314 const VRegister dst = locs()->out(0).fpu_reg(); | 314 const VRegister dst = locs()->out(0).fpu_reg(); |
315 __ veor(dst, dst, dst); | 315 __ veor(dst, dst, dst); |
(...skipping 11 matching lines...) Expand all Loading... |
327 break; | 327 break; |
328 } | 328 } |
329 } | 329 } |
330 } | 330 } |
331 | 331 |
332 | 332 |
333 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 333 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
334 bool opt) const { | 334 bool opt) const { |
335 const intptr_t kNumInputs = 2; | 335 const intptr_t kNumInputs = 2; |
336 const intptr_t kNumTemps = 0; | 336 const intptr_t kNumTemps = 0; |
337 LocationSummary* summary = new(zone) LocationSummary( | 337 LocationSummary* summary = new (zone) |
338 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 338 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
339 summary->set_in(0, Location::RegisterLocation(R0)); // Value. | 339 summary->set_in(0, Location::RegisterLocation(R0)); // Value. |
340 summary->set_in(1, Location::RegisterLocation(R1)); // Type arguments. | 340 summary->set_in(1, Location::RegisterLocation(R1)); // Type arguments. |
341 summary->set_out(0, Location::RegisterLocation(R0)); | 341 summary->set_out(0, Location::RegisterLocation(R0)); |
342 return summary; | 342 return summary; |
343 } | 343 } |
344 | 344 |
345 | 345 |
346 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 346 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
347 bool opt) const { | 347 bool opt) const { |
348 const intptr_t kNumInputs = 1; | 348 const intptr_t kNumInputs = 1; |
349 const intptr_t kNumTemps = 0; | 349 const intptr_t kNumTemps = 0; |
350 LocationSummary* locs = new(zone) LocationSummary( | 350 LocationSummary* locs = new (zone) |
351 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 351 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
352 locs->set_in(0, Location::RegisterLocation(R0)); | 352 locs->set_in(0, Location::RegisterLocation(R0)); |
353 locs->set_out(0, Location::RegisterLocation(R0)); | 353 locs->set_out(0, Location::RegisterLocation(R0)); |
354 return locs; | 354 return locs; |
355 } | 355 } |
356 | 356 |
357 | 357 |
358 static void EmitAssertBoolean(Register reg, | 358 static void EmitAssertBoolean(Register reg, |
359 TokenPosition token_pos, | 359 TokenPosition token_pos, |
360 intptr_t deopt_id, | 360 intptr_t deopt_id, |
361 LocationSummary* locs, | 361 LocationSummary* locs, |
362 FlowGraphCompiler* compiler) { | 362 FlowGraphCompiler* compiler) { |
363 // Check that the type of the value is allowed in conditional context. | 363 // Check that the type of the value is allowed in conditional context. |
364 // Call the runtime if the object is not bool::true or bool::false. | 364 // Call the runtime if the object is not bool::true or bool::false. |
365 ASSERT(locs->always_calls()); | 365 ASSERT(locs->always_calls()); |
366 Label done; | 366 Label done; |
367 | 367 |
368 if (Isolate::Current()->type_checks()) { | 368 if (Isolate::Current()->type_checks()) { |
369 __ CompareObject(reg, Bool::True()); | 369 __ CompareObject(reg, Bool::True()); |
370 __ b(&done, EQ); | 370 __ b(&done, EQ); |
371 __ CompareObject(reg, Bool::False()); | 371 __ CompareObject(reg, Bool::False()); |
372 __ b(&done, EQ); | 372 __ b(&done, EQ); |
373 } else { | 373 } else { |
374 ASSERT(Isolate::Current()->asserts()); | 374 ASSERT(Isolate::Current()->asserts()); |
375 __ CompareObject(reg, Object::null_instance()); | 375 __ CompareObject(reg, Object::null_instance()); |
376 __ b(&done, NE); | 376 __ b(&done, NE); |
377 } | 377 } |
378 | 378 |
379 __ Push(reg); // Push the source object. | 379 __ Push(reg); // Push the source object. |
380 compiler->GenerateRuntimeCall(token_pos, | 380 compiler->GenerateRuntimeCall(token_pos, deopt_id, |
381 deopt_id, | 381 kNonBoolTypeErrorRuntimeEntry, 1, locs); |
382 kNonBoolTypeErrorRuntimeEntry, | |
383 1, | |
384 locs); | |
385 // We should never return here. | 382 // We should never return here. |
386 __ brk(0); | 383 __ brk(0); |
387 __ Bind(&done); | 384 __ Bind(&done); |
388 } | 385 } |
389 | 386 |
390 | 387 |
391 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 388 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
392 const Register obj = locs()->in(0).reg(); | 389 const Register obj = locs()->in(0).reg(); |
393 const Register result = locs()->out(0).reg(); | 390 const Register result = locs()->out(0).reg(); |
394 | 391 |
395 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 392 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
396 ASSERT(obj == result); | 393 ASSERT(obj == result); |
397 } | 394 } |
398 | 395 |
399 | 396 |
400 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 397 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
401 switch (kind) { | 398 switch (kind) { |
402 case Token::kEQ: return EQ; | 399 case Token::kEQ: |
403 case Token::kNE: return NE; | 400 return EQ; |
404 case Token::kLT: return LT; | 401 case Token::kNE: |
405 case Token::kGT: return GT; | 402 return NE; |
406 case Token::kLTE: return LE; | 403 case Token::kLT: |
407 case Token::kGTE: return GE; | 404 return LT; |
| 405 case Token::kGT: |
| 406 return GT; |
| 407 case Token::kLTE: |
| 408 return LE; |
| 409 case Token::kGTE: |
| 410 return GE; |
408 default: | 411 default: |
409 UNREACHABLE(); | 412 UNREACHABLE(); |
410 return VS; | 413 return VS; |
411 } | 414 } |
412 } | 415 } |
413 | 416 |
414 | 417 |
415 static Condition FlipCondition(Condition condition) { | 418 static Condition FlipCondition(Condition condition) { |
416 switch (condition) { | 419 switch (condition) { |
417 case EQ: return EQ; | 420 case EQ: |
418 case NE: return NE; | 421 return EQ; |
419 case LT: return GT; | 422 case NE: |
420 case LE: return GE; | 423 return NE; |
421 case GT: return LT; | 424 case LT: |
422 case GE: return LE; | 425 return GT; |
423 case CC: return HI; | 426 case LE: |
424 case LS: return CS; | 427 return GE; |
425 case HI: return CC; | 428 case GT: |
426 case CS: return LS; | 429 return LT; |
| 430 case GE: |
| 431 return LE; |
| 432 case CC: |
| 433 return HI; |
| 434 case LS: |
| 435 return CS; |
| 436 case HI: |
| 437 return CC; |
| 438 case CS: |
| 439 return LS; |
427 default: | 440 default: |
428 UNREACHABLE(); | 441 UNREACHABLE(); |
429 return EQ; | 442 return EQ; |
430 } | 443 } |
431 } | 444 } |
432 | 445 |
433 | 446 |
434 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 447 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
435 Condition true_condition, | 448 Condition true_condition, |
436 BranchLabels labels) { | 449 BranchLabels labels) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 __ CompareRegisters(left.reg(), right.reg()); | 481 __ CompareRegisters(left.reg(), right.reg()); |
469 } | 482 } |
470 return true_condition; | 483 return true_condition; |
471 } | 484 } |
472 | 485 |
473 | 486 |
474 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 487 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |
475 bool opt) const { | 488 bool opt) const { |
476 const intptr_t kNumInputs = 2; | 489 const intptr_t kNumInputs = 2; |
477 if (operation_cid() == kDoubleCid) { | 490 if (operation_cid() == kDoubleCid) { |
478 const intptr_t kNumTemps = 0; | 491 const intptr_t kNumTemps = 0; |
479 LocationSummary* locs = new(zone) LocationSummary( | 492 LocationSummary* locs = new (zone) |
480 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 493 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
481 locs->set_in(0, Location::RequiresFpuRegister()); | 494 locs->set_in(0, Location::RequiresFpuRegister()); |
482 locs->set_in(1, Location::RequiresFpuRegister()); | 495 locs->set_in(1, Location::RequiresFpuRegister()); |
483 locs->set_out(0, Location::RequiresRegister()); | 496 locs->set_out(0, Location::RequiresRegister()); |
484 return locs; | 497 return locs; |
485 } | 498 } |
486 if (operation_cid() == kSmiCid) { | 499 if (operation_cid() == kSmiCid) { |
487 const intptr_t kNumTemps = 0; | 500 const intptr_t kNumTemps = 0; |
488 LocationSummary* locs = new(zone) LocationSummary( | 501 LocationSummary* locs = new (zone) |
489 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 502 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
490 locs->set_in(0, Location::RegisterOrConstant(left())); | 503 locs->set_in(0, Location::RegisterOrConstant(left())); |
491 // Only one input can be a constant operand. The case of two constant | 504 // Only one input can be a constant operand. The case of two constant |
492 // operands should be handled by constant propagation. | 505 // operands should be handled by constant propagation. |
493 // Only right can be a stack slot. | 506 // Only right can be a stack slot. |
494 locs->set_in(1, locs->in(0).IsConstant() | 507 locs->set_in(1, locs->in(0).IsConstant() |
495 ? Location::RequiresRegister() | 508 ? Location::RequiresRegister() |
496 : Location::RegisterOrConstant(right())); | 509 : Location::RegisterOrConstant(right())); |
497 locs->set_out(0, Location::RequiresRegister()); | 510 locs->set_out(0, Location::RequiresRegister()); |
498 return locs; | 511 return locs; |
499 } | 512 } |
500 UNREACHABLE(); | 513 UNREACHABLE(); |
501 return NULL; | 514 return NULL; |
502 } | 515 } |
503 | 516 |
504 | 517 |
505 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 518 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
506 switch (kind) { | 519 switch (kind) { |
507 case Token::kEQ: return EQ; | 520 case Token::kEQ: |
508 case Token::kNE: return NE; | 521 return EQ; |
509 case Token::kLT: return LT; | 522 case Token::kNE: |
510 case Token::kGT: return GT; | 523 return NE; |
511 case Token::kLTE: return LE; | 524 case Token::kLT: |
512 case Token::kGTE: return GE; | 525 return LT; |
| 526 case Token::kGT: |
| 527 return GT; |
| 528 case Token::kLTE: |
| 529 return LE; |
| 530 case Token::kGTE: |
| 531 return GE; |
513 default: | 532 default: |
514 UNREACHABLE(); | 533 UNREACHABLE(); |
515 return VS; | 534 return VS; |
516 } | 535 } |
517 } | 536 } |
518 | 537 |
519 | 538 |
520 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 539 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
521 LocationSummary* locs, | 540 LocationSummary* locs, |
522 Token::Kind kind) { | 541 Token::Kind kind) { |
(...skipping 12 matching lines...) Expand all Loading... |
535 } else { | 554 } else { |
536 ASSERT(operation_cid() == kDoubleCid); | 555 ASSERT(operation_cid() == kDoubleCid); |
537 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 556 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
538 } | 557 } |
539 } | 558 } |
540 | 559 |
541 | 560 |
542 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 561 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
543 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 562 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
544 Label is_true, is_false; | 563 Label is_true, is_false; |
545 BranchLabels labels = { &is_true, &is_false, &is_false }; | 564 BranchLabels labels = {&is_true, &is_false, &is_false}; |
546 Condition true_condition = EmitComparisonCode(compiler, labels); | 565 Condition true_condition = EmitComparisonCode(compiler, labels); |
547 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { | 566 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { |
548 // Special case for NaN comparison. Result is always false unless | 567 // Special case for NaN comparison. Result is always false unless |
549 // relational operator is !=. | 568 // relational operator is !=. |
550 __ b(&is_false, VS); | 569 __ b(&is_false, VS); |
551 } | 570 } |
552 EmitBranchOnCondition(compiler, true_condition, labels); | 571 EmitBranchOnCondition(compiler, true_condition, labels); |
553 // TODO(zra): instead of branching, use the csel instruction to get | 572 // TODO(zra): instead of branching, use the csel instruction to get |
554 // True or False into result. | 573 // True or False into result. |
555 const Register result = locs()->out(0).reg(); | 574 const Register result = locs()->out(0).reg(); |
(...skipping 15 matching lines...) Expand all Loading... |
571 Condition true_condition = EmitComparisonCode(compiler, labels); | 590 Condition true_condition = EmitComparisonCode(compiler, labels); |
572 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { | 591 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { |
573 // Special case for NaN comparison. Result is always false unless | 592 // Special case for NaN comparison. Result is always false unless |
574 // relational operator is !=. | 593 // relational operator is !=. |
575 __ b(labels.false_label, VS); | 594 __ b(labels.false_label, VS); |
576 } | 595 } |
577 EmitBranchOnCondition(compiler, true_condition, labels); | 596 EmitBranchOnCondition(compiler, true_condition, labels); |
578 } | 597 } |
579 | 598 |
580 | 599 |
581 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, | 600 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
582 bool opt) const { | |
583 const intptr_t kNumInputs = 2; | 601 const intptr_t kNumInputs = 2; |
584 const intptr_t kNumTemps = 0; | 602 const intptr_t kNumTemps = 0; |
585 LocationSummary* locs = new(zone) LocationSummary( | 603 LocationSummary* locs = new (zone) |
586 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 604 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
587 locs->set_in(0, Location::RequiresRegister()); | 605 locs->set_in(0, Location::RequiresRegister()); |
588 // Only one input can be a constant operand. The case of two constant | 606 // Only one input can be a constant operand. The case of two constant |
589 // operands should be handled by constant propagation. | 607 // operands should be handled by constant propagation. |
590 locs->set_in(1, Location::RegisterOrConstant(right())); | 608 locs->set_in(1, Location::RegisterOrConstant(right())); |
591 return locs; | 609 return locs; |
592 } | 610 } |
593 | 611 |
594 | 612 |
595 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 613 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
596 BranchLabels labels) { | 614 BranchLabels labels) { |
597 const Register left = locs()->in(0).reg(); | 615 const Register left = locs()->in(0).reg(); |
598 Location right = locs()->in(1); | 616 Location right = locs()->in(1); |
599 if (right.IsConstant()) { | 617 if (right.IsConstant()) { |
600 ASSERT(right.constant().IsSmi()); | 618 ASSERT(right.constant().IsSmi()); |
601 const int64_t imm = | 619 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); |
602 reinterpret_cast<int64_t>(right.constant().raw()); | |
603 __ TestImmediate(left, imm); | 620 __ TestImmediate(left, imm); |
604 } else { | 621 } else { |
605 __ tst(left, Operand(right.reg())); | 622 __ tst(left, Operand(right.reg())); |
606 } | 623 } |
607 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; | 624 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |
608 return true_condition; | 625 return true_condition; |
609 } | 626 } |
610 | 627 |
611 | 628 |
612 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 629 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
613 // Never emitted outside of the BranchInstr. | 630 // Never emitted outside of the BranchInstr. |
614 UNREACHABLE(); | 631 UNREACHABLE(); |
615 } | 632 } |
616 | 633 |
617 | 634 |
618 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 635 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
619 BranchInstr* branch) { | 636 BranchInstr* branch) { |
620 BranchLabels labels = compiler->CreateBranchLabels(branch); | 637 BranchLabels labels = compiler->CreateBranchLabels(branch); |
621 Condition true_condition = EmitComparisonCode(compiler, labels); | 638 Condition true_condition = EmitComparisonCode(compiler, labels); |
622 EmitBranchOnCondition(compiler, true_condition, labels); | 639 EmitBranchOnCondition(compiler, true_condition, labels); |
623 } | 640 } |
624 | 641 |
625 | 642 |
626 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 643 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
627 bool opt) const { | 644 bool opt) const { |
628 const intptr_t kNumInputs = 1; | 645 const intptr_t kNumInputs = 1; |
629 const intptr_t kNumTemps = 1; | 646 const intptr_t kNumTemps = 1; |
630 LocationSummary* locs = new(zone) LocationSummary( | 647 LocationSummary* locs = new (zone) |
631 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 648 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
632 locs->set_in(0, Location::RequiresRegister()); | 649 locs->set_in(0, Location::RequiresRegister()); |
633 locs->set_temp(0, Location::RequiresRegister()); | 650 locs->set_temp(0, Location::RequiresRegister()); |
634 locs->set_out(0, Location::RequiresRegister()); | 651 locs->set_out(0, Location::RequiresRegister()); |
635 return locs; | 652 return locs; |
636 } | 653 } |
637 | 654 |
638 | 655 |
639 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 656 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
640 BranchLabels labels) { | 657 BranchLabels labels) { |
641 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 658 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
642 const Register val_reg = locs()->in(0).reg(); | 659 const Register val_reg = locs()->in(0).reg(); |
643 const Register cid_reg = locs()->temp(0).reg(); | 660 const Register cid_reg = locs()->temp(0).reg(); |
644 | 661 |
645 Label* deopt = CanDeoptimize() | 662 Label* deopt = |
646 ? compiler->AddDeoptStub(deopt_id(), | 663 CanDeoptimize() |
647 ICData::kDeoptTestCids, | 664 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, |
648 licm_hoisted_ ? ICData::kHoisted : 0) | 665 licm_hoisted_ ? ICData::kHoisted : 0) |
649 : NULL; | 666 : NULL; |
650 | 667 |
651 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 668 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
652 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 669 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
653 ASSERT(data[0] == kSmiCid); | 670 ASSERT(data[0] == kSmiCid); |
654 bool result = data[1] == true_result; | 671 bool result = data[1] == true_result; |
655 __ tsti(val_reg, Immediate(kSmiTagMask)); | 672 __ tsti(val_reg, Immediate(kSmiTagMask)); |
656 __ b(result ? labels.true_label : labels.false_label, EQ); | 673 __ b(result ? labels.true_label : labels.false_label, EQ); |
657 __ LoadClassId(cid_reg, val_reg); | 674 __ LoadClassId(cid_reg, val_reg); |
658 | 675 |
659 for (intptr_t i = 2; i < data.length(); i += 2) { | 676 for (intptr_t i = 2; i < data.length(); i += 2) { |
(...skipping 21 matching lines...) Expand all Loading... |
681 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 698 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
682 BranchInstr* branch) { | 699 BranchInstr* branch) { |
683 BranchLabels labels = compiler->CreateBranchLabels(branch); | 700 BranchLabels labels = compiler->CreateBranchLabels(branch); |
684 EmitComparisonCode(compiler, labels); | 701 EmitComparisonCode(compiler, labels); |
685 } | 702 } |
686 | 703 |
687 | 704 |
688 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 705 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
689 const Register result_reg = locs()->out(0).reg(); | 706 const Register result_reg = locs()->out(0).reg(); |
690 Label is_true, is_false, done; | 707 Label is_true, is_false, done; |
691 BranchLabels labels = { &is_true, &is_false, &is_false }; | 708 BranchLabels labels = {&is_true, &is_false, &is_false}; |
692 EmitComparisonCode(compiler, labels); | 709 EmitComparisonCode(compiler, labels); |
693 // TODO(zra): instead of branching, use the csel instruction to get | 710 // TODO(zra): instead of branching, use the csel instruction to get |
694 // True or False into result. | 711 // True or False into result. |
695 __ Bind(&is_false); | 712 __ Bind(&is_false); |
696 __ LoadObject(result_reg, Bool::False()); | 713 __ LoadObject(result_reg, Bool::False()); |
697 __ b(&done); | 714 __ b(&done); |
698 __ Bind(&is_true); | 715 __ Bind(&is_true); |
699 __ LoadObject(result_reg, Bool::True()); | 716 __ LoadObject(result_reg, Bool::True()); |
700 __ Bind(&done); | 717 __ Bind(&done); |
701 } | 718 } |
702 | 719 |
703 | 720 |
704 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 721 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
705 bool opt) const { | 722 bool opt) const { |
706 const intptr_t kNumInputs = 2; | 723 const intptr_t kNumInputs = 2; |
707 const intptr_t kNumTemps = 0; | 724 const intptr_t kNumTemps = 0; |
708 if (operation_cid() == kDoubleCid) { | 725 if (operation_cid() == kDoubleCid) { |
709 LocationSummary* summary = new(zone) LocationSummary( | 726 LocationSummary* summary = new (zone) |
710 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 727 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
711 summary->set_in(0, Location::RequiresFpuRegister()); | 728 summary->set_in(0, Location::RequiresFpuRegister()); |
712 summary->set_in(1, Location::RequiresFpuRegister()); | 729 summary->set_in(1, Location::RequiresFpuRegister()); |
713 summary->set_out(0, Location::RequiresRegister()); | 730 summary->set_out(0, Location::RequiresRegister()); |
714 return summary; | 731 return summary; |
715 } | 732 } |
716 ASSERT(operation_cid() == kSmiCid); | 733 ASSERT(operation_cid() == kSmiCid); |
717 LocationSummary* summary = new(zone) LocationSummary( | 734 LocationSummary* summary = new (zone) |
718 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 735 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
719 summary->set_in(0, Location::RegisterOrConstant(left())); | 736 summary->set_in(0, Location::RegisterOrConstant(left())); |
720 // Only one input can be a constant operand. The case of two constant | 737 // Only one input can be a constant operand. The case of two constant |
721 // operands should be handled by constant propagation. | 738 // operands should be handled by constant propagation. |
722 summary->set_in(1, summary->in(0).IsConstant() | 739 summary->set_in(1, summary->in(0).IsConstant() |
723 ? Location::RequiresRegister() | 740 ? Location::RequiresRegister() |
724 : Location::RegisterOrConstant(right())); | 741 : Location::RegisterOrConstant(right())); |
725 summary->set_out(0, Location::RequiresRegister()); | 742 summary->set_out(0, Location::RequiresRegister()); |
726 return summary; | 743 return summary; |
727 } | 744 } |
728 | 745 |
729 | 746 |
730 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 747 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
731 BranchLabels labels) { | 748 BranchLabels labels) { |
732 if (operation_cid() == kSmiCid) { | 749 if (operation_cid() == kSmiCid) { |
733 return EmitSmiComparisonOp(compiler, locs(), kind()); | 750 return EmitSmiComparisonOp(compiler, locs(), kind()); |
734 } else { | 751 } else { |
735 ASSERT(operation_cid() == kDoubleCid); | 752 ASSERT(operation_cid() == kDoubleCid); |
736 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 753 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
737 } | 754 } |
738 } | 755 } |
739 | 756 |
740 | 757 |
741 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 758 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
742 Label is_true, is_false; | 759 Label is_true, is_false; |
743 BranchLabels labels = { &is_true, &is_false, &is_false }; | 760 BranchLabels labels = {&is_true, &is_false, &is_false}; |
744 Condition true_condition = EmitComparisonCode(compiler, labels); | 761 Condition true_condition = EmitComparisonCode(compiler, labels); |
745 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { | 762 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { |
746 // Special case for NaN comparison. Result is always false unless | 763 // Special case for NaN comparison. Result is always false unless |
747 // relational operator is !=. | 764 // relational operator is !=. |
748 __ b(&is_false, VS); | 765 __ b(&is_false, VS); |
749 } | 766 } |
750 EmitBranchOnCondition(compiler, true_condition, labels); | 767 EmitBranchOnCondition(compiler, true_condition, labels); |
751 // TODO(zra): instead of branching, use the csel instruction to get | 768 // TODO(zra): instead of branching, use the csel instruction to get |
752 // True or False into result. | 769 // True or False into result. |
753 const Register result = locs()->out(0).reg(); | 770 const Register result = locs()->out(0).reg(); |
(...skipping 27 matching lines...) Expand all Loading... |
781 | 798 |
782 | 799 |
783 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 800 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
784 SetupNative(); | 801 SetupNative(); |
785 const Register result = locs()->out(0).reg(); | 802 const Register result = locs()->out(0).reg(); |
786 | 803 |
787 // Push the result place holder initialized to NULL. | 804 // Push the result place holder initialized to NULL. |
788 __ PushObject(Object::null_object()); | 805 __ PushObject(Object::null_object()); |
789 // Pass a pointer to the first argument in R2. | 806 // Pass a pointer to the first argument in R2. |
790 if (!function().HasOptionalParameters()) { | 807 if (!function().HasOptionalParameters()) { |
791 __ AddImmediate(R2, FP, (kParamEndSlotFromFp + | 808 __ AddImmediate( |
792 function().NumParameters()) * kWordSize); | 809 R2, FP, (kParamEndSlotFromFp + function().NumParameters()) * kWordSize); |
793 } else { | 810 } else { |
794 __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize); | 811 __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize); |
795 } | 812 } |
796 // Compute the effective address. When running under the simulator, | 813 // Compute the effective address. When running under the simulator, |
797 // this is a redirection address that forces the simulator to call | 814 // this is a redirection address that forces the simulator to call |
798 // into the runtime system. | 815 // into the runtime system. |
799 uword entry; | 816 uword entry; |
800 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 817 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
801 const StubEntry* stub_entry; | 818 const StubEntry* stub_entry; |
802 if (link_lazily()) { | 819 if (link_lazily()) { |
(...skipping 10 matching lines...) Expand all Loading... |
813 } else { | 830 } else { |
814 // In the case of non bootstrap native methods the CallNativeCFunction | 831 // In the case of non bootstrap native methods the CallNativeCFunction |
815 // stub generates the redirection address when running under the simulator | 832 // stub generates the redirection address when running under the simulator |
816 // and hence we do not change 'entry' here. | 833 // and hence we do not change 'entry' here. |
817 stub_entry = StubCode::CallNativeCFunction_entry(); | 834 stub_entry = StubCode::CallNativeCFunction_entry(); |
818 } | 835 } |
819 } | 836 } |
820 __ LoadImmediate(R1, argc_tag); | 837 __ LoadImmediate(R1, argc_tag); |
821 ExternalLabel label(entry); | 838 ExternalLabel label(entry); |
822 __ LoadNativeEntry(R5, &label); | 839 __ LoadNativeEntry(R5, &label); |
823 compiler->GenerateCall(token_pos(), | 840 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, |
824 *stub_entry, | |
825 RawPcDescriptors::kOther, | |
826 locs()); | 841 locs()); |
827 __ Pop(result); | 842 __ Pop(result); |
828 } | 843 } |
829 | 844 |
830 | 845 |
831 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 846 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |
832 Zone* zone, bool opt) const { | 847 Zone* zone, |
| 848 bool opt) const { |
833 const intptr_t kNumInputs = 1; | 849 const intptr_t kNumInputs = 1; |
834 // TODO(fschneider): Allow immediate operands for the char code. | 850 // TODO(fschneider): Allow immediate operands for the char code. |
835 return LocationSummary::Make(zone, | 851 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
836 kNumInputs, | |
837 Location::RequiresRegister(), | |
838 LocationSummary::kNoCall); | 852 LocationSummary::kNoCall); |
839 } | 853 } |
840 | 854 |
841 | 855 |
842 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 856 void OneByteStringFromCharCodeInstr::EmitNativeCode( |
843 FlowGraphCompiler* compiler) { | 857 FlowGraphCompiler* compiler) { |
844 ASSERT(compiler->is_optimizing()); | 858 ASSERT(compiler->is_optimizing()); |
845 const Register char_code = locs()->in(0).reg(); | 859 const Register char_code = locs()->in(0).reg(); |
846 const Register result = locs()->out(0).reg(); | 860 const Register result = locs()->out(0).reg(); |
847 | 861 |
848 __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset())); | 862 __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset())); |
849 __ AddImmediate( | 863 __ AddImmediate(result, result, |
850 result, result, Symbols::kNullCharCodeSymbolOffset * kWordSize); | 864 Symbols::kNullCharCodeSymbolOffset * kWordSize); |
851 __ SmiUntag(TMP, char_code); // Untag to use scaled adress mode. | 865 __ SmiUntag(TMP, char_code); // Untag to use scaled adress mode. |
852 __ ldr(result, Address(result, TMP, UXTX, Address::Scaled)); | 866 __ ldr(result, Address(result, TMP, UXTX, Address::Scaled)); |
853 } | 867 } |
854 | 868 |
855 | 869 |
856 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 870 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
857 bool opt) const { | 871 bool opt) const { |
858 const intptr_t kNumInputs = 1; | 872 const intptr_t kNumInputs = 1; |
859 return LocationSummary::Make(zone, | 873 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
860 kNumInputs, | |
861 Location::RequiresRegister(), | |
862 LocationSummary::kNoCall); | 874 LocationSummary::kNoCall); |
863 } | 875 } |
864 | 876 |
865 | 877 |
866 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 878 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
867 ASSERT(cid_ == kOneByteStringCid); | 879 ASSERT(cid_ == kOneByteStringCid); |
868 const Register str = locs()->in(0).reg(); | 880 const Register str = locs()->in(0).reg(); |
869 const Register result = locs()->out(0).reg(); | 881 const Register result = locs()->out(0).reg(); |
870 __ LoadFieldFromOffset(result, str, String::length_offset()); | 882 __ LoadFieldFromOffset(result, str, String::length_offset()); |
871 __ ldr(TMP, FieldAddress(str, OneByteString::data_offset()), kUnsignedByte); | 883 __ ldr(TMP, FieldAddress(str, OneByteString::data_offset()), kUnsignedByte); |
872 __ CompareImmediate(result, Smi::RawValue(1)); | 884 __ CompareImmediate(result, Smi::RawValue(1)); |
873 __ LoadImmediate(result, -1); | 885 __ LoadImmediate(result, -1); |
874 __ csel(result, TMP, result, EQ); | 886 __ csel(result, TMP, result, EQ); |
875 __ SmiTag(result); | 887 __ SmiTag(result); |
876 } | 888 } |
877 | 889 |
878 | 890 |
879 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 891 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |
880 bool opt) const { | 892 bool opt) const { |
881 const intptr_t kNumInputs = 1; | 893 const intptr_t kNumInputs = 1; |
882 const intptr_t kNumTemps = 0; | 894 const intptr_t kNumTemps = 0; |
883 LocationSummary* summary = new(zone) LocationSummary( | 895 LocationSummary* summary = new (zone) |
884 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 896 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
885 summary->set_in(0, Location::RegisterLocation(R0)); | 897 summary->set_in(0, Location::RegisterLocation(R0)); |
886 summary->set_out(0, Location::RegisterLocation(R0)); | 898 summary->set_out(0, Location::RegisterLocation(R0)); |
887 return summary; | 899 return summary; |
888 } | 900 } |
889 | 901 |
890 | 902 |
891 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 903 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
892 const Register array = locs()->in(0).reg(); | 904 const Register array = locs()->in(0).reg(); |
893 __ Push(array); | 905 __ Push(array); |
894 const int kNumberOfArguments = 1; | 906 const int kNumberOfArguments = 1; |
895 const Array& kNoArgumentNames = Object::null_array(); | 907 const Array& kNoArgumentNames = Object::null_array(); |
896 compiler->GenerateStaticCall(deopt_id(), | 908 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), |
897 token_pos(), | 909 kNumberOfArguments, kNoArgumentNames, locs(), |
898 CallFunction(), | |
899 kNumberOfArguments, | |
900 kNoArgumentNames, | |
901 locs(), | |
902 ICData::Handle()); | 910 ICData::Handle()); |
903 ASSERT(locs()->out(0).reg() == R0); | 911 ASSERT(locs()->out(0).reg() == R0); |
904 } | 912 } |
905 | 913 |
906 | 914 |
907 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 915 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |
908 bool opt) const { | 916 bool opt) const { |
909 const intptr_t kNumInputs = 1; | 917 const intptr_t kNumInputs = 1; |
910 return LocationSummary::Make(zone, | 918 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
911 kNumInputs, | |
912 Location::RequiresRegister(), | |
913 LocationSummary::kNoCall); | 919 LocationSummary::kNoCall); |
914 } | 920 } |
915 | 921 |
916 | 922 |
917 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 923 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
918 const Register obj = locs()->in(0).reg(); | 924 const Register obj = locs()->in(0).reg(); |
919 const Register result = locs()->out(0).reg(); | 925 const Register result = locs()->out(0).reg(); |
920 if (object()->definition()->representation() == kUntagged) { | 926 if (object()->definition()->representation() == kUntagged) { |
921 __ LoadFromOffset(result, obj, offset()); | 927 __ LoadFromOffset(result, obj, offset()); |
922 } else { | 928 } else { |
923 ASSERT(object()->definition()->representation() == kTagged); | 929 ASSERT(object()->definition()->representation() == kTagged); |
924 __ LoadFieldFromOffset(result, obj, offset()); | 930 __ LoadFieldFromOffset(result, obj, offset()); |
925 } | 931 } |
926 } | 932 } |
927 | 933 |
928 | 934 |
929 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 935 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |
930 bool opt) const { | 936 bool opt) const { |
931 const intptr_t kNumInputs = 1; | 937 const intptr_t kNumInputs = 1; |
932 return LocationSummary::Make(zone, | 938 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
933 kNumInputs, | |
934 Location::RequiresRegister(), | |
935 LocationSummary::kNoCall); | 939 LocationSummary::kNoCall); |
936 } | 940 } |
937 | 941 |
938 | 942 |
939 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 943 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
940 const Register object = locs()->in(0).reg(); | 944 const Register object = locs()->in(0).reg(); |
941 const Register result = locs()->out(0).reg(); | 945 const Register result = locs()->out(0).reg(); |
942 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 946 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |
943 if (CompileType::Smi().IsAssignableTo(value_type) || | 947 if (CompileType::Smi().IsAssignableTo(value_type) || |
944 value_type.IsTypeParameter()) { | 948 value_type.IsTypeParameter()) { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1024 } | 1028 } |
1025 | 1029 |
1026 | 1030 |
1027 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) { | 1031 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) { |
1028 ConstantInstr* constant = value->definition()->AsConstant(); | 1032 ConstantInstr* constant = value->definition()->AsConstant(); |
1029 if ((constant == NULL) || !constant->value().IsSmi()) { | 1033 if ((constant == NULL) || !constant->value().IsSmi()) { |
1030 return false; | 1034 return false; |
1031 } | 1035 } |
1032 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); | 1036 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); |
1033 const intptr_t scale = Instance::ElementSizeFor(cid); | 1037 const intptr_t scale = Instance::ElementSizeFor(cid); |
1034 const int64_t offset = index * scale + | 1038 const int64_t offset = |
| 1039 index * scale + |
1035 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); | 1040 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); |
1036 if (!Utils::IsInt(32, offset)) { | 1041 if (!Utils::IsInt(32, offset)) { |
1037 return false; | 1042 return false; |
1038 } | 1043 } |
1039 return Address::CanHoldOffset(static_cast<int32_t>(offset), | 1044 return Address::CanHoldOffset(static_cast<int32_t>(offset), Address::Offset, |
1040 Address::Offset, | |
1041 Address::OperandSizeFor(cid)); | 1045 Address::OperandSizeFor(cid)); |
1042 } | 1046 } |
1043 | 1047 |
1044 | 1048 |
1045 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 1049 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
1046 bool opt) const { | 1050 bool opt) const { |
1047 const intptr_t kNumInputs = 2; | 1051 const intptr_t kNumInputs = 2; |
1048 const intptr_t kNumTemps = aligned() ? 0 : 1; | 1052 const intptr_t kNumTemps = aligned() ? 0 : 1; |
1049 LocationSummary* locs = new(zone) LocationSummary( | 1053 LocationSummary* locs = new (zone) |
1050 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1054 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1051 locs->set_in(0, Location::RequiresRegister()); | 1055 locs->set_in(0, Location::RequiresRegister()); |
1052 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { | 1056 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { |
1053 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1057 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
1054 } else { | 1058 } else { |
1055 locs->set_in(1, Location::RequiresRegister()); | 1059 locs->set_in(1, Location::RequiresRegister()); |
1056 } | 1060 } |
1057 if ((representation() == kUnboxedDouble) || | 1061 if ((representation() == kUnboxedDouble) || |
1058 (representation() == kUnboxedFloat32x4) || | 1062 (representation() == kUnboxedFloat32x4) || |
1059 (representation() == kUnboxedInt32x4) || | 1063 (representation() == kUnboxedInt32x4) || |
1060 (representation() == kUnboxedFloat64x2)) { | 1064 (representation() == kUnboxedFloat64x2)) { |
1061 locs->set_out(0, Location::RequiresFpuRegister()); | 1065 locs->set_out(0, Location::RequiresFpuRegister()); |
1062 } else { | 1066 } else { |
1063 locs->set_out(0, Location::RequiresRegister()); | 1067 locs->set_out(0, Location::RequiresRegister()); |
1064 } | 1068 } |
1065 if (!aligned()) { | 1069 if (!aligned()) { |
1066 locs->set_temp(0, Location::RequiresRegister()); | 1070 locs->set_temp(0, Location::RequiresRegister()); |
1067 } | 1071 } |
1068 return locs; | 1072 return locs; |
1069 } | 1073 } |
1070 | 1074 |
1071 | 1075 |
1072 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1076 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1073 // The array register points to the backing store for external arrays. | 1077 // The array register points to the backing store for external arrays. |
1074 const Register array = locs()->in(0).reg(); | 1078 const Register array = locs()->in(0).reg(); |
1075 const Location index = locs()->in(1); | 1079 const Location index = locs()->in(1); |
1076 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); | 1080 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |
1077 | 1081 |
1078 Address element_address(TMP); // Bad address. | 1082 Address element_address(TMP); // Bad address. |
1079 if (aligned()) { | 1083 if (aligned()) { |
1080 element_address = index.IsRegister() | 1084 element_address = |
1081 ? __ ElementAddressForRegIndex(true, // Load. | 1085 index.IsRegister() |
1082 IsExternal(), class_id(), index_scale(), | 1086 ? __ ElementAddressForRegIndex(true, // Load. |
1083 array, index.reg()) | 1087 IsExternal(), class_id(), |
1084 : __ ElementAddressForIntIndex( | 1088 index_scale(), array, index.reg()) |
1085 IsExternal(), class_id(), index_scale(), | 1089 : __ ElementAddressForIntIndex(IsExternal(), class_id(), |
1086 array, Smi::Cast(index.constant()).Value()); | 1090 index_scale(), array, |
| 1091 Smi::Cast(index.constant()).Value()); |
1087 // Warning: element_address may use register TMP as base. | 1092 // Warning: element_address may use register TMP as base. |
1088 } else { | 1093 } else { |
1089 if (index.IsRegister()) { | 1094 if (index.IsRegister()) { |
1090 __ LoadElementAddressForRegIndex(address, | 1095 __ LoadElementAddressForRegIndex(address, |
1091 true, // Load. | 1096 true, // Load. |
1092 IsExternal(), class_id(), index_scale(), | 1097 IsExternal(), class_id(), index_scale(), |
1093 array, index.reg()); | 1098 array, index.reg()); |
1094 } else { | 1099 } else { |
1095 __ LoadElementAddressForIntIndex(address, | 1100 __ LoadElementAddressForIntIndex(address, IsExternal(), class_id(), |
1096 IsExternal(), class_id(), index_scale(), | 1101 index_scale(), array, |
1097 array, | |
1098 Smi::Cast(index.constant()).Value()); | 1102 Smi::Cast(index.constant()).Value()); |
1099 } | 1103 } |
1100 } | 1104 } |
1101 | 1105 |
1102 if ((representation() == kUnboxedDouble) || | 1106 if ((representation() == kUnboxedDouble) || |
1103 (representation() == kUnboxedFloat32x4) || | 1107 (representation() == kUnboxedFloat32x4) || |
1104 (representation() == kUnboxedInt32x4) || | 1108 (representation() == kUnboxedInt32x4) || |
1105 (representation() == kUnboxedFloat64x2)) { | 1109 (representation() == kUnboxedFloat64x2)) { |
1106 const VRegister result = locs()->out(0).fpu_reg(); | 1110 const VRegister result = locs()->out(0).fpu_reg(); |
1107 switch (class_id()) { | 1111 switch (class_id()) { |
1108 ASSERT(aligned()); | 1112 ASSERT(aligned()); |
1109 case kTypedDataFloat32ArrayCid: | 1113 case kTypedDataFloat32ArrayCid: |
1110 // Load single precision float. | 1114 // Load single precision float. |
1111 __ fldrs(result, element_address); | 1115 __ fldrs(result, element_address); |
1112 break; | 1116 break; |
1113 case kTypedDataFloat64ArrayCid: | 1117 case kTypedDataFloat64ArrayCid: |
1114 // Load double precision float. | 1118 // Load double precision float. |
(...skipping 25 matching lines...) Expand all Loading... |
1140 case kTypedDataUint32ArrayCid: | 1144 case kTypedDataUint32ArrayCid: |
1141 ASSERT(representation() == kUnboxedUint32); | 1145 ASSERT(representation() == kUnboxedUint32); |
1142 if (aligned()) { | 1146 if (aligned()) { |
1143 __ ldr(result, element_address, kUnsignedWord); | 1147 __ ldr(result, element_address, kUnsignedWord); |
1144 } else { | 1148 } else { |
1145 __ LoadUnaligned(result, address, TMP, kUnsignedWord); | 1149 __ LoadUnaligned(result, address, TMP, kUnsignedWord); |
1146 } | 1150 } |
1147 break; | 1151 break; |
1148 default: | 1152 default: |
1149 UNREACHABLE(); | 1153 UNREACHABLE(); |
1150 } | 1154 } |
1151 return; | 1155 return; |
1152 } | 1156 } |
1153 | 1157 |
1154 ASSERT(representation() == kTagged); | 1158 ASSERT(representation() == kTagged); |
1155 const Register result = locs()->out(0).reg(); | 1159 const Register result = locs()->out(0).reg(); |
1156 switch (class_id()) { | 1160 switch (class_id()) { |
1157 case kTypedDataInt8ArrayCid: | 1161 case kTypedDataInt8ArrayCid: |
1158 ASSERT(index_scale() == 1); | 1162 ASSERT(index_scale() == 1); |
1159 __ ldr(result, element_address, kByte); | 1163 __ ldr(result, element_address, kByte); |
1160 __ SmiTag(result); | 1164 __ SmiTag(result); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1193 __ ldr(result, element_address); | 1197 __ ldr(result, element_address); |
1194 break; | 1198 break; |
1195 } | 1199 } |
1196 } | 1200 } |
1197 | 1201 |
1198 | 1202 |
1199 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 1203 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |
1200 bool opt) const { | 1204 bool opt) const { |
1201 const intptr_t kNumInputs = 2; | 1205 const intptr_t kNumInputs = 2; |
1202 const intptr_t kNumTemps = 0; | 1206 const intptr_t kNumTemps = 0; |
1203 LocationSummary* summary = new(zone) LocationSummary( | 1207 LocationSummary* summary = new (zone) |
1204 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1208 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1205 summary->set_in(0, Location::RequiresRegister()); | 1209 summary->set_in(0, Location::RequiresRegister()); |
1206 summary->set_in(1, Location::RequiresRegister()); | 1210 summary->set_in(1, Location::RequiresRegister()); |
1207 summary->set_out(0, Location::RequiresRegister()); | 1211 summary->set_out(0, Location::RequiresRegister()); |
1208 return summary; | 1212 return summary; |
1209 } | 1213 } |
1210 | 1214 |
1211 | 1215 |
1212 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1216 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1213 // The string register points to the backing store for external strings. | 1217 // The string register points to the backing store for external strings. |
1214 const Register str = locs()->in(0).reg(); | 1218 const Register str = locs()->in(0).reg(); |
1215 const Location index = locs()->in(1); | 1219 const Location index = locs()->in(1); |
1216 | 1220 |
1217 Address element_address = __ ElementAddressForRegIndex( | 1221 Address element_address = __ ElementAddressForRegIndex( |
1218 true, IsExternal(), class_id(), index_scale(), str, index.reg()); | 1222 true, IsExternal(), class_id(), index_scale(), str, index.reg()); |
1219 // Warning: element_address may use register TMP as base. | 1223 // Warning: element_address may use register TMP as base. |
1220 | 1224 |
1221 Register result = locs()->out(0).reg(); | 1225 Register result = locs()->out(0).reg(); |
1222 switch (class_id()) { | 1226 switch (class_id()) { |
1223 case kOneByteStringCid: | 1227 case kOneByteStringCid: |
1224 case kExternalOneByteStringCid: | 1228 case kExternalOneByteStringCid: |
1225 switch (element_count()) { | 1229 switch (element_count()) { |
1226 case 1: __ ldr(result, element_address, kUnsignedByte); break; | 1230 case 1: |
1227 case 2: __ ldr(result, element_address, kUnsignedHalfword); break; | 1231 __ ldr(result, element_address, kUnsignedByte); |
1228 case 4: __ ldr(result, element_address, kUnsignedWord); break; | 1232 break; |
1229 default: UNREACHABLE(); | 1233 case 2: |
| 1234 __ ldr(result, element_address, kUnsignedHalfword); |
| 1235 break; |
| 1236 case 4: |
| 1237 __ ldr(result, element_address, kUnsignedWord); |
| 1238 break; |
| 1239 default: |
| 1240 UNREACHABLE(); |
1230 } | 1241 } |
1231 __ SmiTag(result); | 1242 __ SmiTag(result); |
1232 break; | 1243 break; |
1233 case kTwoByteStringCid: | 1244 case kTwoByteStringCid: |
1234 case kExternalTwoByteStringCid: | 1245 case kExternalTwoByteStringCid: |
1235 switch (element_count()) { | 1246 switch (element_count()) { |
1236 case 1: __ ldr(result, element_address, kUnsignedHalfword); break; | 1247 case 1: |
1237 case 2: __ ldr(result, element_address, kUnsignedWord); break; | 1248 __ ldr(result, element_address, kUnsignedHalfword); |
1238 default: UNREACHABLE(); | 1249 break; |
| 1250 case 2: |
| 1251 __ ldr(result, element_address, kUnsignedWord); |
| 1252 break; |
| 1253 default: |
| 1254 UNREACHABLE(); |
1239 } | 1255 } |
1240 __ SmiTag(result); | 1256 __ SmiTag(result); |
1241 break; | 1257 break; |
1242 default: | 1258 default: |
1243 UNREACHABLE(); | 1259 UNREACHABLE(); |
1244 break; | 1260 break; |
1245 } | 1261 } |
1246 } | 1262 } |
1247 | 1263 |
1248 | 1264 |
1249 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1265 Representation StoreIndexedInstr::RequiredInputRepresentation( |
1250 intptr_t idx) const { | 1266 intptr_t idx) const { |
1251 // Array can be a Dart object or a pointer to external data. | 1267 // Array can be a Dart object or a pointer to external data. |
1252 if (idx == 0) return kNoRepresentation; // Flexible input representation. | 1268 if (idx == 0) return kNoRepresentation; // Flexible input representation. |
1253 if (idx == 1) return kTagged; // Index is a smi. | 1269 if (idx == 1) return kTagged; // Index is a smi. |
1254 ASSERT(idx == 2); | 1270 ASSERT(idx == 2); |
1255 switch (class_id_) { | 1271 switch (class_id_) { |
1256 case kArrayCid: | 1272 case kArrayCid: |
1257 case kOneByteStringCid: | 1273 case kOneByteStringCid: |
1258 case kTypedDataInt8ArrayCid: | 1274 case kTypedDataInt8ArrayCid: |
1259 case kTypedDataUint8ArrayCid: | 1275 case kTypedDataUint8ArrayCid: |
1260 case kExternalTypedDataUint8ArrayCid: | 1276 case kExternalTypedDataUint8ArrayCid: |
1261 case kTypedDataUint8ClampedArrayCid: | 1277 case kTypedDataUint8ClampedArrayCid: |
1262 case kExternalTypedDataUint8ClampedArrayCid: | 1278 case kExternalTypedDataUint8ClampedArrayCid: |
1263 case kTypedDataInt16ArrayCid: | 1279 case kTypedDataInt16ArrayCid: |
(...skipping 16 matching lines...) Expand all Loading... |
1280 UNREACHABLE(); | 1296 UNREACHABLE(); |
1281 return kTagged; | 1297 return kTagged; |
1282 } | 1298 } |
1283 } | 1299 } |
1284 | 1300 |
1285 | 1301 |
1286 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1302 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
1287 bool opt) const { | 1303 bool opt) const { |
1288 const intptr_t kNumInputs = 3; | 1304 const intptr_t kNumInputs = 3; |
1289 const intptr_t kNumTemps = aligned() ? 0 : 2; | 1305 const intptr_t kNumTemps = aligned() ? 0 : 2; |
1290 LocationSummary* locs = new(zone) LocationSummary( | 1306 LocationSummary* locs = new (zone) |
1291 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1307 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1292 locs->set_in(0, Location::RequiresRegister()); | 1308 locs->set_in(0, Location::RequiresRegister()); |
1293 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { | 1309 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { |
1294 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1310 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
1295 } else { | 1311 } else { |
1296 locs->set_in(1, Location::WritableRegister()); | 1312 locs->set_in(1, Location::WritableRegister()); |
1297 } | 1313 } |
1298 switch (class_id()) { | 1314 switch (class_id()) { |
1299 case kArrayCid: | 1315 case kArrayCid: |
1300 locs->set_in(2, ShouldEmitStoreBarrier() | 1316 locs->set_in(2, ShouldEmitStoreBarrier() |
1301 ? Location::WritableRegister() | 1317 ? Location::WritableRegister() |
1302 : Location::RegisterOrConstant(value())); | 1318 : Location::RegisterOrConstant(value())); |
1303 break; | 1319 break; |
1304 case kExternalTypedDataUint8ArrayCid: | 1320 case kExternalTypedDataUint8ArrayCid: |
1305 case kExternalTypedDataUint8ClampedArrayCid: | 1321 case kExternalTypedDataUint8ClampedArrayCid: |
1306 case kTypedDataInt8ArrayCid: | 1322 case kTypedDataInt8ArrayCid: |
1307 case kTypedDataUint8ArrayCid: | 1323 case kTypedDataUint8ArrayCid: |
1308 case kTypedDataUint8ClampedArrayCid: | 1324 case kTypedDataUint8ClampedArrayCid: |
1309 case kOneByteStringCid: | 1325 case kOneByteStringCid: |
1310 case kTypedDataInt16ArrayCid: | 1326 case kTypedDataInt16ArrayCid: |
1311 case kTypedDataUint16ArrayCid: | 1327 case kTypedDataUint16ArrayCid: |
1312 case kTypedDataInt32ArrayCid: | 1328 case kTypedDataInt32ArrayCid: |
(...skipping 23 matching lines...) Expand all Loading... |
1336 | 1352 |
1337 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1353 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1338 // The array register points to the backing store for external arrays. | 1354 // The array register points to the backing store for external arrays. |
1339 const Register array = locs()->in(0).reg(); | 1355 const Register array = locs()->in(0).reg(); |
1340 const Location index = locs()->in(1); | 1356 const Location index = locs()->in(1); |
1341 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); | 1357 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |
1342 const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg(); | 1358 const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg(); |
1343 | 1359 |
1344 Address element_address(TMP); // Bad address. | 1360 Address element_address(TMP); // Bad address. |
1345 if (aligned()) { | 1361 if (aligned()) { |
1346 element_address = index.IsRegister() | 1362 element_address = |
1347 ? __ ElementAddressForRegIndex(false, // Store. | 1363 index.IsRegister() |
1348 IsExternal(), class_id(), index_scale(), | 1364 ? __ ElementAddressForRegIndex(false, // Store. |
1349 array, index.reg()) | 1365 IsExternal(), class_id(), |
1350 : __ ElementAddressForIntIndex( | 1366 index_scale(), array, index.reg()) |
1351 IsExternal(), class_id(), index_scale(), | 1367 : __ ElementAddressForIntIndex(IsExternal(), class_id(), |
1352 array, Smi::Cast(index.constant()).Value()); | 1368 index_scale(), array, |
| 1369 Smi::Cast(index.constant()).Value()); |
1353 } else { | 1370 } else { |
1354 if (index.IsRegister()) { | 1371 if (index.IsRegister()) { |
1355 __ LoadElementAddressForRegIndex(address, | 1372 __ LoadElementAddressForRegIndex(address, |
1356 false, // Store. | 1373 false, // Store. |
1357 IsExternal(), class_id(), index_scale(), | 1374 IsExternal(), class_id(), index_scale(), |
1358 array, index.reg()); | 1375 array, index.reg()); |
1359 } else { | 1376 } else { |
1360 __ LoadElementAddressForIntIndex(address, | 1377 __ LoadElementAddressForIntIndex(address, IsExternal(), class_id(), |
1361 IsExternal(), class_id(), index_scale(), | 1378 index_scale(), array, |
1362 array, | |
1363 Smi::Cast(index.constant()).Value()); | 1379 Smi::Cast(index.constant()).Value()); |
1364 } | 1380 } |
1365 } | 1381 } |
1366 | 1382 |
1367 switch (class_id()) { | 1383 switch (class_id()) { |
1368 case kArrayCid: | 1384 case kArrayCid: |
1369 ASSERT(aligned()); | 1385 ASSERT(aligned()); |
1370 if (ShouldEmitStoreBarrier()) { | 1386 if (ShouldEmitStoreBarrier()) { |
1371 const Register value = locs()->in(2).reg(); | 1387 const Register value = locs()->in(2).reg(); |
1372 __ StoreIntoObject(array, element_address, value); | 1388 __ StoreIntoObject(array, element_address, value); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1405 value = 0xFF; | 1421 value = 0xFF; |
1406 } else if (value < 0) { | 1422 } else if (value < 0) { |
1407 value = 0; | 1423 value = 0; |
1408 } | 1424 } |
1409 __ LoadImmediate(TMP, static_cast<int8_t>(value)); | 1425 __ LoadImmediate(TMP, static_cast<int8_t>(value)); |
1410 __ str(TMP, element_address, kUnsignedByte); | 1426 __ str(TMP, element_address, kUnsignedByte); |
1411 } else { | 1427 } else { |
1412 const Register value = locs()->in(2).reg(); | 1428 const Register value = locs()->in(2).reg(); |
1413 __ CompareImmediate(value, 0x1FE); // Smi value and smi 0xFF. | 1429 __ CompareImmediate(value, 0x1FE); // Smi value and smi 0xFF. |
1414 // Clamp to 0x00 or 0xFF respectively. | 1430 // Clamp to 0x00 or 0xFF respectively. |
1415 __ csetm(TMP, GT); // TMP = value > 0x1FE ? -1 : 0. | 1431 __ csetm(TMP, GT); // TMP = value > 0x1FE ? -1 : 0. |
1416 __ csel(TMP, value, TMP, LS); // TMP = value in range ? value : TMP. | 1432 __ csel(TMP, value, TMP, LS); // TMP = value in range ? value : TMP. |
1417 __ SmiUntag(TMP); | 1433 __ SmiUntag(TMP); |
1418 __ str(TMP, element_address, kUnsignedByte); | 1434 __ str(TMP, element_address, kUnsignedByte); |
1419 } | 1435 } |
1420 break; | 1436 break; |
1421 } | 1437 } |
1422 case kTypedDataInt16ArrayCid: | 1438 case kTypedDataInt16ArrayCid: |
1423 case kTypedDataUint16ArrayCid: { | 1439 case kTypedDataUint16ArrayCid: { |
1424 const Register value = locs()->in(2).reg(); | 1440 const Register value = locs()->in(2).reg(); |
1425 __ SmiUntag(TMP, value); | 1441 __ SmiUntag(TMP, value); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1485 } | 1501 } |
1486 | 1502 |
1487 | 1503 |
1488 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 1504 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |
1489 bool opt) const { | 1505 bool opt) const { |
1490 const intptr_t kNumInputs = 1; | 1506 const intptr_t kNumInputs = 1; |
1491 | 1507 |
1492 const intptr_t value_cid = value()->Type()->ToCid(); | 1508 const intptr_t value_cid = value()->Type()->ToCid(); |
1493 const intptr_t field_cid = field().guarded_cid(); | 1509 const intptr_t field_cid = field().guarded_cid(); |
1494 | 1510 |
1495 const bool emit_full_guard = | 1511 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); |
1496 !opt || (field_cid == kIllegalCid); | |
1497 | 1512 |
1498 const bool needs_value_cid_temp_reg = emit_full_guard || | 1513 const bool needs_value_cid_temp_reg = |
1499 ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); | 1514 emit_full_guard || ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); |
1500 | 1515 |
1501 const bool needs_field_temp_reg = emit_full_guard; | 1516 const bool needs_field_temp_reg = emit_full_guard; |
1502 | 1517 |
1503 intptr_t num_temps = 0; | 1518 intptr_t num_temps = 0; |
1504 if (needs_value_cid_temp_reg) { | 1519 if (needs_value_cid_temp_reg) { |
1505 num_temps++; | 1520 num_temps++; |
1506 } | 1521 } |
1507 if (needs_field_temp_reg) { | 1522 if (needs_field_temp_reg) { |
1508 num_temps++; | 1523 num_temps++; |
1509 } | 1524 } |
1510 | 1525 |
1511 LocationSummary* summary = new(zone) LocationSummary( | 1526 LocationSummary* summary = new (zone) |
1512 zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 1527 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
1513 summary->set_in(0, Location::RequiresRegister()); | 1528 summary->set_in(0, Location::RequiresRegister()); |
1514 | 1529 |
1515 for (intptr_t i = 0; i < num_temps; i++) { | 1530 for (intptr_t i = 0; i < num_temps; i++) { |
1516 summary->set_temp(i, Location::RequiresRegister()); | 1531 summary->set_temp(i, Location::RequiresRegister()); |
1517 } | 1532 } |
1518 | 1533 |
1519 return summary; | 1534 return summary; |
1520 } | 1535 } |
1521 | 1536 |
1522 | 1537 |
1523 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1538 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1524 ASSERT(sizeof(classid_t) == kInt32Size); | 1539 ASSERT(sizeof(classid_t) == kInt32Size); |
1525 const intptr_t value_cid = value()->Type()->ToCid(); | 1540 const intptr_t value_cid = value()->Type()->ToCid(); |
1526 const intptr_t field_cid = field().guarded_cid(); | 1541 const intptr_t field_cid = field().guarded_cid(); |
1527 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1542 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
1528 | 1543 |
1529 if (field_cid == kDynamicCid) { | 1544 if (field_cid == kDynamicCid) { |
1530 if (Compiler::IsBackgroundCompilation()) { | 1545 if (Compiler::IsBackgroundCompilation()) { |
1531 // Field state changed while compiling. | 1546 // Field state changed while compiling. |
1532 Compiler::AbortBackgroundCompilation(deopt_id(), | 1547 Compiler::AbortBackgroundCompilation( |
| 1548 deopt_id(), |
1533 "GuardFieldClassInstr: field state changed while compiling"); | 1549 "GuardFieldClassInstr: field state changed while compiling"); |
1534 } | 1550 } |
1535 ASSERT(!compiler->is_optimizing()); | 1551 ASSERT(!compiler->is_optimizing()); |
1536 return; // Nothing to emit. | 1552 return; // Nothing to emit. |
1537 } | 1553 } |
1538 | 1554 |
1539 const bool emit_full_guard = | 1555 const bool emit_full_guard = |
1540 !compiler->is_optimizing() || (field_cid == kIllegalCid); | 1556 !compiler->is_optimizing() || (field_cid == kIllegalCid); |
1541 | 1557 |
1542 const bool needs_value_cid_temp_reg = emit_full_guard || | 1558 const bool needs_value_cid_temp_reg = |
1543 ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); | 1559 emit_full_guard || ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); |
1544 | 1560 |
1545 const bool needs_field_temp_reg = emit_full_guard; | 1561 const bool needs_field_temp_reg = emit_full_guard; |
1546 | 1562 |
1547 const Register value_reg = locs()->in(0).reg(); | 1563 const Register value_reg = locs()->in(0).reg(); |
1548 | 1564 |
1549 const Register value_cid_reg = needs_value_cid_temp_reg ? | 1565 const Register value_cid_reg = |
1550 locs()->temp(0).reg() : kNoRegister; | 1566 needs_value_cid_temp_reg ? locs()->temp(0).reg() : kNoRegister; |
1551 | 1567 |
1552 const Register field_reg = needs_field_temp_reg ? | 1568 const Register field_reg = needs_field_temp_reg |
1553 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; | 1569 ? locs()->temp(locs()->temp_count() - 1).reg() |
| 1570 : kNoRegister; |
1554 | 1571 |
1555 Label ok, fail_label; | 1572 Label ok, fail_label; |
1556 | 1573 |
1557 Label* deopt = compiler->is_optimizing() ? | 1574 Label* deopt = |
1558 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1575 compiler->is_optimizing() |
| 1576 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1577 : NULL; |
1559 | 1578 |
1560 Label* fail = (deopt != NULL) ? deopt : &fail_label; | 1579 Label* fail = (deopt != NULL) ? deopt : &fail_label; |
1561 | 1580 |
1562 if (emit_full_guard) { | 1581 if (emit_full_guard) { |
1563 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1582 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
1564 | 1583 |
1565 FieldAddress field_cid_operand( | 1584 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset(), |
1566 field_reg, Field::guarded_cid_offset(), kUnsignedWord); | 1585 kUnsignedWord); |
1567 FieldAddress field_nullability_operand( | 1586 FieldAddress field_nullability_operand( |
1568 field_reg, Field::is_nullable_offset(), kUnsignedWord); | 1587 field_reg, Field::is_nullable_offset(), kUnsignedWord); |
1569 | 1588 |
1570 if (value_cid == kDynamicCid) { | 1589 if (value_cid == kDynamicCid) { |
1571 LoadValueCid(compiler, value_cid_reg, value_reg); | 1590 LoadValueCid(compiler, value_cid_reg, value_reg); |
1572 Label skip_length_check; | 1591 Label skip_length_check; |
1573 __ ldr(TMP, field_cid_operand, kUnsignedWord); | 1592 __ ldr(TMP, field_cid_operand, kUnsignedWord); |
1574 __ CompareRegisters(value_cid_reg, TMP); | 1593 __ CompareRegisters(value_cid_reg, TMP); |
1575 __ b(&ok, EQ); | 1594 __ b(&ok, EQ); |
1576 __ ldr(TMP, field_nullability_operand, kUnsignedWord); | 1595 __ ldr(TMP, field_nullability_operand, kUnsignedWord); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1610 if (deopt == NULL) { | 1629 if (deopt == NULL) { |
1611 ASSERT(!compiler->is_optimizing()); | 1630 ASSERT(!compiler->is_optimizing()); |
1612 __ b(&ok); | 1631 __ b(&ok); |
1613 } | 1632 } |
1614 } | 1633 } |
1615 | 1634 |
1616 if (deopt == NULL) { | 1635 if (deopt == NULL) { |
1617 ASSERT(!compiler->is_optimizing()); | 1636 ASSERT(!compiler->is_optimizing()); |
1618 __ Bind(fail); | 1637 __ Bind(fail); |
1619 | 1638 |
1620 __ LoadFieldFromOffset( | 1639 __ LoadFieldFromOffset(TMP, field_reg, Field::guarded_cid_offset(), |
1621 TMP, field_reg, Field::guarded_cid_offset(), kUnsignedWord); | 1640 kUnsignedWord); |
1622 __ CompareImmediate(TMP, kDynamicCid); | 1641 __ CompareImmediate(TMP, kDynamicCid); |
1623 __ b(&ok, EQ); | 1642 __ b(&ok, EQ); |
1624 | 1643 |
1625 __ Push(field_reg); | 1644 __ Push(field_reg); |
1626 __ Push(value_reg); | 1645 __ Push(value_reg); |
1627 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); | 1646 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); |
1628 __ Drop(2); // Drop the field and the value. | 1647 __ Drop(2); // Drop the field and the value. |
1629 } | 1648 } |
1630 } else { | 1649 } else { |
1631 ASSERT(compiler->is_optimizing()); | 1650 ASSERT(compiler->is_optimizing()); |
(...skipping 24 matching lines...) Expand all Loading... |
1656 } | 1675 } |
1657 __ Bind(&ok); | 1676 __ Bind(&ok); |
1658 } | 1677 } |
1659 | 1678 |
1660 | 1679 |
1661 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 1680 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |
1662 bool opt) const { | 1681 bool opt) const { |
1663 const intptr_t kNumInputs = 1; | 1682 const intptr_t kNumInputs = 1; |
1664 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1683 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
1665 const intptr_t kNumTemps = 3; | 1684 const intptr_t kNumTemps = 3; |
1666 LocationSummary* summary = new(zone) LocationSummary( | 1685 LocationSummary* summary = new (zone) |
1667 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1686 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1668 summary->set_in(0, Location::RequiresRegister()); | 1687 summary->set_in(0, Location::RequiresRegister()); |
1669 // We need temporaries for field object, length offset and expected length. | 1688 // We need temporaries for field object, length offset and expected length. |
1670 summary->set_temp(0, Location::RequiresRegister()); | 1689 summary->set_temp(0, Location::RequiresRegister()); |
1671 summary->set_temp(1, Location::RequiresRegister()); | 1690 summary->set_temp(1, Location::RequiresRegister()); |
1672 summary->set_temp(2, Location::RequiresRegister()); | 1691 summary->set_temp(2, Location::RequiresRegister()); |
1673 return summary; | 1692 return summary; |
1674 } else { | 1693 } else { |
1675 LocationSummary* summary = new(zone) LocationSummary( | 1694 LocationSummary* summary = new (zone) |
1676 zone, kNumInputs, 0, LocationSummary::kNoCall); | 1695 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
1677 summary->set_in(0, Location::RequiresRegister()); | 1696 summary->set_in(0, Location::RequiresRegister()); |
1678 return summary; | 1697 return summary; |
1679 } | 1698 } |
1680 UNREACHABLE(); | 1699 UNREACHABLE(); |
1681 } | 1700 } |
1682 | 1701 |
1683 | 1702 |
1684 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1703 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1685 if (field().guarded_list_length() == Field::kNoFixedLength) { | 1704 if (field().guarded_list_length() == Field::kNoFixedLength) { |
1686 if (Compiler::IsBackgroundCompilation()) { | 1705 if (Compiler::IsBackgroundCompilation()) { |
1687 // Field state changed while compiling. | 1706 // Field state changed while compiling. |
1688 Compiler::AbortBackgroundCompilation(deopt_id(), | 1707 Compiler::AbortBackgroundCompilation( |
| 1708 deopt_id(), |
1689 "GuardFieldLengthInstr: field state changed while compiling"); | 1709 "GuardFieldLengthInstr: field state changed while compiling"); |
1690 } | 1710 } |
1691 ASSERT(!compiler->is_optimizing()); | 1711 ASSERT(!compiler->is_optimizing()); |
1692 return; // Nothing to emit. | 1712 return; // Nothing to emit. |
1693 } | 1713 } |
1694 | 1714 |
1695 Label* deopt = compiler->is_optimizing() ? | 1715 Label* deopt = |
1696 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1716 compiler->is_optimizing() |
| 1717 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1718 : NULL; |
1697 | 1719 |
1698 const Register value_reg = locs()->in(0).reg(); | 1720 const Register value_reg = locs()->in(0).reg(); |
1699 | 1721 |
1700 if (!compiler->is_optimizing() || | 1722 if (!compiler->is_optimizing() || |
1701 (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1723 (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
1702 const Register field_reg = locs()->temp(0).reg(); | 1724 const Register field_reg = locs()->temp(0).reg(); |
1703 const Register offset_reg = locs()->temp(1).reg(); | 1725 const Register offset_reg = locs()->temp(1).reg(); |
1704 const Register length_reg = locs()->temp(2).reg(); | 1726 const Register length_reg = locs()->temp(2).reg(); |
1705 | 1727 |
1706 Label ok; | 1728 Label ok; |
1707 | 1729 |
1708 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1730 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
1709 | 1731 |
1710 __ ldr(offset_reg, | 1732 __ ldr(offset_reg, |
1711 FieldAddress(field_reg, | 1733 FieldAddress(field_reg, |
1712 Field::guarded_list_length_in_object_offset_offset()), | 1734 Field::guarded_list_length_in_object_offset_offset()), |
1713 kByte); | 1735 kByte); |
1714 __ ldr(length_reg, FieldAddress(field_reg, | 1736 __ ldr(length_reg, |
1715 Field::guarded_list_length_offset())); | 1737 FieldAddress(field_reg, Field::guarded_list_length_offset())); |
1716 | 1738 |
1717 __ tst(offset_reg, Operand(offset_reg)); | 1739 __ tst(offset_reg, Operand(offset_reg)); |
1718 __ b(&ok, MI); | 1740 __ b(&ok, MI); |
1719 | 1741 |
1720 // Load the length from the value. GuardFieldClass already verified that | 1742 // Load the length from the value. GuardFieldClass already verified that |
1721 // value's class matches guarded class id of the field. | 1743 // value's class matches guarded class id of the field. |
1722 // offset_reg contains offset already corrected by -kHeapObjectTag that is | 1744 // offset_reg contains offset already corrected by -kHeapObjectTag that is |
1723 // why we use Address instead of FieldAddress. | 1745 // why we use Address instead of FieldAddress. |
1724 __ ldr(TMP, Address(value_reg, offset_reg)); | 1746 __ ldr(TMP, Address(value_reg, offset_reg)); |
1725 __ CompareRegisters(length_reg, TMP); | 1747 __ CompareRegisters(length_reg, TMP); |
1726 | 1748 |
1727 if (deopt == NULL) { | 1749 if (deopt == NULL) { |
1728 __ b(&ok, EQ); | 1750 __ b(&ok, EQ); |
1729 | 1751 |
1730 __ Push(field_reg); | 1752 __ Push(field_reg); |
1731 __ Push(value_reg); | 1753 __ Push(value_reg); |
1732 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); | 1754 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); |
1733 __ Drop(2); // Drop the field and the value. | 1755 __ Drop(2); // Drop the field and the value. |
1734 } else { | 1756 } else { |
1735 __ b(deopt, NE); | 1757 __ b(deopt, NE); |
1736 } | 1758 } |
1737 | 1759 |
1738 __ Bind(&ok); | 1760 __ Bind(&ok); |
1739 } else { | 1761 } else { |
1740 ASSERT(compiler->is_optimizing()); | 1762 ASSERT(compiler->is_optimizing()); |
1741 ASSERT(field().guarded_list_length() >= 0); | 1763 ASSERT(field().guarded_list_length() >= 0); |
1742 ASSERT(field().guarded_list_length_in_object_offset() != | 1764 ASSERT(field().guarded_list_length_in_object_offset() != |
1743 Field::kUnknownLengthOffset); | 1765 Field::kUnknownLengthOffset); |
1744 | 1766 |
1745 __ ldr(TMP, FieldAddress(value_reg, | 1767 __ ldr(TMP, FieldAddress(value_reg, |
1746 field().guarded_list_length_in_object_offset())); | 1768 field().guarded_list_length_in_object_offset())); |
1747 __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length())); | 1769 __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length())); |
1748 __ b(deopt, NE); | 1770 __ b(deopt, NE); |
1749 } | 1771 } |
1750 } | 1772 } |
1751 | 1773 |
1752 | 1774 |
1753 class BoxAllocationSlowPath : public SlowPathCode { | 1775 class BoxAllocationSlowPath : public SlowPathCode { |
1754 public: | 1776 public: |
1755 BoxAllocationSlowPath(Instruction* instruction, | 1777 BoxAllocationSlowPath(Instruction* instruction, |
1756 const Class& cls, | 1778 const Class& cls, |
1757 Register result) | 1779 Register result) |
1758 : instruction_(instruction), | 1780 : instruction_(instruction), cls_(cls), result_(result) {} |
1759 cls_(cls), | |
1760 result_(result) { } | |
1761 | 1781 |
1762 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1782 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
1763 if (Assembler::EmittingComments()) { | 1783 if (Assembler::EmittingComments()) { |
1764 __ Comment("%s slow path allocation of %s", | 1784 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), |
1765 instruction_->DebugName(), | |
1766 String::Handle(cls_.ScrubbedName()).ToCString()); | 1785 String::Handle(cls_.ScrubbedName()).ToCString()); |
1767 } | 1786 } |
1768 __ Bind(entry_label()); | 1787 __ Bind(entry_label()); |
1769 const Code& stub = Code::ZoneHandle(compiler->zone(), | 1788 const Code& stub = Code::ZoneHandle( |
1770 StubCode::GetAllocationStubForClass(cls_)); | 1789 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); |
1771 const StubEntry stub_entry(stub); | 1790 const StubEntry stub_entry(stub); |
1772 | 1791 |
1773 LocationSummary* locs = instruction_->locs(); | 1792 LocationSummary* locs = instruction_->locs(); |
1774 | 1793 |
1775 locs->live_registers()->Remove(Location::RegisterLocation(result_)); | 1794 locs->live_registers()->Remove(Location::RegisterLocation(result_)); |
1776 | 1795 |
1777 compiler->SaveLiveRegisters(locs); | 1796 compiler->SaveLiveRegisters(locs); |
1778 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. | 1797 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. |
1779 stub_entry, | 1798 stub_entry, RawPcDescriptors::kOther, locs); |
1780 RawPcDescriptors::kOther, | |
1781 locs); | |
1782 compiler->AddStubCallTarget(stub); | 1799 compiler->AddStubCallTarget(stub); |
1783 __ mov(result_, R0); | 1800 __ mov(result_, R0); |
1784 compiler->RestoreLiveRegisters(locs); | 1801 compiler->RestoreLiveRegisters(locs); |
1785 __ b(exit_label()); | 1802 __ b(exit_label()); |
1786 } | 1803 } |
1787 | 1804 |
1788 static void Allocate(FlowGraphCompiler* compiler, | 1805 static void Allocate(FlowGraphCompiler* compiler, |
1789 Instruction* instruction, | 1806 Instruction* instruction, |
1790 const Class& cls, | 1807 const Class& cls, |
1791 Register result, | 1808 Register result, |
(...skipping 21 matching lines...) Expand all Loading... |
1813 StoreInstanceFieldInstr* instruction, | 1830 StoreInstanceFieldInstr* instruction, |
1814 Register box_reg, | 1831 Register box_reg, |
1815 const Class& cls, | 1832 const Class& cls, |
1816 Register instance_reg, | 1833 Register instance_reg, |
1817 intptr_t offset, | 1834 intptr_t offset, |
1818 Register temp) { | 1835 Register temp) { |
1819 Label done; | 1836 Label done; |
1820 __ LoadFieldFromOffset(box_reg, instance_reg, offset); | 1837 __ LoadFieldFromOffset(box_reg, instance_reg, offset); |
1821 __ CompareObject(box_reg, Object::null_object()); | 1838 __ CompareObject(box_reg, Object::null_object()); |
1822 __ b(&done, NE); | 1839 __ b(&done, NE); |
1823 BoxAllocationSlowPath::Allocate( | 1840 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); |
1824 compiler, instruction, cls, box_reg, temp); | |
1825 __ mov(temp, box_reg); | 1841 __ mov(temp, box_reg); |
1826 __ StoreIntoObjectOffset(instance_reg, offset, temp); | 1842 __ StoreIntoObjectOffset(instance_reg, offset, temp); |
1827 __ Bind(&done); | 1843 __ Bind(&done); |
1828 } | 1844 } |
1829 | 1845 |
1830 | 1846 |
1831 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 1847 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |
1832 bool opt) const { | 1848 bool opt) const { |
1833 const intptr_t kNumInputs = 2; | 1849 const intptr_t kNumInputs = 2; |
1834 const intptr_t kNumTemps = | 1850 const intptr_t kNumTemps = |
1835 (IsUnboxedStore() && opt) ? 2 : | 1851 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 2 : 0); |
1836 ((IsPotentialUnboxedStore()) ? 2 : 0); | 1852 LocationSummary* summary = new (zone) |
1837 LocationSummary* summary = new(zone) LocationSummary( | 1853 LocationSummary(zone, kNumInputs, kNumTemps, |
1838 zone, kNumInputs, kNumTemps, | 1854 ((IsUnboxedStore() && opt && is_initialization()) || |
1839 ((IsUnboxedStore() && opt && is_initialization()) || | 1855 IsPotentialUnboxedStore()) |
1840 IsPotentialUnboxedStore()) | 1856 ? LocationSummary::kCallOnSlowPath |
1841 ? LocationSummary::kCallOnSlowPath | 1857 : LocationSummary::kNoCall); |
1842 : LocationSummary::kNoCall); | |
1843 | 1858 |
1844 summary->set_in(0, Location::RequiresRegister()); | 1859 summary->set_in(0, Location::RequiresRegister()); |
1845 if (IsUnboxedStore() && opt) { | 1860 if (IsUnboxedStore() && opt) { |
1846 summary->set_in(1, Location::RequiresFpuRegister()); | 1861 summary->set_in(1, Location::RequiresFpuRegister()); |
1847 summary->set_temp(0, Location::RequiresRegister()); | 1862 summary->set_temp(0, Location::RequiresRegister()); |
1848 summary->set_temp(1, Location::RequiresRegister()); | 1863 summary->set_temp(1, Location::RequiresRegister()); |
1849 } else if (IsPotentialUnboxedStore()) { | 1864 } else if (IsPotentialUnboxedStore()) { |
1850 summary->set_in(1, ShouldEmitStoreBarrier() | 1865 summary->set_in(1, ShouldEmitStoreBarrier() ? Location::WritableRegister() |
1851 ? Location::WritableRegister() | 1866 : Location::RequiresRegister()); |
1852 : Location::RequiresRegister()); | 1867 summary->set_temp(0, Location::RequiresRegister()); |
1853 summary->set_temp(0, Location::RequiresRegister()); | 1868 summary->set_temp(1, Location::RequiresRegister()); |
1854 summary->set_temp(1, Location::RequiresRegister()); | |
1855 } else { | 1869 } else { |
1856 summary->set_in(1, ShouldEmitStoreBarrier() | 1870 summary->set_in(1, ShouldEmitStoreBarrier() |
1857 ? Location::WritableRegister() | 1871 ? Location::WritableRegister() |
1858 : Location::RegisterOrConstant(value())); | 1872 : Location::RegisterOrConstant(value())); |
1859 } | 1873 } |
1860 return summary; | 1874 return summary; |
1861 } | 1875 } |
1862 | 1876 |
1863 | 1877 |
1864 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1878 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1865 ASSERT(sizeof(classid_t) == kInt32Size); | 1879 ASSERT(sizeof(classid_t) == kInt32Size); |
1866 Label skip_store; | 1880 Label skip_store; |
1867 | 1881 |
1868 const Register instance_reg = locs()->in(0).reg(); | 1882 const Register instance_reg = locs()->in(0).reg(); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1931 Label store_float32x4; | 1945 Label store_float32x4; |
1932 Label store_float64x2; | 1946 Label store_float64x2; |
1933 | 1947 |
1934 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 1948 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
1935 | 1949 |
1936 __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(), | 1950 __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(), |
1937 kUnsignedWord); | 1951 kUnsignedWord); |
1938 __ CompareImmediate(temp2, kNullCid); | 1952 __ CompareImmediate(temp2, kNullCid); |
1939 __ b(&store_pointer, EQ); | 1953 __ b(&store_pointer, EQ); |
1940 | 1954 |
1941 __ LoadFromOffset( | 1955 __ LoadFromOffset(temp2, temp, Field::kind_bits_offset() - kHeapObjectTag, |
1942 temp2, temp, Field::kind_bits_offset() - kHeapObjectTag, | 1956 kUnsignedByte); |
1943 kUnsignedByte); | |
1944 __ tsti(temp2, Immediate(1 << Field::kUnboxingCandidateBit)); | 1957 __ tsti(temp2, Immediate(1 << Field::kUnboxingCandidateBit)); |
1945 __ b(&store_pointer, EQ); | 1958 __ b(&store_pointer, EQ); |
1946 | 1959 |
1947 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), | 1960 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), |
1948 kUnsignedWord); | 1961 kUnsignedWord); |
1949 __ CompareImmediate(temp2, kDoubleCid); | 1962 __ CompareImmediate(temp2, kDoubleCid); |
1950 __ b(&store_double, EQ); | 1963 __ b(&store_double, EQ); |
1951 | 1964 |
1952 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), | 1965 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), |
1953 kUnsignedWord); | 1966 kUnsignedWord); |
1954 __ CompareImmediate(temp2, kFloat32x4Cid); | 1967 __ CompareImmediate(temp2, kFloat32x4Cid); |
1955 __ b(&store_float32x4, EQ); | 1968 __ b(&store_float32x4, EQ); |
1956 | 1969 |
1957 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), | 1970 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), |
1958 kUnsignedWord); | 1971 kUnsignedWord); |
1959 __ CompareImmediate(temp2, kFloat64x2Cid); | 1972 __ CompareImmediate(temp2, kFloat64x2Cid); |
1960 __ b(&store_float64x2, EQ); | 1973 __ b(&store_float64x2, EQ); |
1961 | 1974 |
1962 // Fall through. | 1975 // Fall through. |
1963 __ b(&store_pointer); | 1976 __ b(&store_pointer); |
1964 | 1977 |
1965 if (!compiler->is_optimizing()) { | 1978 if (!compiler->is_optimizing()) { |
1966 locs()->live_registers()->Add(locs()->in(0)); | 1979 locs()->live_registers()->Add(locs()->in(0)); |
1967 locs()->live_registers()->Add(locs()->in(1)); | 1980 locs()->live_registers()->Add(locs()->in(1)); |
1968 } | 1981 } |
1969 | 1982 |
1970 { | 1983 { |
1971 __ Bind(&store_double); | 1984 __ Bind(&store_double); |
1972 EnsureMutableBox(compiler, | 1985 EnsureMutableBox(compiler, this, temp, compiler->double_class(), |
1973 this, | 1986 instance_reg, offset_in_bytes_, temp2); |
1974 temp, | |
1975 compiler->double_class(), | |
1976 instance_reg, | |
1977 offset_in_bytes_, | |
1978 temp2); | |
1979 __ LoadDFieldFromOffset(VTMP, value_reg, Double::value_offset()); | 1987 __ LoadDFieldFromOffset(VTMP, value_reg, Double::value_offset()); |
1980 __ StoreDFieldToOffset(VTMP, temp, Double::value_offset()); | 1988 __ StoreDFieldToOffset(VTMP, temp, Double::value_offset()); |
1981 __ b(&skip_store); | 1989 __ b(&skip_store); |
1982 } | 1990 } |
1983 | 1991 |
1984 { | 1992 { |
1985 __ Bind(&store_float32x4); | 1993 __ Bind(&store_float32x4); |
1986 EnsureMutableBox(compiler, | 1994 EnsureMutableBox(compiler, this, temp, compiler->float32x4_class(), |
1987 this, | 1995 instance_reg, offset_in_bytes_, temp2); |
1988 temp, | |
1989 compiler->float32x4_class(), | |
1990 instance_reg, | |
1991 offset_in_bytes_, | |
1992 temp2); | |
1993 __ LoadQFieldFromOffset(VTMP, value_reg, Float32x4::value_offset()); | 1996 __ LoadQFieldFromOffset(VTMP, value_reg, Float32x4::value_offset()); |
1994 __ StoreQFieldToOffset(VTMP, temp, Float32x4::value_offset()); | 1997 __ StoreQFieldToOffset(VTMP, temp, Float32x4::value_offset()); |
1995 __ b(&skip_store); | 1998 __ b(&skip_store); |
1996 } | 1999 } |
1997 | 2000 |
1998 { | 2001 { |
1999 __ Bind(&store_float64x2); | 2002 __ Bind(&store_float64x2); |
2000 EnsureMutableBox(compiler, | 2003 EnsureMutableBox(compiler, this, temp, compiler->float64x2_class(), |
2001 this, | 2004 instance_reg, offset_in_bytes_, temp2); |
2002 temp, | |
2003 compiler->float64x2_class(), | |
2004 instance_reg, | |
2005 offset_in_bytes_, | |
2006 temp2); | |
2007 __ LoadQFieldFromOffset(VTMP, value_reg, Float64x2::value_offset()); | 2005 __ LoadQFieldFromOffset(VTMP, value_reg, Float64x2::value_offset()); |
2008 __ StoreQFieldToOffset(VTMP, temp, Float64x2::value_offset()); | 2006 __ StoreQFieldToOffset(VTMP, temp, Float64x2::value_offset()); |
2009 __ b(&skip_store); | 2007 __ b(&skip_store); |
2010 } | 2008 } |
2011 | 2009 |
2012 __ Bind(&store_pointer); | 2010 __ Bind(&store_pointer); |
2013 } | 2011 } |
2014 | 2012 |
2015 if (ShouldEmitStoreBarrier()) { | 2013 if (ShouldEmitStoreBarrier()) { |
2016 const Register value_reg = locs()->in(1).reg(); | 2014 const Register value_reg = locs()->in(1).reg(); |
2017 __ StoreIntoObjectOffset( | 2015 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, value_reg, |
2018 instance_reg, offset_in_bytes_, value_reg, CanValueBeSmi()); | 2016 CanValueBeSmi()); |
2019 } else { | 2017 } else { |
2020 if (locs()->in(1).IsConstant()) { | 2018 if (locs()->in(1).IsConstant()) { |
2021 __ StoreIntoObjectOffsetNoBarrier( | 2019 __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes_, |
2022 instance_reg, offset_in_bytes_, locs()->in(1).constant()); | 2020 locs()->in(1).constant()); |
2023 } else { | 2021 } else { |
2024 const Register value_reg = locs()->in(1).reg(); | 2022 const Register value_reg = locs()->in(1).reg(); |
2025 __ StoreIntoObjectOffsetNoBarrier( | 2023 __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes_, |
2026 instance_reg, offset_in_bytes_, value_reg); | 2024 value_reg); |
2027 } | 2025 } |
2028 } | 2026 } |
2029 __ Bind(&skip_store); | 2027 __ Bind(&skip_store); |
2030 } | 2028 } |
2031 | 2029 |
2032 | 2030 |
2033 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2031 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |
2034 bool opt) const { | 2032 bool opt) const { |
2035 const intptr_t kNumInputs = 1; | 2033 const intptr_t kNumInputs = 1; |
2036 const intptr_t kNumTemps = 0; | 2034 const intptr_t kNumTemps = 0; |
2037 LocationSummary* summary = new(zone) LocationSummary( | 2035 LocationSummary* summary = new (zone) |
2038 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2036 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2039 summary->set_in(0, Location::RequiresRegister()); | 2037 summary->set_in(0, Location::RequiresRegister()); |
2040 summary->set_out(0, Location::RequiresRegister()); | 2038 summary->set_out(0, Location::RequiresRegister()); |
2041 return summary; | 2039 return summary; |
2042 } | 2040 } |
2043 | 2041 |
2044 | 2042 |
2045 // When the parser is building an implicit static getter for optimization, | 2043 // When the parser is building an implicit static getter for optimization, |
2046 // it can generate a function body where deoptimization ids do not line up | 2044 // it can generate a function body where deoptimization ids do not line up |
2047 // with the unoptimized code. | 2045 // with the unoptimized code. |
2048 // | 2046 // |
2049 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 2047 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
2050 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2048 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2051 const Register field = locs()->in(0).reg(); | 2049 const Register field = locs()->in(0).reg(); |
2052 const Register result = locs()->out(0).reg(); | 2050 const Register result = locs()->out(0).reg(); |
2053 __ LoadFieldFromOffset(result, field, Field::static_value_offset()); | 2051 __ LoadFieldFromOffset(result, field, Field::static_value_offset()); |
2054 } | 2052 } |
2055 | 2053 |
2056 | 2054 |
2057 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2055 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |
2058 bool opt) const { | 2056 bool opt) const { |
2059 LocationSummary* locs = new(zone) LocationSummary( | 2057 LocationSummary* locs = |
2060 zone, 1, 1, LocationSummary::kNoCall); | 2058 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); |
2061 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 2059 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
2062 : Location::RequiresRegister()); | 2060 : Location::RequiresRegister()); |
2063 locs->set_temp(0, Location::RequiresRegister()); | 2061 locs->set_temp(0, Location::RequiresRegister()); |
2064 return locs; | 2062 return locs; |
2065 } | 2063 } |
2066 | 2064 |
2067 | 2065 |
2068 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2066 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2069 const Register value = locs()->in(0).reg(); | 2067 const Register value = locs()->in(0).reg(); |
2070 const Register temp = locs()->temp(0).reg(); | 2068 const Register temp = locs()->temp(0).reg(); |
2071 | 2069 |
2072 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 2070 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
2073 if (this->value()->NeedsStoreBuffer()) { | 2071 if (this->value()->NeedsStoreBuffer()) { |
2074 __ StoreIntoObjectOffset( | 2072 __ StoreIntoObjectOffset(temp, Field::static_value_offset(), value, |
2075 temp, Field::static_value_offset(), value, CanValueBeSmi()); | 2073 CanValueBeSmi()); |
2076 } else { | 2074 } else { |
2077 __ StoreIntoObjectOffsetNoBarrier(temp, | 2075 __ StoreIntoObjectOffsetNoBarrier(temp, Field::static_value_offset(), |
2078 Field::static_value_offset(), | |
2079 value); | 2076 value); |
2080 } | 2077 } |
2081 } | 2078 } |
2082 | 2079 |
2083 | 2080 |
2084 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 2081 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
2085 bool opt) const { | 2082 bool opt) const { |
2086 const intptr_t kNumInputs = 2; | 2083 const intptr_t kNumInputs = 2; |
2087 const intptr_t kNumTemps = 0; | 2084 const intptr_t kNumTemps = 0; |
2088 LocationSummary* summary = new(zone) LocationSummary( | 2085 LocationSummary* summary = new (zone) |
2089 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2086 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2090 summary->set_in(0, Location::RegisterLocation(R0)); | 2087 summary->set_in(0, Location::RegisterLocation(R0)); |
2091 summary->set_in(1, Location::RegisterLocation(R1)); | 2088 summary->set_in(1, Location::RegisterLocation(R1)); |
2092 summary->set_out(0, Location::RegisterLocation(R0)); | 2089 summary->set_out(0, Location::RegisterLocation(R0)); |
2093 return summary; | 2090 return summary; |
2094 } | 2091 } |
2095 | 2092 |
2096 | 2093 |
2097 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2094 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2098 ASSERT(locs()->in(0).reg() == R0); // Value. | 2095 ASSERT(locs()->in(0).reg() == R0); // Value. |
2099 ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments. | 2096 ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments. |
2100 | 2097 |
2101 compiler->GenerateInstanceOf(token_pos(), | 2098 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), negate_result(), |
2102 deopt_id(), | |
2103 type(), | |
2104 negate_result(), | |
2105 locs()); | 2099 locs()); |
2106 ASSERT(locs()->out(0).reg() == R0); | 2100 ASSERT(locs()->out(0).reg() == R0); |
2107 } | 2101 } |
2108 | 2102 |
2109 | 2103 |
2110 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 2104 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
2111 bool opt) const { | 2105 bool opt) const { |
2112 const intptr_t kNumInputs = 2; | 2106 const intptr_t kNumInputs = 2; |
2113 const intptr_t kNumTemps = 0; | 2107 const intptr_t kNumTemps = 0; |
2114 LocationSummary* locs = new(zone) LocationSummary( | 2108 LocationSummary* locs = new (zone) |
2115 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2109 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2116 locs->set_in(kElementTypePos, Location::RegisterLocation(R1)); | 2110 locs->set_in(kElementTypePos, Location::RegisterLocation(R1)); |
2117 locs->set_in(kLengthPos, Location::RegisterLocation(R2)); | 2111 locs->set_in(kLengthPos, Location::RegisterLocation(R2)); |
2118 locs->set_out(0, Location::RegisterLocation(R0)); | 2112 locs->set_out(0, Location::RegisterLocation(R0)); |
2119 return locs; | 2113 return locs; |
2120 } | 2114 } |
2121 | 2115 |
2122 | 2116 |
2123 // Inlines array allocation for known constant values. | 2117 // Inlines array allocation for known constant values. |
2124 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 2118 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
2125 intptr_t num_elements, | 2119 intptr_t num_elements, |
2126 Label* slow_path, | 2120 Label* slow_path, |
2127 Label* done) { | 2121 Label* done) { |
2128 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. | 2122 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. |
2129 const Register kLengthReg = R2; | 2123 const Register kLengthReg = R2; |
2130 const Register kElemTypeReg = R1; | 2124 const Register kElemTypeReg = R1; |
2131 const intptr_t instance_size = Array::InstanceSize(num_elements); | 2125 const intptr_t instance_size = Array::InstanceSize(num_elements); |
2132 | 2126 |
2133 __ TryAllocateArray(kArrayCid, instance_size, slow_path, | 2127 __ TryAllocateArray(kArrayCid, instance_size, slow_path, |
2134 R0, // instance | 2128 R0, // instance |
2135 R3, // end address | 2129 R3, // end address |
2136 R6, | 2130 R6, R8); |
2137 R8); | |
2138 // R0: new object start as a tagged pointer. | 2131 // R0: new object start as a tagged pointer. |
2139 // R3: new object end address. | 2132 // R3: new object end address. |
2140 | 2133 |
2141 // Store the type argument field. | 2134 // Store the type argument field. |
2142 __ StoreIntoObjectNoBarrier(R0, | 2135 __ StoreIntoObjectNoBarrier( |
2143 FieldAddress(R0, Array::type_arguments_offset()), | 2136 R0, FieldAddress(R0, Array::type_arguments_offset()), kElemTypeReg); |
2144 kElemTypeReg); | |
2145 | 2137 |
2146 // Set the length field. | 2138 // Set the length field. |
2147 __ StoreIntoObjectNoBarrier(R0, | 2139 __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, Array::length_offset()), |
2148 FieldAddress(R0, Array::length_offset()), | |
2149 kLengthReg); | 2140 kLengthReg); |
2150 | 2141 |
2151 // TODO(zra): Use stp once added. | 2142 // TODO(zra): Use stp once added. |
2152 // Initialize all array elements to raw_null. | 2143 // Initialize all array elements to raw_null. |
2153 // R0: new object start as a tagged pointer. | 2144 // R0: new object start as a tagged pointer. |
2154 // R3: new object end address. | 2145 // R3: new object end address. |
2155 // R8: iterator which initially points to the start of the variable | 2146 // R8: iterator which initially points to the start of the variable |
2156 // data area to be initialized. | 2147 // data area to be initialized. |
2157 // R6: null | 2148 // R6: null |
2158 if (num_elements > 0) { | 2149 if (num_elements > 0) { |
(...skipping 22 matching lines...) Expand all Loading... |
2181 | 2172 |
2182 | 2173 |
2183 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2174 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2184 const Register kLengthReg = R2; | 2175 const Register kLengthReg = R2; |
2185 const Register kElemTypeReg = R1; | 2176 const Register kElemTypeReg = R1; |
2186 const Register kResultReg = R0; | 2177 const Register kResultReg = R0; |
2187 | 2178 |
2188 ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg); | 2179 ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg); |
2189 ASSERT(locs()->in(kLengthPos).reg() == kLengthReg); | 2180 ASSERT(locs()->in(kLengthPos).reg() == kLengthReg); |
2190 | 2181 |
2191 if (compiler->is_optimizing() && | 2182 if (compiler->is_optimizing() && !FLAG_precompiled_mode && |
2192 !FLAG_precompiled_mode && | |
2193 num_elements()->BindsToConstant() && | 2183 num_elements()->BindsToConstant() && |
2194 num_elements()->BoundConstant().IsSmi()) { | 2184 num_elements()->BoundConstant().IsSmi()) { |
2195 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); | 2185 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); |
2196 if ((length >= 0) && (length <= Array::kMaxElements)) { | 2186 if ((length >= 0) && (length <= Array::kMaxElements)) { |
2197 Label slow_path, done; | 2187 Label slow_path, done; |
2198 InlineArrayAllocation(compiler, length, &slow_path, &done); | 2188 InlineArrayAllocation(compiler, length, &slow_path, &done); |
2199 __ Bind(&slow_path); | 2189 __ Bind(&slow_path); |
2200 __ PushObject(Object::null_object()); // Make room for the result. | 2190 __ PushObject(Object::null_object()); // Make room for the result. |
2201 __ Push(kLengthReg); // length. | 2191 __ Push(kLengthReg); // length. |
2202 __ Push(kElemTypeReg); | 2192 __ Push(kElemTypeReg); |
2203 compiler->GenerateRuntimeCall(token_pos(), | 2193 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2204 deopt_id(), | 2194 kAllocateArrayRuntimeEntry, 2, locs()); |
2205 kAllocateArrayRuntimeEntry, | |
2206 2, | |
2207 locs()); | |
2208 __ Drop(2); | 2195 __ Drop(2); |
2209 __ Pop(kResultReg); | 2196 __ Pop(kResultReg); |
2210 __ Bind(&done); | 2197 __ Bind(&done); |
2211 return; | 2198 return; |
2212 } | 2199 } |
2213 } | 2200 } |
2214 const Code& stub = Code::ZoneHandle(compiler->zone(), | 2201 const Code& stub = Code::ZoneHandle(compiler->zone(), |
2215 StubCode::AllocateArray_entry()->code()); | 2202 StubCode::AllocateArray_entry()->code()); |
2216 compiler->AddStubCallTarget(stub); | 2203 compiler->AddStubCallTarget(stub); |
2217 compiler->GenerateCall(token_pos(), | 2204 compiler->GenerateCall(token_pos(), *StubCode::AllocateArray_entry(), |
2218 *StubCode::AllocateArray_entry(), | 2205 RawPcDescriptors::kOther, locs()); |
2219 RawPcDescriptors::kOther, | |
2220 locs()); | |
2221 ASSERT(locs()->out(0).reg() == kResultReg); | 2206 ASSERT(locs()->out(0).reg() == kResultReg); |
2222 } | 2207 } |
2223 | 2208 |
2224 | 2209 |
2225 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 2210 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |
2226 bool opt) const { | 2211 bool opt) const { |
2227 const intptr_t kNumInputs = 1; | 2212 const intptr_t kNumInputs = 1; |
2228 const intptr_t kNumTemps = | 2213 const intptr_t kNumTemps = |
2229 (IsUnboxedLoad() && opt) ? 1 : | 2214 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 1 : 0); |
2230 ((IsPotentialUnboxedLoad()) ? 1 : 0); | 2215 LocationSummary* locs = new (zone) LocationSummary( |
2231 LocationSummary* locs = new(zone) LocationSummary( | 2216 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) |
2232 zone, kNumInputs, kNumTemps, | 2217 ? LocationSummary::kNoCall |
2233 (opt && !IsPotentialUnboxedLoad()) | 2218 : LocationSummary::kCallOnSlowPath); |
2234 ? LocationSummary::kNoCall | |
2235 : LocationSummary::kCallOnSlowPath); | |
2236 | 2219 |
2237 locs->set_in(0, Location::RequiresRegister()); | 2220 locs->set_in(0, Location::RequiresRegister()); |
2238 | 2221 |
2239 if (IsUnboxedLoad() && opt) { | 2222 if (IsUnboxedLoad() && opt) { |
2240 locs->set_temp(0, Location::RequiresRegister()); | 2223 locs->set_temp(0, Location::RequiresRegister()); |
2241 } else if (IsPotentialUnboxedLoad()) { | 2224 } else if (IsPotentialUnboxedLoad()) { |
2242 locs->set_temp(0, Location::RequiresRegister()); | 2225 locs->set_temp(0, Location::RequiresRegister()); |
2243 } | 2226 } |
2244 locs->set_out(0, Location::RequiresRegister()); | 2227 locs->set_out(0, Location::RequiresRegister()); |
2245 return locs; | 2228 return locs; |
(...skipping 30 matching lines...) Expand all Loading... |
2276 if (IsPotentialUnboxedLoad()) { | 2259 if (IsPotentialUnboxedLoad()) { |
2277 const Register temp = locs()->temp(0).reg(); | 2260 const Register temp = locs()->temp(0).reg(); |
2278 | 2261 |
2279 Label load_pointer; | 2262 Label load_pointer; |
2280 Label load_double; | 2263 Label load_double; |
2281 Label load_float32x4; | 2264 Label load_float32x4; |
2282 Label load_float64x2; | 2265 Label load_float64x2; |
2283 | 2266 |
2284 __ LoadObject(result_reg, Field::ZoneHandle(field()->Original())); | 2267 __ LoadObject(result_reg, Field::ZoneHandle(field()->Original())); |
2285 | 2268 |
2286 FieldAddress field_cid_operand( | 2269 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset(), |
2287 result_reg, Field::guarded_cid_offset(), kUnsignedWord); | 2270 kUnsignedWord); |
2288 FieldAddress field_nullability_operand( | 2271 FieldAddress field_nullability_operand( |
2289 result_reg, Field::is_nullable_offset(), kUnsignedWord); | 2272 result_reg, Field::is_nullable_offset(), kUnsignedWord); |
2290 | 2273 |
2291 __ ldr(temp, field_nullability_operand, kUnsignedWord); | 2274 __ ldr(temp, field_nullability_operand, kUnsignedWord); |
2292 __ CompareImmediate(temp, kNullCid); | 2275 __ CompareImmediate(temp, kNullCid); |
2293 __ b(&load_pointer, EQ); | 2276 __ b(&load_pointer, EQ); |
2294 | 2277 |
2295 __ ldr(temp, field_cid_operand, kUnsignedWord); | 2278 __ ldr(temp, field_cid_operand, kUnsignedWord); |
2296 __ CompareImmediate(temp, kDoubleCid); | 2279 __ CompareImmediate(temp, kDoubleCid); |
2297 __ b(&load_double, EQ); | 2280 __ b(&load_double, EQ); |
2298 | 2281 |
2299 __ ldr(temp, field_cid_operand, kUnsignedWord); | 2282 __ ldr(temp, field_cid_operand, kUnsignedWord); |
2300 __ CompareImmediate(temp, kFloat32x4Cid); | 2283 __ CompareImmediate(temp, kFloat32x4Cid); |
2301 __ b(&load_float32x4, EQ); | 2284 __ b(&load_float32x4, EQ); |
2302 | 2285 |
2303 __ ldr(temp, field_cid_operand, kUnsignedWord); | 2286 __ ldr(temp, field_cid_operand, kUnsignedWord); |
2304 __ CompareImmediate(temp, kFloat64x2Cid); | 2287 __ CompareImmediate(temp, kFloat64x2Cid); |
2305 __ b(&load_float64x2, EQ); | 2288 __ b(&load_float64x2, EQ); |
2306 | 2289 |
2307 // Fall through. | 2290 // Fall through. |
2308 __ b(&load_pointer); | 2291 __ b(&load_pointer); |
2309 | 2292 |
2310 if (!compiler->is_optimizing()) { | 2293 if (!compiler->is_optimizing()) { |
2311 locs()->live_registers()->Add(locs()->in(0)); | 2294 locs()->live_registers()->Add(locs()->in(0)); |
2312 } | 2295 } |
2313 | 2296 |
2314 { | 2297 { |
2315 __ Bind(&load_double); | 2298 __ Bind(&load_double); |
2316 BoxAllocationSlowPath::Allocate(compiler, | 2299 BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(), |
2317 this, | 2300 result_reg, temp); |
2318 compiler->double_class(), | |
2319 result_reg, | |
2320 temp); | |
2321 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); | 2301 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); |
2322 __ LoadDFieldFromOffset(VTMP, temp, Double::value_offset()); | 2302 __ LoadDFieldFromOffset(VTMP, temp, Double::value_offset()); |
2323 __ StoreDFieldToOffset(VTMP, result_reg, Double::value_offset()); | 2303 __ StoreDFieldToOffset(VTMP, result_reg, Double::value_offset()); |
2324 __ b(&done); | 2304 __ b(&done); |
2325 } | 2305 } |
2326 | 2306 |
2327 { | 2307 { |
2328 __ Bind(&load_float32x4); | 2308 __ Bind(&load_float32x4); |
2329 BoxAllocationSlowPath::Allocate(compiler, | 2309 BoxAllocationSlowPath::Allocate( |
2330 this, | 2310 compiler, this, compiler->float32x4_class(), result_reg, temp); |
2331 compiler->float32x4_class(), | |
2332 result_reg, | |
2333 temp); | |
2334 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); | 2311 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); |
2335 __ LoadQFieldFromOffset(VTMP, temp, Float32x4::value_offset()); | 2312 __ LoadQFieldFromOffset(VTMP, temp, Float32x4::value_offset()); |
2336 __ StoreQFieldToOffset(VTMP, result_reg, Float32x4::value_offset()); | 2313 __ StoreQFieldToOffset(VTMP, result_reg, Float32x4::value_offset()); |
2337 __ b(&done); | 2314 __ b(&done); |
2338 } | 2315 } |
2339 | 2316 |
2340 { | 2317 { |
2341 __ Bind(&load_float64x2); | 2318 __ Bind(&load_float64x2); |
2342 BoxAllocationSlowPath::Allocate(compiler, | 2319 BoxAllocationSlowPath::Allocate( |
2343 this, | 2320 compiler, this, compiler->float64x2_class(), result_reg, temp); |
2344 compiler->float64x2_class(), | |
2345 result_reg, | |
2346 temp); | |
2347 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); | 2321 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); |
2348 __ LoadQFieldFromOffset(VTMP, temp, Float64x2::value_offset()); | 2322 __ LoadQFieldFromOffset(VTMP, temp, Float64x2::value_offset()); |
2349 __ StoreQFieldToOffset(VTMP, result_reg, Float64x2::value_offset()); | 2323 __ StoreQFieldToOffset(VTMP, result_reg, Float64x2::value_offset()); |
2350 __ b(&done); | 2324 __ b(&done); |
2351 } | 2325 } |
2352 | 2326 |
2353 __ Bind(&load_pointer); | 2327 __ Bind(&load_pointer); |
2354 } | 2328 } |
2355 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); | 2329 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); |
2356 __ Bind(&done); | 2330 __ Bind(&done); |
2357 } | 2331 } |
2358 | 2332 |
2359 | 2333 |
2360 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2334 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
2361 bool opt) const { | 2335 bool opt) const { |
2362 const intptr_t kNumInputs = 1; | 2336 const intptr_t kNumInputs = 1; |
2363 const intptr_t kNumTemps = 0; | 2337 const intptr_t kNumTemps = 0; |
2364 LocationSummary* locs = new(zone) LocationSummary( | 2338 LocationSummary* locs = new (zone) |
2365 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2339 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2366 locs->set_in(0, Location::RegisterLocation(R0)); | 2340 locs->set_in(0, Location::RegisterLocation(R0)); |
2367 locs->set_out(0, Location::RegisterLocation(R0)); | 2341 locs->set_out(0, Location::RegisterLocation(R0)); |
2368 return locs; | 2342 return locs; |
2369 } | 2343 } |
2370 | 2344 |
2371 | 2345 |
2372 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2346 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2373 const Register instantiator_reg = locs()->in(0).reg(); | 2347 const Register instantiator_reg = locs()->in(0).reg(); |
2374 const Register result_reg = locs()->out(0).reg(); | 2348 const Register result_reg = locs()->out(0).reg(); |
2375 | 2349 |
2376 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2350 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
2377 // A runtime call to instantiate the type is required. | 2351 // A runtime call to instantiate the type is required. |
2378 __ PushObject(Object::null_object()); // Make room for the result. | 2352 __ PushObject(Object::null_object()); // Make room for the result. |
2379 __ PushObject(type()); | 2353 __ PushObject(type()); |
2380 __ Push(instantiator_reg); // Push instantiator type arguments. | 2354 __ Push(instantiator_reg); // Push instantiator type arguments. |
2381 compiler->GenerateRuntimeCall(token_pos(), | 2355 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2382 deopt_id(), | 2356 kInstantiateTypeRuntimeEntry, 2, locs()); |
2383 kInstantiateTypeRuntimeEntry, | 2357 __ Drop(2); // Drop instantiator and uninstantiated type. |
2384 2, | |
2385 locs()); | |
2386 __ Drop(2); // Drop instantiator and uninstantiated type. | |
2387 __ Pop(result_reg); // Pop instantiated type. | 2358 __ Pop(result_reg); // Pop instantiated type. |
2388 ASSERT(instantiator_reg == result_reg); | 2359 ASSERT(instantiator_reg == result_reg); |
2389 } | 2360 } |
2390 | 2361 |
2391 | 2362 |
2392 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2363 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
2393 Zone* zone, bool opt) const { | 2364 Zone* zone, |
| 2365 bool opt) const { |
2394 const intptr_t kNumInputs = 1; | 2366 const intptr_t kNumInputs = 1; |
2395 const intptr_t kNumTemps = 0; | 2367 const intptr_t kNumTemps = 0; |
2396 LocationSummary* locs = new(zone) LocationSummary( | 2368 LocationSummary* locs = new (zone) |
2397 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2369 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2398 locs->set_in(0, Location::RegisterLocation(R0)); | 2370 locs->set_in(0, Location::RegisterLocation(R0)); |
2399 locs->set_out(0, Location::RegisterLocation(R0)); | 2371 locs->set_out(0, Location::RegisterLocation(R0)); |
2400 return locs; | 2372 return locs; |
2401 } | 2373 } |
2402 | 2374 |
2403 | 2375 |
2404 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2376 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
2405 FlowGraphCompiler* compiler) { | 2377 FlowGraphCompiler* compiler) { |
2406 const Register instantiator_reg = locs()->in(0).reg(); | 2378 const Register instantiator_reg = locs()->in(0).reg(); |
2407 const Register result_reg = locs()->out(0).reg(); | 2379 const Register result_reg = locs()->out(0).reg(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2439 __ Bind(&found); | 2411 __ Bind(&found); |
2440 __ LoadFromOffset(R0, R2, 1 * kWordSize); // Cached instantiated args. | 2412 __ LoadFromOffset(R0, R2, 1 * kWordSize); // Cached instantiated args. |
2441 __ b(&type_arguments_instantiated); | 2413 __ b(&type_arguments_instantiated); |
2442 | 2414 |
2443 __ Bind(&slow_case); | 2415 __ Bind(&slow_case); |
2444 // Instantiate non-null type arguments. | 2416 // Instantiate non-null type arguments. |
2445 // A runtime call to instantiate the type arguments is required. | 2417 // A runtime call to instantiate the type arguments is required. |
2446 __ PushObject(Object::null_object()); // Make room for the result. | 2418 __ PushObject(Object::null_object()); // Make room for the result. |
2447 __ PushObject(type_arguments()); | 2419 __ PushObject(type_arguments()); |
2448 __ Push(instantiator_reg); // Push instantiator type arguments. | 2420 __ Push(instantiator_reg); // Push instantiator type arguments. |
2449 compiler->GenerateRuntimeCall(token_pos(), | 2421 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2450 deopt_id(), | 2422 kInstantiateTypeArgumentsRuntimeEntry, 2, |
2451 kInstantiateTypeArgumentsRuntimeEntry, | |
2452 2, | |
2453 locs()); | 2423 locs()); |
2454 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 2424 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
2455 __ Pop(result_reg); // Pop instantiated type arguments. | 2425 __ Pop(result_reg); // Pop instantiated type arguments. |
2456 __ Bind(&type_arguments_instantiated); | 2426 __ Bind(&type_arguments_instantiated); |
2457 } | 2427 } |
2458 | 2428 |
2459 | 2429 |
2460 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2430 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
2461 Zone* zone, | 2431 Zone* zone, |
2462 bool opt) const { | 2432 bool opt) const { |
2463 ASSERT(opt); | 2433 ASSERT(opt); |
2464 const intptr_t kNumInputs = 0; | 2434 const intptr_t kNumInputs = 0; |
2465 const intptr_t kNumTemps = 3; | 2435 const intptr_t kNumTemps = 3; |
2466 LocationSummary* locs = new(zone) LocationSummary( | 2436 LocationSummary* locs = new (zone) LocationSummary( |
2467 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2437 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2468 locs->set_temp(0, Location::RegisterLocation(R1)); | 2438 locs->set_temp(0, Location::RegisterLocation(R1)); |
2469 locs->set_temp(1, Location::RegisterLocation(R2)); | 2439 locs->set_temp(1, Location::RegisterLocation(R2)); |
2470 locs->set_temp(2, Location::RegisterLocation(R3)); | 2440 locs->set_temp(2, Location::RegisterLocation(R3)); |
2471 locs->set_out(0, Location::RegisterLocation(R0)); | 2441 locs->set_out(0, Location::RegisterLocation(R0)); |
2472 return locs; | 2442 return locs; |
2473 } | 2443 } |
2474 | 2444 |
2475 | 2445 |
2476 class AllocateContextSlowPath : public SlowPathCode { | 2446 class AllocateContextSlowPath : public SlowPathCode { |
2477 public: | 2447 public: |
2478 explicit AllocateContextSlowPath( | 2448 explicit AllocateContextSlowPath( |
2479 AllocateUninitializedContextInstr* instruction) | 2449 AllocateUninitializedContextInstr* instruction) |
2480 : instruction_(instruction) { } | 2450 : instruction_(instruction) {} |
2481 | 2451 |
2482 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2452 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2483 __ Comment("AllocateContextSlowPath"); | 2453 __ Comment("AllocateContextSlowPath"); |
2484 __ Bind(entry_label()); | 2454 __ Bind(entry_label()); |
2485 | 2455 |
2486 LocationSummary* locs = instruction_->locs(); | 2456 LocationSummary* locs = instruction_->locs(); |
2487 locs->live_registers()->Remove(locs->out(0)); | 2457 locs->live_registers()->Remove(locs->out(0)); |
2488 | 2458 |
2489 compiler->SaveLiveRegisters(locs); | 2459 compiler->SaveLiveRegisters(locs); |
2490 | 2460 |
2491 __ LoadImmediate(R1, instruction_->num_context_variables()); | 2461 __ LoadImmediate(R1, instruction_->num_context_variables()); |
2492 const Code& stub = Code::ZoneHandle( | 2462 const Code& stub = Code::ZoneHandle( |
2493 compiler->zone(), StubCode::AllocateContext_entry()->code()); | 2463 compiler->zone(), StubCode::AllocateContext_entry()->code()); |
2494 compiler->AddStubCallTarget(stub); | 2464 compiler->AddStubCallTarget(stub); |
2495 compiler->GenerateCall(instruction_->token_pos(), | 2465 compiler->GenerateCall(instruction_->token_pos(), |
2496 *StubCode::AllocateContext_entry(), | 2466 *StubCode::AllocateContext_entry(), |
2497 RawPcDescriptors::kOther, | 2467 RawPcDescriptors::kOther, locs); |
2498 locs); | |
2499 ASSERT(instruction_->locs()->out(0).reg() == R0); | 2468 ASSERT(instruction_->locs()->out(0).reg() == R0); |
2500 compiler->RestoreLiveRegisters(instruction_->locs()); | 2469 compiler->RestoreLiveRegisters(instruction_->locs()); |
2501 __ b(exit_label()); | 2470 __ b(exit_label()); |
2502 } | 2471 } |
2503 | 2472 |
2504 private: | 2473 private: |
2505 AllocateUninitializedContextInstr* instruction_; | 2474 AllocateUninitializedContextInstr* instruction_; |
2506 }; | 2475 }; |
2507 | 2476 |
2508 | 2477 |
2509 | |
2510 void AllocateUninitializedContextInstr::EmitNativeCode( | 2478 void AllocateUninitializedContextInstr::EmitNativeCode( |
2511 FlowGraphCompiler* compiler) { | 2479 FlowGraphCompiler* compiler) { |
2512 Register temp0 = locs()->temp(0).reg(); | 2480 Register temp0 = locs()->temp(0).reg(); |
2513 Register temp1 = locs()->temp(1).reg(); | 2481 Register temp1 = locs()->temp(1).reg(); |
2514 Register temp2 = locs()->temp(2).reg(); | 2482 Register temp2 = locs()->temp(2).reg(); |
2515 Register result = locs()->out(0).reg(); | 2483 Register result = locs()->out(0).reg(); |
2516 // Try allocate the object. | 2484 // Try allocate the object. |
2517 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2485 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
2518 compiler->AddSlowPathCode(slow_path); | 2486 compiler->AddSlowPathCode(slow_path); |
2519 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2487 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
2520 | 2488 |
2521 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 2489 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
2522 result, // instance | 2490 result, // instance |
2523 temp0, | 2491 temp0, temp1, temp2); |
2524 temp1, | |
2525 temp2); | |
2526 | 2492 |
2527 // Setup up number of context variables field. | 2493 // Setup up number of context variables field. |
2528 __ LoadImmediate(temp0, num_context_variables()); | 2494 __ LoadImmediate(temp0, num_context_variables()); |
2529 __ str(temp0, FieldAddress(result, Context::num_variables_offset())); | 2495 __ str(temp0, FieldAddress(result, Context::num_variables_offset())); |
2530 | 2496 |
2531 __ Bind(slow_path->exit_label()); | 2497 __ Bind(slow_path->exit_label()); |
2532 } | 2498 } |
2533 | 2499 |
2534 | 2500 |
2535 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 2501 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |
2536 bool opt) const { | 2502 bool opt) const { |
2537 const intptr_t kNumInputs = 0; | 2503 const intptr_t kNumInputs = 0; |
2538 const intptr_t kNumTemps = 1; | 2504 const intptr_t kNumTemps = 1; |
2539 LocationSummary* locs = new(zone) LocationSummary( | 2505 LocationSummary* locs = new (zone) |
2540 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2506 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2541 locs->set_temp(0, Location::RegisterLocation(R1)); | 2507 locs->set_temp(0, Location::RegisterLocation(R1)); |
2542 locs->set_out(0, Location::RegisterLocation(R0)); | 2508 locs->set_out(0, Location::RegisterLocation(R0)); |
2543 return locs; | 2509 return locs; |
2544 } | 2510 } |
2545 | 2511 |
2546 | 2512 |
2547 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2513 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2548 ASSERT(locs()->temp(0).reg() == R1); | 2514 ASSERT(locs()->temp(0).reg() == R1); |
2549 ASSERT(locs()->out(0).reg() == R0); | 2515 ASSERT(locs()->out(0).reg() == R0); |
2550 | 2516 |
2551 __ LoadImmediate(R1, num_context_variables()); | 2517 __ LoadImmediate(R1, num_context_variables()); |
2552 compiler->GenerateCall(token_pos(), | 2518 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), |
2553 *StubCode::AllocateContext_entry(), | 2519 RawPcDescriptors::kOther, locs()); |
2554 RawPcDescriptors::kOther, | |
2555 locs()); | |
2556 } | 2520 } |
2557 | 2521 |
2558 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2522 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
2559 bool opt) const { | 2523 bool opt) const { |
2560 const intptr_t kNumInputs = 1; | 2524 const intptr_t kNumInputs = 1; |
2561 const intptr_t kNumTemps = 1; | 2525 const intptr_t kNumTemps = 1; |
2562 LocationSummary* locs = new(zone) LocationSummary( | 2526 LocationSummary* locs = new (zone) |
2563 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2527 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2564 locs->set_in(0, Location::RegisterLocation(R0)); | 2528 locs->set_in(0, Location::RegisterLocation(R0)); |
2565 locs->set_temp(0, Location::RegisterLocation(R1)); | 2529 locs->set_temp(0, Location::RegisterLocation(R1)); |
2566 return locs; | 2530 return locs; |
2567 } | 2531 } |
2568 | 2532 |
2569 | 2533 |
2570 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2534 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2571 Register field = locs()->in(0).reg(); | 2535 Register field = locs()->in(0).reg(); |
2572 Register temp = locs()->temp(0).reg(); | 2536 Register temp = locs()->temp(0).reg(); |
2573 Label call_runtime, no_call; | 2537 Label call_runtime, no_call; |
2574 | 2538 |
2575 __ ldr(temp, FieldAddress(field, Field::static_value_offset())); | 2539 __ ldr(temp, FieldAddress(field, Field::static_value_offset())); |
2576 __ CompareObject(temp, Object::sentinel()); | 2540 __ CompareObject(temp, Object::sentinel()); |
2577 __ b(&call_runtime, EQ); | 2541 __ b(&call_runtime, EQ); |
2578 | 2542 |
2579 __ CompareObject(temp, Object::transition_sentinel()); | 2543 __ CompareObject(temp, Object::transition_sentinel()); |
2580 __ b(&no_call, NE); | 2544 __ b(&no_call, NE); |
2581 | 2545 |
2582 __ Bind(&call_runtime); | 2546 __ Bind(&call_runtime); |
2583 __ PushObject(Object::null_object()); // Make room for (unused) result. | 2547 __ PushObject(Object::null_object()); // Make room for (unused) result. |
2584 __ Push(field); | 2548 __ Push(field); |
2585 compiler->GenerateRuntimeCall(token_pos(), | 2549 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2586 deopt_id(), | 2550 kInitStaticFieldRuntimeEntry, 1, locs()); |
2587 kInitStaticFieldRuntimeEntry, | |
2588 1, | |
2589 locs()); | |
2590 __ Drop(2); // Remove argument and result placeholder. | 2551 __ Drop(2); // Remove argument and result placeholder. |
2591 __ Bind(&no_call); | 2552 __ Bind(&no_call); |
2592 } | 2553 } |
2593 | 2554 |
2594 | 2555 |
2595 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2556 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
2596 bool opt) const { | 2557 bool opt) const { |
2597 const intptr_t kNumInputs = 1; | 2558 const intptr_t kNumInputs = 1; |
2598 const intptr_t kNumTemps = 0; | 2559 const intptr_t kNumTemps = 0; |
2599 LocationSummary* locs = new(zone) LocationSummary( | 2560 LocationSummary* locs = new (zone) |
2600 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2561 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2601 locs->set_in(0, Location::RegisterLocation(R0)); | 2562 locs->set_in(0, Location::RegisterLocation(R0)); |
2602 locs->set_out(0, Location::RegisterLocation(R0)); | 2563 locs->set_out(0, Location::RegisterLocation(R0)); |
2603 return locs; | 2564 return locs; |
2604 } | 2565 } |
2605 | 2566 |
2606 | 2567 |
2607 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2568 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2608 const Register context_value = locs()->in(0).reg(); | 2569 const Register context_value = locs()->in(0).reg(); |
2609 const Register result = locs()->out(0).reg(); | 2570 const Register result = locs()->out(0).reg(); |
2610 | 2571 |
2611 __ PushObject(Object::null_object()); // Make room for the result. | 2572 __ PushObject(Object::null_object()); // Make room for the result. |
2612 __ Push(context_value); | 2573 __ Push(context_value); |
2613 compiler->GenerateRuntimeCall(token_pos(), | 2574 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2614 deopt_id(), | 2575 kCloneContextRuntimeEntry, 1, locs()); |
2615 kCloneContextRuntimeEntry, | 2576 __ Drop(1); // Remove argument. |
2616 1, | |
2617 locs()); | |
2618 __ Drop(1); // Remove argument. | |
2619 __ Pop(result); // Get result (cloned context). | 2577 __ Pop(result); // Get result (cloned context). |
2620 } | 2578 } |
2621 | 2579 |
2622 | 2580 |
2623 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2581 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
2624 bool opt) const { | 2582 bool opt) const { |
2625 UNREACHABLE(); | 2583 UNREACHABLE(); |
2626 return NULL; | 2584 return NULL; |
2627 } | 2585 } |
2628 | 2586 |
2629 | 2587 |
2630 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2588 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2631 __ Bind(compiler->GetJumpLabel(this)); | 2589 __ Bind(compiler->GetJumpLabel(this)); |
2632 compiler->AddExceptionHandler(catch_try_index(), | 2590 compiler->AddExceptionHandler(catch_try_index(), try_index(), |
2633 try_index(), | |
2634 compiler->assembler()->CodeSize(), | 2591 compiler->assembler()->CodeSize(), |
2635 catch_handler_types_, | 2592 catch_handler_types_, needs_stacktrace()); |
2636 needs_stacktrace()); | |
2637 // On lazy deoptimization we patch the optimized code here to enter the | 2593 // On lazy deoptimization we patch the optimized code here to enter the |
2638 // deoptimization stub. | 2594 // deoptimization stub. |
2639 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 2595 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |
2640 if (compiler->is_optimizing()) { | 2596 if (compiler->is_optimizing()) { |
2641 compiler->AddDeoptIndexAtCall(deopt_id); | 2597 compiler->AddDeoptIndexAtCall(deopt_id); |
2642 } else { | 2598 } else { |
2643 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 2599 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id, |
2644 deopt_id, | |
2645 TokenPosition::kNoSource); | 2600 TokenPosition::kNoSource); |
2646 } | 2601 } |
2647 if (HasParallelMove()) { | 2602 if (HasParallelMove()) { |
2648 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2603 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
2649 } | 2604 } |
2650 | 2605 |
2651 // Restore SP from FP as we are coming from a throw and the code for | 2606 // Restore SP from FP as we are coming from a throw and the code for |
2652 // popping arguments has not been run. | 2607 // popping arguments has not been run. |
2653 const intptr_t fp_sp_dist = | 2608 const intptr_t fp_sp_dist = |
2654 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 2609 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
2655 ASSERT(fp_sp_dist <= 0); | 2610 ASSERT(fp_sp_dist <= 0); |
2656 __ AddImmediate(SP, FP, fp_sp_dist); | 2611 __ AddImmediate(SP, FP, fp_sp_dist); |
2657 | 2612 |
2658 // Restore stack and initialize the two exception variables: | 2613 // Restore stack and initialize the two exception variables: |
2659 // exception and stack trace variables. | 2614 // exception and stack trace variables. |
2660 __ StoreToOffset(kExceptionObjectReg, | 2615 __ StoreToOffset(kExceptionObjectReg, FP, |
2661 FP, exception_var().index() * kWordSize); | 2616 exception_var().index() * kWordSize); |
2662 __ StoreToOffset(kStackTraceObjectReg, | 2617 __ StoreToOffset(kStackTraceObjectReg, FP, |
2663 FP, stacktrace_var().index() * kWordSize); | 2618 stacktrace_var().index() * kWordSize); |
2664 } | 2619 } |
2665 | 2620 |
2666 | 2621 |
2667 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 2622 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |
2668 bool opt) const { | 2623 bool opt) const { |
2669 const intptr_t kNumInputs = 0; | 2624 const intptr_t kNumInputs = 0; |
2670 const intptr_t kNumTemps = 1; | 2625 const intptr_t kNumTemps = 1; |
2671 LocationSummary* summary = new(zone) LocationSummary( | 2626 LocationSummary* summary = new (zone) LocationSummary( |
2672 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2627 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2673 summary->set_temp(0, Location::RequiresRegister()); | 2628 summary->set_temp(0, Location::RequiresRegister()); |
2674 return summary; | 2629 return summary; |
2675 } | 2630 } |
2676 | 2631 |
2677 | 2632 |
2678 class CheckStackOverflowSlowPath : public SlowPathCode { | 2633 class CheckStackOverflowSlowPath : public SlowPathCode { |
2679 public: | 2634 public: |
2680 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2635 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
2681 : instruction_(instruction) { } | 2636 : instruction_(instruction) {} |
2682 | 2637 |
2683 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2638 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2684 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { | 2639 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { |
2685 const Register value = instruction_->locs()->temp(0).reg(); | 2640 const Register value = instruction_->locs()->temp(0).reg(); |
2686 __ Comment("CheckStackOverflowSlowPathOsr"); | 2641 __ Comment("CheckStackOverflowSlowPathOsr"); |
2687 __ Bind(osr_entry_label()); | 2642 __ Bind(osr_entry_label()); |
2688 __ LoadImmediate(value, Thread::kOsrRequest); | 2643 __ LoadImmediate(value, Thread::kOsrRequest); |
2689 __ str(value, Address(THR, Thread::stack_overflow_flags_offset())); | 2644 __ str(value, Address(THR, Thread::stack_overflow_flags_offset())); |
2690 } | 2645 } |
2691 __ Comment("CheckStackOverflowSlowPath"); | 2646 __ Comment("CheckStackOverflowSlowPath"); |
2692 __ Bind(entry_label()); | 2647 __ Bind(entry_label()); |
2693 compiler->SaveLiveRegisters(instruction_->locs()); | 2648 compiler->SaveLiveRegisters(instruction_->locs()); |
2694 // pending_deoptimization_env_ is needed to generate a runtime call that | 2649 // pending_deoptimization_env_ is needed to generate a runtime call that |
2695 // may throw an exception. | 2650 // may throw an exception. |
2696 ASSERT(compiler->pending_deoptimization_env_ == NULL); | 2651 ASSERT(compiler->pending_deoptimization_env_ == NULL); |
2697 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); | 2652 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |
2698 compiler->pending_deoptimization_env_ = env; | 2653 compiler->pending_deoptimization_env_ = env; |
2699 compiler->GenerateRuntimeCall(instruction_->token_pos(), | 2654 compiler->GenerateRuntimeCall( |
2700 instruction_->deopt_id(), | 2655 instruction_->token_pos(), instruction_->deopt_id(), |
2701 kStackOverflowRuntimeEntry, | 2656 kStackOverflowRuntimeEntry, 0, instruction_->locs()); |
2702 0, | |
2703 instruction_->locs()); | |
2704 | 2657 |
2705 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { | 2658 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { |
2706 // In unoptimized code, record loop stack checks as possible OSR entries. | 2659 // In unoptimized code, record loop stack checks as possible OSR entries. |
2707 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, | 2660 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, |
2708 instruction_->deopt_id(), | 2661 instruction_->deopt_id(), |
2709 TokenPosition::kNoSource); | 2662 TokenPosition::kNoSource); |
2710 } | 2663 } |
2711 compiler->pending_deoptimization_env_ = NULL; | 2664 compiler->pending_deoptimization_env_ = NULL; |
2712 compiler->RestoreLiveRegisters(instruction_->locs()); | 2665 compiler->RestoreLiveRegisters(instruction_->locs()); |
2713 __ b(exit_label()); | 2666 __ b(exit_label()); |
(...skipping 20 matching lines...) Expand all Loading... |
2734 __ CompareRegisters(CSP, TMP); | 2687 __ CompareRegisters(CSP, TMP); |
2735 __ b(slow_path->entry_label(), LS); | 2688 __ b(slow_path->entry_label(), LS); |
2736 if (compiler->CanOSRFunction() && in_loop()) { | 2689 if (compiler->CanOSRFunction() && in_loop()) { |
2737 const Register temp = locs()->temp(0).reg(); | 2690 const Register temp = locs()->temp(0).reg(); |
2738 // In unoptimized code check the usage counter to trigger OSR at loop | 2691 // In unoptimized code check the usage counter to trigger OSR at loop |
2739 // stack checks. Use progressively higher thresholds for more deeply | 2692 // stack checks. Use progressively higher thresholds for more deeply |
2740 // nested loops to attempt to hit outer loops with OSR when possible. | 2693 // nested loops to attempt to hit outer loops with OSR when possible. |
2741 __ LoadObject(temp, compiler->parsed_function().function()); | 2694 __ LoadObject(temp, compiler->parsed_function().function()); |
2742 intptr_t threshold = | 2695 intptr_t threshold = |
2743 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2696 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
2744 __ LoadFieldFromOffset( | 2697 __ LoadFieldFromOffset(temp, temp, Function::usage_counter_offset(), kWord); |
2745 temp, temp, Function::usage_counter_offset(), kWord); | |
2746 __ CompareImmediate(temp, threshold); | 2698 __ CompareImmediate(temp, threshold); |
2747 __ b(slow_path->osr_entry_label(), GE); | 2699 __ b(slow_path->osr_entry_label(), GE); |
2748 } | 2700 } |
2749 if (compiler->ForceSlowPathForStackOverflow()) { | 2701 if (compiler->ForceSlowPathForStackOverflow()) { |
2750 __ b(slow_path->entry_label()); | 2702 __ b(slow_path->entry_label()); |
2751 } | 2703 } |
2752 __ Bind(slow_path->exit_label()); | 2704 __ Bind(slow_path->exit_label()); |
2753 } | 2705 } |
2754 | 2706 |
2755 | 2707 |
2756 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2708 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
2757 BinarySmiOpInstr* shift_left) { | 2709 BinarySmiOpInstr* shift_left) { |
2758 const LocationSummary& locs = *shift_left->locs(); | 2710 const LocationSummary& locs = *shift_left->locs(); |
2759 const Register left = locs.in(0).reg(); | 2711 const Register left = locs.in(0).reg(); |
2760 const Register result = locs.out(0).reg(); | 2712 const Register result = locs.out(0).reg(); |
2761 Label* deopt = shift_left->CanDeoptimize() ? | 2713 Label* deopt = shift_left->CanDeoptimize() |
2762 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | 2714 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
2763 : NULL; | 2715 ICData::kDeoptBinarySmiOp) |
| 2716 : NULL; |
2764 if (locs.in(1).IsConstant()) { | 2717 if (locs.in(1).IsConstant()) { |
2765 const Object& constant = locs.in(1).constant(); | 2718 const Object& constant = locs.in(1).constant(); |
2766 ASSERT(constant.IsSmi()); | 2719 ASSERT(constant.IsSmi()); |
2767 // Immediate shift operation takes 6 bits for the count. | 2720 // Immediate shift operation takes 6 bits for the count. |
2768 const intptr_t kCountLimit = 0x3F; | 2721 const intptr_t kCountLimit = 0x3F; |
2769 const intptr_t value = Smi::Cast(constant).Value(); | 2722 const intptr_t value = Smi::Cast(constant).Value(); |
2770 ASSERT((0 < value) && (value < kCountLimit)); | 2723 ASSERT((0 < value) && (value < kCountLimit)); |
2771 if (shift_left->can_overflow()) { | 2724 if (shift_left->can_overflow()) { |
2772 // Check for overflow (preserve left). | 2725 // Check for overflow (preserve left). |
2773 __ LslImmediate(TMP, left, value); | 2726 __ LslImmediate(TMP, left, value); |
(...skipping 18 matching lines...) Expand all Loading... |
2792 __ CompareRegisters(right, ZR); | 2745 __ CompareRegisters(right, ZR); |
2793 __ b(deopt, MI); | 2746 __ b(deopt, MI); |
2794 __ mov(result, ZR); | 2747 __ mov(result, ZR); |
2795 return; | 2748 return; |
2796 } | 2749 } |
2797 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); | 2750 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); |
2798 const bool right_needs_check = | 2751 const bool right_needs_check = |
2799 !RangeUtils::IsWithin(right_range, 0, max_right - 1); | 2752 !RangeUtils::IsWithin(right_range, 0, max_right - 1); |
2800 if (right_needs_check) { | 2753 if (right_needs_check) { |
2801 __ CompareImmediate(right, | 2754 __ CompareImmediate(right, |
2802 reinterpret_cast<int64_t>(Smi::New(max_right))); | 2755 reinterpret_cast<int64_t>(Smi::New(max_right))); |
2803 __ b(deopt, CS); | 2756 __ b(deopt, CS); |
2804 } | 2757 } |
2805 __ SmiUntag(TMP, right); | 2758 __ SmiUntag(TMP, right); |
2806 __ lslv(result, left, TMP); | 2759 __ lslv(result, left, TMP); |
2807 } | 2760 } |
2808 return; | 2761 return; |
2809 } | 2762 } |
2810 | 2763 |
2811 const bool right_needs_check = | 2764 const bool right_needs_check = |
2812 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); | 2765 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); |
2813 if (!shift_left->can_overflow()) { | 2766 if (!shift_left->can_overflow()) { |
2814 if (right_needs_check) { | 2767 if (right_needs_check) { |
2815 const bool right_may_be_negative = | 2768 const bool right_may_be_negative = |
2816 (right_range == NULL) || !right_range->IsPositive(); | 2769 (right_range == NULL) || !right_range->IsPositive(); |
2817 if (right_may_be_negative) { | 2770 if (right_may_be_negative) { |
2818 ASSERT(shift_left->CanDeoptimize()); | 2771 ASSERT(shift_left->CanDeoptimize()); |
2819 __ CompareRegisters(right, ZR); | 2772 __ CompareRegisters(right, ZR); |
2820 __ b(deopt, MI); | 2773 __ b(deopt, MI); |
2821 } | 2774 } |
2822 | 2775 |
2823 __ CompareImmediate( | 2776 __ CompareImmediate(right, |
2824 right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits))); | 2777 reinterpret_cast<int64_t>(Smi::New(Smi::kBits))); |
2825 __ csel(result, ZR, result, CS); | 2778 __ csel(result, ZR, result, CS); |
2826 __ SmiUntag(TMP, right); | 2779 __ SmiUntag(TMP, right); |
2827 __ lslv(TMP, left, TMP); | 2780 __ lslv(TMP, left, TMP); |
2828 __ csel(result, TMP, result, CC); | 2781 __ csel(result, TMP, result, CC); |
2829 } else { | 2782 } else { |
2830 __ SmiUntag(TMP, right); | 2783 __ SmiUntag(TMP, right); |
2831 __ lslv(result, left, TMP); | 2784 __ lslv(result, left, TMP); |
2832 } | 2785 } |
2833 } else { | 2786 } else { |
2834 if (right_needs_check) { | 2787 if (right_needs_check) { |
2835 ASSERT(shift_left->CanDeoptimize()); | 2788 ASSERT(shift_left->CanDeoptimize()); |
2836 __ CompareImmediate( | 2789 __ CompareImmediate(right, |
2837 right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits))); | 2790 reinterpret_cast<int64_t>(Smi::New(Smi::kBits))); |
2838 __ b(deopt, CS); | 2791 __ b(deopt, CS); |
2839 } | 2792 } |
2840 // Left is not a constant. | 2793 // Left is not a constant. |
2841 // Check if count too large for handling it inlined. | 2794 // Check if count too large for handling it inlined. |
2842 __ SmiUntag(TMP, right); | 2795 __ SmiUntag(TMP, right); |
2843 // Overflow test (preserve left, right, and TMP); | 2796 // Overflow test (preserve left, right, and TMP); |
2844 const Register temp = locs.temp(0).reg(); | 2797 const Register temp = locs.temp(0).reg(); |
2845 __ lslv(temp, left, TMP); | 2798 __ lslv(temp, left, TMP); |
2846 __ asrv(TMP2, temp, TMP); | 2799 __ asrv(TMP2, temp, TMP); |
2847 __ CompareRegisters(left, TMP2); | 2800 __ CompareRegisters(left, TMP2); |
2848 __ b(deopt, NE); // Overflow. | 2801 __ b(deopt, NE); // Overflow. |
2849 // Shift for result now we know there is no overflow. | 2802 // Shift for result now we know there is no overflow. |
2850 __ lslv(result, left, TMP); | 2803 __ lslv(result, left, TMP); |
2851 } | 2804 } |
2852 } | 2805 } |
2853 | 2806 |
2854 | 2807 |
2855 class CheckedSmiSlowPath : public SlowPathCode { | 2808 class CheckedSmiSlowPath : public SlowPathCode { |
2856 public: | 2809 public: |
2857 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) | 2810 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) |
2858 : instruction_(instruction), try_index_(try_index) { } | 2811 : instruction_(instruction), try_index_(try_index) {} |
2859 | 2812 |
2860 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2813 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2861 if (Assembler::EmittingComments()) { | 2814 if (Assembler::EmittingComments()) { |
2862 __ Comment("slow path smi operation"); | 2815 __ Comment("slow path smi operation"); |
2863 } | 2816 } |
2864 __ Bind(entry_label()); | 2817 __ Bind(entry_label()); |
2865 LocationSummary* locs = instruction_->locs(); | 2818 LocationSummary* locs = instruction_->locs(); |
2866 Register result = locs->out(0).reg(); | 2819 Register result = locs->out(0).reg(); |
2867 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 2820 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
2868 | 2821 |
2869 compiler->SaveLiveRegisters(locs); | 2822 compiler->SaveLiveRegisters(locs); |
2870 __ Push(locs->in(0).reg()); | 2823 __ Push(locs->in(0).reg()); |
2871 __ Push(locs->in(1).reg()); | 2824 __ Push(locs->in(1).reg()); |
2872 compiler->EmitMegamorphicInstanceCall( | 2825 compiler->EmitMegamorphicInstanceCall( |
2873 *instruction_->call()->ic_data(), | 2826 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
2874 instruction_->call()->ArgumentCount(), | 2827 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
2875 instruction_->call()->deopt_id(), | 2828 locs, try_index_, |
2876 instruction_->call()->token_pos(), | |
2877 locs, | |
2878 try_index_, | |
2879 /* slow_path_argument_count = */ 2); | 2829 /* slow_path_argument_count = */ 2); |
2880 __ mov(result, R0); | 2830 __ mov(result, R0); |
2881 compiler->RestoreLiveRegisters(locs); | 2831 compiler->RestoreLiveRegisters(locs); |
2882 __ b(exit_label()); | 2832 __ b(exit_label()); |
2883 } | 2833 } |
2884 | 2834 |
2885 private: | 2835 private: |
2886 CheckedSmiOpInstr* instruction_; | 2836 CheckedSmiOpInstr* instruction_; |
2887 intptr_t try_index_; | 2837 intptr_t try_index_; |
2888 }; | 2838 }; |
2889 | 2839 |
2890 | 2840 |
2891 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 2841 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
2892 bool opt) const { | 2842 bool opt) const { |
2893 const intptr_t kNumInputs = 2; | 2843 const intptr_t kNumInputs = 2; |
2894 const intptr_t kNumTemps = 0; | 2844 const intptr_t kNumTemps = 0; |
2895 LocationSummary* summary = new(zone) LocationSummary( | 2845 LocationSummary* summary = new (zone) LocationSummary( |
2896 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2846 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2897 summary->set_in(0, Location::RequiresRegister()); | 2847 summary->set_in(0, Location::RequiresRegister()); |
2898 summary->set_in(1, Location::RequiresRegister()); | 2848 summary->set_in(1, Location::RequiresRegister()); |
2899 summary->set_out(0, Location::RequiresRegister()); | 2849 summary->set_out(0, Location::RequiresRegister()); |
2900 return summary; | 2850 return summary; |
2901 } | 2851 } |
2902 | 2852 |
2903 | 2853 |
2904 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2854 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2905 CheckedSmiSlowPath* slow_path = | 2855 CheckedSmiSlowPath* slow_path = |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2963 | 2913 |
2964 class CheckedSmiComparisonSlowPath : public SlowPathCode { | 2914 class CheckedSmiComparisonSlowPath : public SlowPathCode { |
2965 public: | 2915 public: |
2966 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, | 2916 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, |
2967 intptr_t try_index, | 2917 intptr_t try_index, |
2968 BranchLabels labels, | 2918 BranchLabels labels, |
2969 bool merged) | 2919 bool merged) |
2970 : instruction_(instruction), | 2920 : instruction_(instruction), |
2971 try_index_(try_index), | 2921 try_index_(try_index), |
2972 labels_(labels), | 2922 labels_(labels), |
2973 merged_(merged) { } | 2923 merged_(merged) {} |
2974 | 2924 |
2975 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2925 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2976 if (Assembler::EmittingComments()) { | 2926 if (Assembler::EmittingComments()) { |
2977 __ Comment("slow path smi operation"); | 2927 __ Comment("slow path smi operation"); |
2978 } | 2928 } |
2979 __ Bind(entry_label()); | 2929 __ Bind(entry_label()); |
2980 LocationSummary* locs = instruction_->locs(); | 2930 LocationSummary* locs = instruction_->locs(); |
2981 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); | 2931 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); |
2982 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 2932 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
2983 | 2933 |
2984 compiler->SaveLiveRegisters(locs); | 2934 compiler->SaveLiveRegisters(locs); |
2985 __ Push(locs->in(0).reg()); | 2935 __ Push(locs->in(0).reg()); |
2986 __ Push(locs->in(1).reg()); | 2936 __ Push(locs->in(1).reg()); |
2987 compiler->EmitMegamorphicInstanceCall( | 2937 compiler->EmitMegamorphicInstanceCall( |
2988 *instruction_->call()->ic_data(), | 2938 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
2989 instruction_->call()->ArgumentCount(), | 2939 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
2990 instruction_->call()->deopt_id(), | 2940 locs, try_index_, |
2991 instruction_->call()->token_pos(), | |
2992 locs, | |
2993 try_index_, | |
2994 /* slow_path_argument_count = */ 2); | 2941 /* slow_path_argument_count = */ 2); |
2995 __ mov(result, R0); | 2942 __ mov(result, R0); |
2996 compiler->RestoreLiveRegisters(locs); | 2943 compiler->RestoreLiveRegisters(locs); |
2997 if (merged_) { | 2944 if (merged_) { |
2998 __ CompareObject(result, Bool::True()); | 2945 __ CompareObject(result, Bool::True()); |
2999 __ b(instruction_->is_negated() | 2946 __ b( |
3000 ? labels_.false_label : labels_.true_label, EQ); | 2947 instruction_->is_negated() ? labels_.false_label : labels_.true_label, |
3001 __ b(instruction_->is_negated() | 2948 EQ); |
3002 ? labels_.true_label : labels_.false_label); | 2949 __ b(instruction_->is_negated() ? labels_.true_label |
| 2950 : labels_.false_label); |
3003 } else { | 2951 } else { |
3004 __ b(exit_label()); | 2952 __ b(exit_label()); |
3005 } | 2953 } |
3006 } | 2954 } |
3007 | 2955 |
3008 private: | 2956 private: |
3009 CheckedSmiComparisonInstr* instruction_; | 2957 CheckedSmiComparisonInstr* instruction_; |
3010 intptr_t try_index_; | 2958 intptr_t try_index_; |
3011 BranchLabels labels_; | 2959 BranchLabels labels_; |
3012 bool merged_; | 2960 bool merged_; |
3013 }; | 2961 }; |
3014 | 2962 |
3015 | 2963 |
3016 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 2964 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
3017 Zone* zone, bool opt) const { | 2965 Zone* zone, |
| 2966 bool opt) const { |
3018 const intptr_t kNumInputs = 2; | 2967 const intptr_t kNumInputs = 2; |
3019 const intptr_t kNumTemps = 1; | 2968 const intptr_t kNumTemps = 1; |
3020 LocationSummary* summary = new(zone) LocationSummary( | 2969 LocationSummary* summary = new (zone) LocationSummary( |
3021 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2970 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
3022 summary->set_in(0, Location::RequiresRegister()); | 2971 summary->set_in(0, Location::RequiresRegister()); |
3023 summary->set_in(1, Location::RequiresRegister()); | 2972 summary->set_in(1, Location::RequiresRegister()); |
3024 summary->set_temp(0, Location::RequiresRegister()); | 2973 summary->set_temp(0, Location::RequiresRegister()); |
3025 summary->set_out(0, Location::RequiresRegister()); | 2974 summary->set_out(0, Location::RequiresRegister()); |
3026 return summary; | 2975 return summary; |
3027 } | 2976 } |
3028 | 2977 |
3029 | 2978 |
3030 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 2979 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
3031 FlowGraphCompiler* compiler, BranchLabels labels) { | 2980 FlowGraphCompiler* compiler, |
| 2981 BranchLabels labels) { |
3032 return EmitSmiComparisonOp(compiler, locs(), kind()); | 2982 return EmitSmiComparisonOp(compiler, locs(), kind()); |
3033 } | 2983 } |
3034 | 2984 |
3035 | 2985 |
3036 #define EMIT_SMI_CHECK \ | 2986 #define EMIT_SMI_CHECK \ |
3037 Register left = locs()->in(0).reg(); \ | 2987 Register left = locs()->in(0).reg(); \ |
3038 Register right = locs()->in(1).reg(); \ | 2988 Register right = locs()->in(1).reg(); \ |
3039 Register temp = locs()->temp(0).reg(); \ | 2989 Register temp = locs()->temp(0).reg(); \ |
3040 intptr_t left_cid = this->left()->Type()->ToCid(); \ | 2990 intptr_t left_cid = this->left()->Type()->ToCid(); \ |
3041 intptr_t right_cid = this->right()->Type()->ToCid(); \ | 2991 intptr_t right_cid = this->right()->Type()->ToCid(); \ |
3042 if (this->left()->definition() == this->right()->definition()) { \ | 2992 if (this->left()->definition() == this->right()->definition()) { \ |
3043 __ tsti(left, Immediate(kSmiTagMask)); \ | 2993 __ tsti(left, Immediate(kSmiTagMask)); \ |
3044 } else if (left_cid == kSmiCid) { \ | 2994 } else if (left_cid == kSmiCid) { \ |
3045 __ tsti(right, Immediate(kSmiTagMask)); \ | 2995 __ tsti(right, Immediate(kSmiTagMask)); \ |
3046 } else if (right_cid == kSmiCid) { \ | 2996 } else if (right_cid == kSmiCid) { \ |
3047 __ tsti(left, Immediate(kSmiTagMask)); \ | 2997 __ tsti(left, Immediate(kSmiTagMask)); \ |
3048 } else { \ | 2998 } else { \ |
3049 __ orr(temp, left, Operand(right)); \ | 2999 __ orr(temp, left, Operand(right)); \ |
3050 __ tsti(temp, Immediate(kSmiTagMask)); \ | 3000 __ tsti(temp, Immediate(kSmiTagMask)); \ |
3051 } \ | 3001 } \ |
3052 __ b(slow_path->entry_label(), NE) | 3002 __ b(slow_path->entry_label(), NE) |
3053 | 3003 |
3054 | 3004 |
3055 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3005 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
3056 BranchInstr* branch) { | 3006 BranchInstr* branch) { |
3057 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3007 BranchLabels labels = compiler->CreateBranchLabels(branch); |
3058 CheckedSmiComparisonSlowPath* slow_path = | 3008 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3059 new CheckedSmiComparisonSlowPath(this, | 3009 this, compiler->CurrentTryIndex(), labels, |
3060 compiler->CurrentTryIndex(), | 3010 /* merged = */ true); |
3061 labels, | |
3062 /* merged = */ true); | |
3063 compiler->AddSlowPathCode(slow_path); | 3011 compiler->AddSlowPathCode(slow_path); |
3064 EMIT_SMI_CHECK; | 3012 EMIT_SMI_CHECK; |
3065 Condition true_condition = EmitComparisonCode(compiler, labels); | 3013 Condition true_condition = EmitComparisonCode(compiler, labels); |
3066 EmitBranchOnCondition(compiler, true_condition, labels); | 3014 EmitBranchOnCondition(compiler, true_condition, labels); |
3067 __ Bind(slow_path->exit_label()); | 3015 __ Bind(slow_path->exit_label()); |
3068 } | 3016 } |
3069 | 3017 |
3070 | 3018 |
3071 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3019 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3072 Label true_label, false_label, done; | 3020 Label true_label, false_label, done; |
3073 BranchLabels labels = { &true_label, &false_label, &false_label }; | 3021 BranchLabels labels = {&true_label, &false_label, &false_label}; |
3074 CheckedSmiComparisonSlowPath* slow_path = | 3022 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3075 new CheckedSmiComparisonSlowPath(this, | 3023 this, compiler->CurrentTryIndex(), labels, |
3076 compiler->CurrentTryIndex(), | 3024 /* merged = */ false); |
3077 labels, | |
3078 /* merged = */ false); | |
3079 compiler->AddSlowPathCode(slow_path); | 3025 compiler->AddSlowPathCode(slow_path); |
3080 EMIT_SMI_CHECK; | 3026 EMIT_SMI_CHECK; |
3081 Condition true_condition = | 3027 Condition true_condition = EmitComparisonCode(compiler, labels); |
3082 EmitComparisonCode(compiler, labels); | |
3083 EmitBranchOnCondition(compiler, true_condition, labels); | 3028 EmitBranchOnCondition(compiler, true_condition, labels); |
3084 Register result = locs()->out(0).reg(); | 3029 Register result = locs()->out(0).reg(); |
3085 __ Bind(&false_label); | 3030 __ Bind(&false_label); |
3086 __ LoadObject(result, Bool::False()); | 3031 __ LoadObject(result, Bool::False()); |
3087 __ b(&done); | 3032 __ b(&done); |
3088 __ Bind(&true_label); | 3033 __ Bind(&true_label); |
3089 __ LoadObject(result, Bool::True()); | 3034 __ LoadObject(result, Bool::True()); |
3090 __ Bind(&done); | 3035 __ Bind(&done); |
3091 __ Bind(slow_path->exit_label()); | 3036 __ Bind(slow_path->exit_label()); |
3092 } | 3037 } |
3093 | 3038 |
3094 | 3039 |
3095 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 3040 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
3096 bool opt) const { | 3041 bool opt) const { |
3097 const intptr_t kNumInputs = 2; | 3042 const intptr_t kNumInputs = 2; |
3098 const intptr_t kNumTemps = | 3043 const intptr_t kNumTemps = (((op_kind() == Token::kSHL) && can_overflow()) || |
3099 (((op_kind() == Token::kSHL) && can_overflow()) || | 3044 (op_kind() == Token::kSHR)) |
3100 (op_kind() == Token::kSHR)) ? 1 : 0; | 3045 ? 1 |
3101 LocationSummary* summary = new(zone) LocationSummary( | 3046 : 0; |
3102 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3047 LocationSummary* summary = new (zone) |
| 3048 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3103 if (op_kind() == Token::kTRUNCDIV) { | 3049 if (op_kind() == Token::kTRUNCDIV) { |
3104 summary->set_in(0, Location::RequiresRegister()); | 3050 summary->set_in(0, Location::RequiresRegister()); |
3105 if (RightIsPowerOfTwoConstant()) { | 3051 if (RightIsPowerOfTwoConstant()) { |
3106 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 3052 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
3107 summary->set_in(1, Location::Constant(right_constant)); | 3053 summary->set_in(1, Location::Constant(right_constant)); |
3108 } else { | 3054 } else { |
3109 summary->set_in(1, Location::RequiresRegister()); | 3055 summary->set_in(1, Location::RequiresRegister()); |
3110 } | 3056 } |
3111 summary->set_out(0, Location::RequiresRegister()); | 3057 summary->set_out(0, Location::RequiresRegister()); |
3112 return summary; | 3058 return summary; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3208 __ OrImmediate(result, left, imm); | 3154 __ OrImmediate(result, left, imm); |
3209 break; | 3155 break; |
3210 case Token::kBIT_XOR: | 3156 case Token::kBIT_XOR: |
3211 // No overflow check. | 3157 // No overflow check. |
3212 __ XorImmediate(result, left, imm); | 3158 __ XorImmediate(result, left, imm); |
3213 break; | 3159 break; |
3214 case Token::kSHR: { | 3160 case Token::kSHR: { |
3215 // Asr operation masks the count to 6 bits. | 3161 // Asr operation masks the count to 6 bits. |
3216 const intptr_t kCountLimit = 0x3F; | 3162 const intptr_t kCountLimit = 0x3F; |
3217 intptr_t value = Smi::Cast(constant).Value(); | 3163 intptr_t value = Smi::Cast(constant).Value(); |
3218 __ AsrImmediate( | 3164 __ AsrImmediate(result, left, |
3219 result, left, Utils::Minimum(value + kSmiTagSize, kCountLimit)); | 3165 Utils::Minimum(value + kSmiTagSize, kCountLimit)); |
3220 __ SmiTag(result); | 3166 __ SmiTag(result); |
3221 break; | 3167 break; |
3222 } | 3168 } |
3223 default: | 3169 default: |
3224 UNREACHABLE(); | 3170 UNREACHABLE(); |
3225 break; | 3171 break; |
3226 } | 3172 } |
3227 return; | 3173 return; |
3228 } | 3174 } |
3229 | 3175 |
(...skipping 16 matching lines...) Expand all Loading... |
3246 __ subs(result, left, Operand(right)); | 3192 __ subs(result, left, Operand(right)); |
3247 __ b(deopt, VS); | 3193 __ b(deopt, VS); |
3248 } | 3194 } |
3249 break; | 3195 break; |
3250 } | 3196 } |
3251 case Token::kMUL: { | 3197 case Token::kMUL: { |
3252 __ SmiUntag(TMP, left); | 3198 __ SmiUntag(TMP, left); |
3253 if (deopt == NULL) { | 3199 if (deopt == NULL) { |
3254 __ mul(result, TMP, right); | 3200 __ mul(result, TMP, right); |
3255 } else { | 3201 } else { |
3256 __ mul(result, TMP, right); | 3202 __ mul(result, TMP, right); |
3257 __ smulh(TMP, TMP, right); | 3203 __ smulh(TMP, TMP, right); |
3258 // TMP: result bits 64..127. | 3204 // TMP: result bits 64..127. |
3259 __ cmp(TMP, Operand(result, ASR, 63)); | 3205 __ cmp(TMP, Operand(result, ASR, 63)); |
3260 __ b(deopt, NE); | 3206 __ b(deopt, NE); |
3261 } | 3207 } |
3262 break; | 3208 break; |
3263 } | 3209 } |
3264 case Token::kBIT_AND: { | 3210 case Token::kBIT_AND: { |
3265 // No overflow check. | 3211 // No overflow check. |
3266 __ and_(result, left, Operand(right)); | 3212 __ and_(result, left, Operand(right)); |
3267 break; | 3213 break; |
3268 } | 3214 } |
3269 case Token::kBIT_OR: { | 3215 case Token::kBIT_OR: { |
3270 // No overflow check. | 3216 // No overflow check. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3369 } | 3315 } |
3370 | 3316 |
3371 | 3317 |
3372 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3318 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
3373 bool opt) const { | 3319 bool opt) const { |
3374 intptr_t left_cid = left()->Type()->ToCid(); | 3320 intptr_t left_cid = left()->Type()->ToCid(); |
3375 intptr_t right_cid = right()->Type()->ToCid(); | 3321 intptr_t right_cid = right()->Type()->ToCid(); |
3376 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3322 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
3377 const intptr_t kNumInputs = 2; | 3323 const intptr_t kNumInputs = 2; |
3378 const intptr_t kNumTemps = 0; | 3324 const intptr_t kNumTemps = 0; |
3379 LocationSummary* summary = new(zone) LocationSummary( | 3325 LocationSummary* summary = new (zone) |
3380 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3326 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3381 summary->set_in(0, Location::RequiresRegister()); | 3327 summary->set_in(0, Location::RequiresRegister()); |
3382 summary->set_in(1, Location::RequiresRegister()); | 3328 summary->set_in(1, Location::RequiresRegister()); |
3383 return summary; | 3329 return summary; |
3384 } | 3330 } |
3385 | 3331 |
3386 | 3332 |
3387 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3333 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3388 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3334 Label* deopt = |
3389 ICData::kDeoptBinaryDoubleOp, | 3335 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
3390 licm_hoisted_ ? ICData::kHoisted : 0); | 3336 licm_hoisted_ ? ICData::kHoisted : 0); |
3391 intptr_t left_cid = left()->Type()->ToCid(); | 3337 intptr_t left_cid = left()->Type()->ToCid(); |
3392 intptr_t right_cid = right()->Type()->ToCid(); | 3338 intptr_t right_cid = right()->Type()->ToCid(); |
3393 const Register left = locs()->in(0).reg(); | 3339 const Register left = locs()->in(0).reg(); |
3394 const Register right = locs()->in(1).reg(); | 3340 const Register right = locs()->in(1).reg(); |
3395 if (this->left()->definition() == this->right()->definition()) { | 3341 if (this->left()->definition() == this->right()->definition()) { |
3396 __ tsti(left, Immediate(kSmiTagMask)); | 3342 __ tsti(left, Immediate(kSmiTagMask)); |
3397 } else if (left_cid == kSmiCid) { | 3343 } else if (left_cid == kSmiCid) { |
3398 __ tsti(right, Immediate(kSmiTagMask)); | 3344 __ tsti(right, Immediate(kSmiTagMask)); |
3399 } else if (right_cid == kSmiCid) { | 3345 } else if (right_cid == kSmiCid) { |
3400 __ tsti(left, Immediate(kSmiTagMask)); | 3346 __ tsti(left, Immediate(kSmiTagMask)); |
3401 } else { | 3347 } else { |
3402 __ orr(TMP, left, Operand(right)); | 3348 __ orr(TMP, left, Operand(right)); |
3403 __ tsti(TMP, Immediate(kSmiTagMask)); | 3349 __ tsti(TMP, Immediate(kSmiTagMask)); |
3404 } | 3350 } |
3405 __ b(deopt, EQ); | 3351 __ b(deopt, EQ); |
3406 } | 3352 } |
3407 | 3353 |
3408 | 3354 |
3409 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, | 3355 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
3410 bool opt) const { | |
3411 const intptr_t kNumInputs = 1; | 3356 const intptr_t kNumInputs = 1; |
3412 const intptr_t kNumTemps = 1; | 3357 const intptr_t kNumTemps = 1; |
3413 LocationSummary* summary = new(zone) LocationSummary( | 3358 LocationSummary* summary = new (zone) LocationSummary( |
3414 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3359 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
3415 summary->set_in(0, Location::RequiresFpuRegister()); | 3360 summary->set_in(0, Location::RequiresFpuRegister()); |
3416 summary->set_temp(0, Location::RequiresRegister()); | 3361 summary->set_temp(0, Location::RequiresRegister()); |
3417 summary->set_out(0, Location::RequiresRegister()); | 3362 summary->set_out(0, Location::RequiresRegister()); |
3418 return summary; | 3363 return summary; |
3419 } | 3364 } |
3420 | 3365 |
3421 | 3366 |
3422 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3367 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3423 const Register out_reg = locs()->out(0).reg(); | 3368 const Register out_reg = locs()->out(0).reg(); |
3424 const Register temp_reg = locs()->temp(0).reg(); | 3369 const Register temp_reg = locs()->temp(0).reg(); |
3425 const VRegister value = locs()->in(0).fpu_reg(); | 3370 const VRegister value = locs()->in(0).fpu_reg(); |
3426 | 3371 |
3427 BoxAllocationSlowPath::Allocate( | 3372 BoxAllocationSlowPath::Allocate(compiler, this, |
3428 compiler, | 3373 compiler->BoxClassFor(from_representation()), |
3429 this, | 3374 out_reg, temp_reg); |
3430 compiler->BoxClassFor(from_representation()), | |
3431 out_reg, | |
3432 temp_reg); | |
3433 | 3375 |
3434 switch (from_representation()) { | 3376 switch (from_representation()) { |
3435 case kUnboxedDouble: | 3377 case kUnboxedDouble: |
3436 __ StoreDFieldToOffset(value, out_reg, ValueOffset()); | 3378 __ StoreDFieldToOffset(value, out_reg, ValueOffset()); |
3437 break; | 3379 break; |
3438 case kUnboxedFloat32x4: | 3380 case kUnboxedFloat32x4: |
3439 case kUnboxedFloat64x2: | 3381 case kUnboxedFloat64x2: |
3440 case kUnboxedInt32x4: | 3382 case kUnboxedInt32x4: |
3441 __ StoreQFieldToOffset(value, out_reg, ValueOffset()); | 3383 __ StoreQFieldToOffset(value, out_reg, ValueOffset()); |
3442 break; | 3384 break; |
3443 default: | 3385 default: |
3444 UNREACHABLE(); | 3386 UNREACHABLE(); |
3445 break; | 3387 break; |
3446 } | 3388 } |
3447 } | 3389 } |
3448 | 3390 |
3449 | 3391 |
3450 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, | 3392 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
3451 bool opt) const { | |
3452 const intptr_t kNumInputs = 1; | 3393 const intptr_t kNumInputs = 1; |
3453 const intptr_t kNumTemps = 0; | 3394 const intptr_t kNumTemps = 0; |
3454 LocationSummary* summary = new(zone) LocationSummary( | 3395 LocationSummary* summary = new (zone) |
3455 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3396 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3456 summary->set_in(0, Location::RequiresRegister()); | 3397 summary->set_in(0, Location::RequiresRegister()); |
3457 summary->set_out(0, Location::RequiresFpuRegister()); | 3398 summary->set_out(0, Location::RequiresFpuRegister()); |
3458 return summary; | 3399 return summary; |
3459 } | 3400 } |
3460 | 3401 |
3461 | 3402 |
3462 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { | 3403 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |
3463 const Register box = locs()->in(0).reg(); | 3404 const Register box = locs()->in(0).reg(); |
3464 | 3405 |
3465 switch (representation()) { | 3406 switch (representation()) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3515 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3456 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3516 const intptr_t value_cid = value()->Type()->ToCid(); | 3457 const intptr_t value_cid = value()->Type()->ToCid(); |
3517 const intptr_t box_cid = BoxCid(); | 3458 const intptr_t box_cid = BoxCid(); |
3518 | 3459 |
3519 if (value_cid == box_cid) { | 3460 if (value_cid == box_cid) { |
3520 EmitLoadFromBox(compiler); | 3461 EmitLoadFromBox(compiler); |
3521 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 3462 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
3522 EmitSmiConversion(compiler); | 3463 EmitSmiConversion(compiler); |
3523 } else { | 3464 } else { |
3524 const Register box = locs()->in(0).reg(); | 3465 const Register box = locs()->in(0).reg(); |
3525 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), | 3466 Label* deopt = |
3526 ICData::kDeoptCheckClass); | 3467 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass); |
3527 Label is_smi; | 3468 Label is_smi; |
3528 | 3469 |
3529 if ((value()->Type()->ToNullableCid() == box_cid) && | 3470 if ((value()->Type()->ToNullableCid() == box_cid) && |
3530 value()->Type()->is_nullable()) { | 3471 value()->Type()->is_nullable()) { |
3531 __ CompareObject(box, Object::null_object()); | 3472 __ CompareObject(box, Object::null_object()); |
3532 __ b(deopt, EQ); | 3473 __ b(deopt, EQ); |
3533 } else { | 3474 } else { |
3534 __ tsti(box, Immediate(kSmiTagMask)); | 3475 __ tsti(box, Immediate(kSmiTagMask)); |
3535 __ b(CanConvertSmi() ? &is_smi : deopt, EQ); | 3476 __ b(CanConvertSmi() ? &is_smi : deopt, EQ); |
3536 __ CompareClassId(box, box_cid); | 3477 __ CompareClassId(box, box_cid); |
(...skipping 12 matching lines...) Expand all Loading... |
3549 } | 3490 } |
3550 } | 3491 } |
3551 | 3492 |
3552 | 3493 |
3553 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 3494 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |
3554 bool opt) const { | 3495 bool opt) const { |
3555 ASSERT((from_representation() == kUnboxedInt32) || | 3496 ASSERT((from_representation() == kUnboxedInt32) || |
3556 (from_representation() == kUnboxedUint32)); | 3497 (from_representation() == kUnboxedUint32)); |
3557 const intptr_t kNumInputs = 1; | 3498 const intptr_t kNumInputs = 1; |
3558 const intptr_t kNumTemps = 0; | 3499 const intptr_t kNumTemps = 0; |
3559 LocationSummary* summary = new(zone) LocationSummary( | 3500 LocationSummary* summary = new (zone) |
3560 zone, | 3501 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3561 kNumInputs, | |
3562 kNumTemps, | |
3563 LocationSummary::kNoCall); | |
3564 summary->set_in(0, Location::RequiresRegister()); | 3502 summary->set_in(0, Location::RequiresRegister()); |
3565 summary->set_out(0, Location::RequiresRegister()); | 3503 summary->set_out(0, Location::RequiresRegister()); |
3566 return summary; | 3504 return summary; |
3567 } | 3505 } |
3568 | 3506 |
3569 | 3507 |
3570 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3508 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3571 Register value = locs()->in(0).reg(); | 3509 Register value = locs()->in(0).reg(); |
3572 Register out = locs()->out(0).reg(); | 3510 Register out = locs()->out(0).reg(); |
3573 ASSERT(value != out); | 3511 ASSERT(value != out); |
(...skipping 10 matching lines...) Expand all Loading... |
3584 } | 3522 } |
3585 | 3523 |
3586 | 3524 |
3587 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr) | 3525 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr) |
3588 | 3526 |
3589 | 3527 |
3590 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 3528 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |
3591 bool opt) const { | 3529 bool opt) const { |
3592 const intptr_t kNumInputs = 1; | 3530 const intptr_t kNumInputs = 1; |
3593 const intptr_t kNumTemps = 0; | 3531 const intptr_t kNumTemps = 0; |
3594 LocationSummary* summary = new(zone) LocationSummary( | 3532 LocationSummary* summary = new (zone) |
3595 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3533 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3596 summary->set_in(0, Location::RequiresRegister()); | 3534 summary->set_in(0, Location::RequiresRegister()); |
3597 summary->set_out(0, Location::RequiresRegister()); | 3535 summary->set_out(0, Location::RequiresRegister()); |
3598 return summary; | 3536 return summary; |
3599 } | 3537 } |
3600 | 3538 |
3601 | 3539 |
3602 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3540 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3603 const intptr_t value_cid = value()->Type()->ToCid(); | 3541 const intptr_t value_cid = value()->Type()->ToCid(); |
3604 const Register out = locs()->out(0).reg(); | 3542 const Register out = locs()->out(0).reg(); |
3605 const Register value = locs()->in(0).reg(); | 3543 const Register value = locs()->in(0).reg(); |
3606 Label* deopt = CanDeoptimize() ? | 3544 Label* deopt = |
3607 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL; | 3545 CanDeoptimize() |
| 3546 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) |
| 3547 : NULL; |
3608 | 3548 |
3609 if (value_cid == kSmiCid) { | 3549 if (value_cid == kSmiCid) { |
3610 __ SmiUntag(out, value); | 3550 __ SmiUntag(out, value); |
3611 } else if (value_cid == kMintCid) { | 3551 } else if (value_cid == kMintCid) { |
3612 __ LoadFieldFromOffset(out, value, Mint::value_offset()); | 3552 __ LoadFieldFromOffset(out, value, Mint::value_offset()); |
3613 } else if (!CanDeoptimize()) { | 3553 } else if (!CanDeoptimize()) { |
3614 // Type information is not conclusive, but range analysis found | 3554 // Type information is not conclusive, but range analysis found |
3615 // the value to be in int64 range. Therefore it must be a smi | 3555 // the value to be in int64 range. Therefore it must be a smi |
3616 // or mint value. | 3556 // or mint value. |
3617 ASSERT(is_truncating()); | 3557 ASSERT(is_truncating()); |
(...skipping 21 matching lines...) Expand all Loading... |
3639 __ cmp(out, Operand(out, SXTW, 0)); | 3579 __ cmp(out, Operand(out, SXTW, 0)); |
3640 __ b(deopt, NE); | 3580 __ b(deopt, NE); |
3641 } | 3581 } |
3642 } | 3582 } |
3643 | 3583 |
3644 | 3584 |
3645 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 3585 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
3646 bool opt) const { | 3586 bool opt) const { |
3647 const intptr_t kNumInputs = 2; | 3587 const intptr_t kNumInputs = 2; |
3648 const intptr_t kNumTemps = 0; | 3588 const intptr_t kNumTemps = 0; |
3649 LocationSummary* summary = new(zone) LocationSummary( | 3589 LocationSummary* summary = new (zone) |
3650 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3590 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3651 summary->set_in(0, Location::RequiresFpuRegister()); | 3591 summary->set_in(0, Location::RequiresFpuRegister()); |
3652 summary->set_in(1, Location::RequiresFpuRegister()); | 3592 summary->set_in(1, Location::RequiresFpuRegister()); |
3653 summary->set_out(0, Location::RequiresFpuRegister()); | 3593 summary->set_out(0, Location::RequiresFpuRegister()); |
3654 return summary; | 3594 return summary; |
3655 } | 3595 } |
3656 | 3596 |
3657 | 3597 |
3658 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3598 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3659 const VRegister left = locs()->in(0).fpu_reg(); | 3599 const VRegister left = locs()->in(0).fpu_reg(); |
3660 const VRegister right = locs()->in(1).fpu_reg(); | 3600 const VRegister right = locs()->in(1).fpu_reg(); |
3661 const VRegister result = locs()->out(0).fpu_reg(); | 3601 const VRegister result = locs()->out(0).fpu_reg(); |
3662 switch (op_kind()) { | 3602 switch (op_kind()) { |
3663 case Token::kADD: __ faddd(result, left, right); break; | 3603 case Token::kADD: |
3664 case Token::kSUB: __ fsubd(result, left, right); break; | 3604 __ faddd(result, left, right); |
3665 case Token::kMUL: __ fmuld(result, left, right); break; | 3605 break; |
3666 case Token::kDIV: __ fdivd(result, left, right); break; | 3606 case Token::kSUB: |
3667 default: UNREACHABLE(); | 3607 __ fsubd(result, left, right); |
| 3608 break; |
| 3609 case Token::kMUL: |
| 3610 __ fmuld(result, left, right); |
| 3611 break; |
| 3612 case Token::kDIV: |
| 3613 __ fdivd(result, left, right); |
| 3614 break; |
| 3615 default: |
| 3616 UNREACHABLE(); |
3668 } | 3617 } |
3669 } | 3618 } |
3670 | 3619 |
3671 | 3620 |
3672 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 3621 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |
3673 bool opt) const { | 3622 bool opt) const { |
3674 const intptr_t kNumInputs = 1; | 3623 const intptr_t kNumInputs = 1; |
3675 const intptr_t kNumTemps = | 3624 const intptr_t kNumTemps = |
3676 op_kind() == MethodRecognizer::kDouble_getIsInfinite ? 1 : 0; | 3625 op_kind() == MethodRecognizer::kDouble_getIsInfinite ? 1 : 0; |
3677 LocationSummary* summary = new(zone) LocationSummary( | 3626 LocationSummary* summary = new (zone) |
3678 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3627 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3679 summary->set_in(0, Location::RequiresFpuRegister()); | 3628 summary->set_in(0, Location::RequiresFpuRegister()); |
3680 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 3629 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
3681 summary->set_temp(0, Location::RequiresRegister()); | 3630 summary->set_temp(0, Location::RequiresRegister()); |
3682 } | 3631 } |
3683 summary->set_out(0, Location::RequiresRegister()); | 3632 summary->set_out(0, Location::RequiresRegister()); |
3684 return summary; | 3633 return summary; |
3685 } | 3634 } |
3686 | 3635 |
3687 | 3636 |
3688 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 3637 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
(...skipping 22 matching lines...) Expand all Loading... |
3711 ASSERT(compiler->is_optimizing()); | 3660 ASSERT(compiler->is_optimizing()); |
3712 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3661 BranchLabels labels = compiler->CreateBranchLabels(branch); |
3713 Condition true_condition = EmitComparisonCode(compiler, labels); | 3662 Condition true_condition = EmitComparisonCode(compiler, labels); |
3714 EmitBranchOnCondition(compiler, true_condition, labels); | 3663 EmitBranchOnCondition(compiler, true_condition, labels); |
3715 } | 3664 } |
3716 | 3665 |
3717 | 3666 |
3718 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3667 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3719 ASSERT(compiler->is_optimizing()); | 3668 ASSERT(compiler->is_optimizing()); |
3720 Label is_true, is_false; | 3669 Label is_true, is_false; |
3721 BranchLabels labels = { &is_true, &is_false, &is_false }; | 3670 BranchLabels labels = {&is_true, &is_false, &is_false}; |
3722 Condition true_condition = EmitComparisonCode(compiler, labels); | 3671 Condition true_condition = EmitComparisonCode(compiler, labels); |
3723 const Register result = locs()->out(0).reg(); | 3672 const Register result = locs()->out(0).reg(); |
3724 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { | 3673 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { |
3725 __ LoadObject(result, Bool::False()); | 3674 __ LoadObject(result, Bool::False()); |
3726 __ LoadObject(TMP, Bool::True()); | 3675 __ LoadObject(TMP, Bool::True()); |
3727 __ csel(result, TMP, result, true_condition); | 3676 __ csel(result, TMP, result, true_condition); |
3728 } else { | 3677 } else { |
3729 __ LoadObject(result, Bool::False()); | 3678 __ LoadObject(result, Bool::False()); |
3730 __ LoadObject(TMP, Bool::True()); | 3679 __ LoadObject(TMP, Bool::True()); |
3731 __ csel(result, TMP, result, true_condition); | 3680 __ csel(result, TMP, result, true_condition); |
3732 } | 3681 } |
3733 } | 3682 } |
3734 | 3683 |
3735 | 3684 |
3736 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 3685 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
3737 bool opt) const { | 3686 bool opt) const { |
3738 const intptr_t kNumInputs = 2; | 3687 const intptr_t kNumInputs = 2; |
3739 const intptr_t kNumTemps = 0; | 3688 const intptr_t kNumTemps = 0; |
3740 LocationSummary* summary = new(zone) LocationSummary( | 3689 LocationSummary* summary = new (zone) |
3741 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3690 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3742 summary->set_in(0, Location::RequiresFpuRegister()); | 3691 summary->set_in(0, Location::RequiresFpuRegister()); |
3743 summary->set_in(1, Location::RequiresFpuRegister()); | 3692 summary->set_in(1, Location::RequiresFpuRegister()); |
3744 summary->set_out(0, Location::RequiresFpuRegister()); | 3693 summary->set_out(0, Location::RequiresFpuRegister()); |
3745 return summary; | 3694 return summary; |
3746 } | 3695 } |
3747 | 3696 |
3748 | 3697 |
3749 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3698 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3750 const VRegister left = locs()->in(0).fpu_reg(); | 3699 const VRegister left = locs()->in(0).fpu_reg(); |
3751 const VRegister right = locs()->in(1).fpu_reg(); | 3700 const VRegister right = locs()->in(1).fpu_reg(); |
3752 const VRegister result = locs()->out(0).fpu_reg(); | 3701 const VRegister result = locs()->out(0).fpu_reg(); |
3753 | 3702 |
3754 switch (op_kind()) { | 3703 switch (op_kind()) { |
3755 case Token::kADD: __ vadds(result, left, right); break; | 3704 case Token::kADD: |
3756 case Token::kSUB: __ vsubs(result, left, right); break; | 3705 __ vadds(result, left, right); |
3757 case Token::kMUL: __ vmuls(result, left, right); break; | 3706 break; |
3758 case Token::kDIV: __ vdivs(result, left, right); break; | 3707 case Token::kSUB: |
3759 default: UNREACHABLE(); | 3708 __ vsubs(result, left, right); |
| 3709 break; |
| 3710 case Token::kMUL: |
| 3711 __ vmuls(result, left, right); |
| 3712 break; |
| 3713 case Token::kDIV: |
| 3714 __ vdivs(result, left, right); |
| 3715 break; |
| 3716 default: |
| 3717 UNREACHABLE(); |
3760 } | 3718 } |
3761 } | 3719 } |
3762 | 3720 |
3763 | 3721 |
3764 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, | 3722 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, |
3765 bool opt) const { | 3723 bool opt) const { |
3766 const intptr_t kNumInputs = 2; | 3724 const intptr_t kNumInputs = 2; |
3767 const intptr_t kNumTemps = 0; | 3725 const intptr_t kNumTemps = 0; |
3768 LocationSummary* summary = new(zone) LocationSummary( | 3726 LocationSummary* summary = new (zone) |
3769 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3727 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3770 summary->set_in(0, Location::RequiresFpuRegister()); | 3728 summary->set_in(0, Location::RequiresFpuRegister()); |
3771 summary->set_in(1, Location::RequiresFpuRegister()); | 3729 summary->set_in(1, Location::RequiresFpuRegister()); |
3772 summary->set_out(0, Location::RequiresFpuRegister()); | 3730 summary->set_out(0, Location::RequiresFpuRegister()); |
3773 return summary; | 3731 return summary; |
3774 } | 3732 } |
3775 | 3733 |
3776 | 3734 |
3777 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3735 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3778 const VRegister left = locs()->in(0).fpu_reg(); | 3736 const VRegister left = locs()->in(0).fpu_reg(); |
3779 const VRegister right = locs()->in(1).fpu_reg(); | 3737 const VRegister right = locs()->in(1).fpu_reg(); |
3780 const VRegister result = locs()->out(0).fpu_reg(); | 3738 const VRegister result = locs()->out(0).fpu_reg(); |
3781 | 3739 |
3782 switch (op_kind()) { | 3740 switch (op_kind()) { |
3783 case Token::kADD: __ vaddd(result, left, right); break; | 3741 case Token::kADD: |
3784 case Token::kSUB: __ vsubd(result, left, right); break; | 3742 __ vaddd(result, left, right); |
3785 case Token::kMUL: __ vmuld(result, left, right); break; | 3743 break; |
3786 case Token::kDIV: __ vdivd(result, left, right); break; | 3744 case Token::kSUB: |
3787 default: UNREACHABLE(); | 3745 __ vsubd(result, left, right); |
| 3746 break; |
| 3747 case Token::kMUL: |
| 3748 __ vmuld(result, left, right); |
| 3749 break; |
| 3750 case Token::kDIV: |
| 3751 __ vdivd(result, left, right); |
| 3752 break; |
| 3753 default: |
| 3754 UNREACHABLE(); |
3788 } | 3755 } |
3789 } | 3756 } |
3790 | 3757 |
3791 | 3758 |
3792 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, | 3759 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, |
3793 bool opt) const { | 3760 bool opt) const { |
3794 const intptr_t kNumInputs = 1; | 3761 const intptr_t kNumInputs = 1; |
3795 const intptr_t kNumTemps = 0; | 3762 const intptr_t kNumTemps = 0; |
3796 LocationSummary* summary = new LocationSummary( | 3763 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
3797 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3764 LocationSummary::kNoCall); |
3798 summary->set_in(0, Location::RequiresFpuRegister()); | 3765 summary->set_in(0, Location::RequiresFpuRegister()); |
3799 summary->set_out(0, Location::RequiresFpuRegister()); | 3766 summary->set_out(0, Location::RequiresFpuRegister()); |
3800 return summary; | 3767 return summary; |
3801 } | 3768 } |
3802 | 3769 |
3803 | 3770 |
3804 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3771 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3805 const VRegister value = locs()->in(0).fpu_reg(); | 3772 const VRegister value = locs()->in(0).fpu_reg(); |
3806 const VRegister result = locs()->out(0).fpu_reg(); | 3773 const VRegister result = locs()->out(0).fpu_reg(); |
3807 | 3774 |
(...skipping 15 matching lines...) Expand all Loading... |
3823 __ fcvtds(result, result); | 3790 __ fcvtds(result, result); |
3824 break; | 3791 break; |
3825 case MethodRecognizer::kInt32x4Shuffle: | 3792 case MethodRecognizer::kInt32x4Shuffle: |
3826 case MethodRecognizer::kFloat32x4Shuffle: | 3793 case MethodRecognizer::kFloat32x4Shuffle: |
3827 if (mask_ == 0x00) { | 3794 if (mask_ == 0x00) { |
3828 __ vdups(result, value, 0); | 3795 __ vdups(result, value, 0); |
3829 } else if (mask_ == 0x55) { | 3796 } else if (mask_ == 0x55) { |
3830 __ vdups(result, value, 1); | 3797 __ vdups(result, value, 1); |
3831 } else if (mask_ == 0xAA) { | 3798 } else if (mask_ == 0xAA) { |
3832 __ vdups(result, value, 2); | 3799 __ vdups(result, value, 2); |
3833 } else if (mask_ == 0xFF) { | 3800 } else if (mask_ == 0xFF) { |
3834 __ vdups(result, value, 3); | 3801 __ vdups(result, value, 3); |
3835 } else { | 3802 } else { |
3836 __ vinss(result, 0, value, mask_ & 0x3); | 3803 __ vinss(result, 0, value, mask_ & 0x3); |
3837 __ vinss(result, 1, value, (mask_ >> 2) & 0x3); | 3804 __ vinss(result, 1, value, (mask_ >> 2) & 0x3); |
3838 __ vinss(result, 2, value, (mask_ >> 4) & 0x3); | 3805 __ vinss(result, 2, value, (mask_ >> 4) & 0x3); |
3839 __ vinss(result, 3, value, (mask_ >> 6) & 0x3); | 3806 __ vinss(result, 3, value, (mask_ >> 6) & 0x3); |
3840 } | 3807 } |
3841 break; | 3808 break; |
3842 default: UNREACHABLE(); | 3809 default: |
| 3810 UNREACHABLE(); |
3843 } | 3811 } |
3844 } | 3812 } |
3845 | 3813 |
3846 | 3814 |
3847 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 3815 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |
3848 bool opt) const { | 3816 bool opt) const { |
3849 const intptr_t kNumInputs = 2; | 3817 const intptr_t kNumInputs = 2; |
3850 const intptr_t kNumTemps = 0; | 3818 const intptr_t kNumTemps = 0; |
3851 LocationSummary* summary = new LocationSummary( | 3819 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
3852 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3820 LocationSummary::kNoCall); |
3853 summary->set_in(0, Location::RequiresFpuRegister()); | 3821 summary->set_in(0, Location::RequiresFpuRegister()); |
3854 summary->set_in(1, Location::RequiresFpuRegister()); | 3822 summary->set_in(1, Location::RequiresFpuRegister()); |
3855 summary->set_out(0, Location::RequiresFpuRegister()); | 3823 summary->set_out(0, Location::RequiresFpuRegister()); |
3856 return summary; | 3824 return summary; |
3857 } | 3825 } |
3858 | 3826 |
3859 | 3827 |
3860 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3828 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3861 const VRegister left = locs()->in(0).fpu_reg(); | 3829 const VRegister left = locs()->in(0).fpu_reg(); |
3862 const VRegister right = locs()->in(1).fpu_reg(); | 3830 const VRegister right = locs()->in(1).fpu_reg(); |
3863 const VRegister result = locs()->out(0).fpu_reg(); | 3831 const VRegister result = locs()->out(0).fpu_reg(); |
3864 | 3832 |
3865 switch (op_kind()) { | 3833 switch (op_kind()) { |
3866 case MethodRecognizer::kFloat32x4ShuffleMix: | 3834 case MethodRecognizer::kFloat32x4ShuffleMix: |
3867 case MethodRecognizer::kInt32x4ShuffleMix: | 3835 case MethodRecognizer::kInt32x4ShuffleMix: |
3868 __ vinss(result, 0, left, mask_ & 0x3); | 3836 __ vinss(result, 0, left, mask_ & 0x3); |
3869 __ vinss(result, 1, left, (mask_ >> 2) & 0x3); | 3837 __ vinss(result, 1, left, (mask_ >> 2) & 0x3); |
3870 __ vinss(result, 2, right, (mask_ >> 4) & 0x3); | 3838 __ vinss(result, 2, right, (mask_ >> 4) & 0x3); |
3871 __ vinss(result, 3, right, (mask_ >> 6) & 0x3); | 3839 __ vinss(result, 3, right, (mask_ >> 6) & 0x3); |
3872 break; | 3840 break; |
3873 default: UNREACHABLE(); | 3841 default: |
| 3842 UNREACHABLE(); |
3874 } | 3843 } |
3875 } | 3844 } |
3876 | 3845 |
3877 | 3846 |
3878 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, | 3847 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, |
3879 bool opt) const { | 3848 bool opt) const { |
3880 const intptr_t kNumInputs = 1; | 3849 const intptr_t kNumInputs = 1; |
3881 const intptr_t kNumTemps = 1; | 3850 const intptr_t kNumTemps = 1; |
3882 LocationSummary* summary = new LocationSummary( | 3851 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
3883 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3852 LocationSummary::kNoCall); |
3884 summary->set_in(0, Location::RequiresFpuRegister()); | 3853 summary->set_in(0, Location::RequiresFpuRegister()); |
3885 summary->set_temp(0, Location::RequiresRegister()); | 3854 summary->set_temp(0, Location::RequiresRegister()); |
3886 summary->set_out(0, Location::RequiresRegister()); | 3855 summary->set_out(0, Location::RequiresRegister()); |
3887 return summary; | 3856 return summary; |
3888 } | 3857 } |
3889 | 3858 |
3890 | 3859 |
3891 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3860 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3892 const VRegister value = locs()->in(0).fpu_reg(); | 3861 const VRegister value = locs()->in(0).fpu_reg(); |
3893 const Register out = locs()->out(0).reg(); | 3862 const Register out = locs()->out(0).reg(); |
(...skipping 13 matching lines...) Expand all Loading... |
3907 // W lane. | 3876 // W lane. |
3908 __ vmovrs(temp, value, 3); | 3877 __ vmovrs(temp, value, 3); |
3909 __ LsrImmediate(temp, temp, 31); | 3878 __ LsrImmediate(temp, temp, 31); |
3910 __ orr(out, out, Operand(temp, LSL, 3)); | 3879 __ orr(out, out, Operand(temp, LSL, 3)); |
3911 // Tag. | 3880 // Tag. |
3912 __ SmiTag(out); | 3881 __ SmiTag(out); |
3913 } | 3882 } |
3914 | 3883 |
3915 | 3884 |
3916 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 3885 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
3917 Zone* zone, bool opt) const { | 3886 Zone* zone, |
| 3887 bool opt) const { |
3918 const intptr_t kNumInputs = 4; | 3888 const intptr_t kNumInputs = 4; |
3919 const intptr_t kNumTemps = 0; | 3889 const intptr_t kNumTemps = 0; |
3920 LocationSummary* summary = new(zone) LocationSummary( | 3890 LocationSummary* summary = new (zone) |
3921 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3891 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3922 summary->set_in(0, Location::RequiresFpuRegister()); | 3892 summary->set_in(0, Location::RequiresFpuRegister()); |
3923 summary->set_in(1, Location::RequiresFpuRegister()); | 3893 summary->set_in(1, Location::RequiresFpuRegister()); |
3924 summary->set_in(2, Location::RequiresFpuRegister()); | 3894 summary->set_in(2, Location::RequiresFpuRegister()); |
3925 summary->set_in(3, Location::RequiresFpuRegister()); | 3895 summary->set_in(3, Location::RequiresFpuRegister()); |
3926 summary->set_out(0, Location::RequiresFpuRegister()); | 3896 summary->set_out(0, Location::RequiresFpuRegister()); |
3927 return summary; | 3897 return summary; |
3928 } | 3898 } |
3929 | 3899 |
3930 | 3900 |
3931 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3901 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(...skipping 11 matching lines...) Expand all Loading... |
3943 __ vinss(r, 2, VTMP, 0); | 3913 __ vinss(r, 2, VTMP, 0); |
3944 __ fcvtsd(VTMP, v3); | 3914 __ fcvtsd(VTMP, v3); |
3945 __ vinss(r, 3, VTMP, 0); | 3915 __ vinss(r, 3, VTMP, 0); |
3946 } | 3916 } |
3947 | 3917 |
3948 | 3918 |
3949 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, | 3919 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, |
3950 bool opt) const { | 3920 bool opt) const { |
3951 const intptr_t kNumInputs = 0; | 3921 const intptr_t kNumInputs = 0; |
3952 const intptr_t kNumTemps = 0; | 3922 const intptr_t kNumTemps = 0; |
3953 LocationSummary* summary = new(zone) LocationSummary( | 3923 LocationSummary* summary = new (zone) |
3954 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3924 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3955 summary->set_out(0, Location::RequiresFpuRegister()); | 3925 summary->set_out(0, Location::RequiresFpuRegister()); |
3956 return summary; | 3926 return summary; |
3957 } | 3927 } |
3958 | 3928 |
3959 | 3929 |
3960 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3930 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3961 const VRegister v = locs()->out(0).fpu_reg(); | 3931 const VRegister v = locs()->out(0).fpu_reg(); |
3962 __ veor(v, v, v); | 3932 __ veor(v, v, v); |
3963 } | 3933 } |
3964 | 3934 |
3965 | 3935 |
3966 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, | 3936 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, |
3967 bool opt) const { | 3937 bool opt) const { |
3968 const intptr_t kNumInputs = 1; | 3938 const intptr_t kNumInputs = 1; |
3969 const intptr_t kNumTemps = 0; | 3939 const intptr_t kNumTemps = 0; |
3970 LocationSummary* summary = new(zone) LocationSummary( | 3940 LocationSummary* summary = new (zone) |
3971 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3941 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3972 summary->set_in(0, Location::RequiresFpuRegister()); | 3942 summary->set_in(0, Location::RequiresFpuRegister()); |
3973 summary->set_out(0, Location::RequiresFpuRegister()); | 3943 summary->set_out(0, Location::RequiresFpuRegister()); |
3974 return summary; | 3944 return summary; |
3975 } | 3945 } |
3976 | 3946 |
3977 | 3947 |
3978 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3948 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3979 const VRegister value = locs()->in(0).fpu_reg(); | 3949 const VRegister value = locs()->in(0).fpu_reg(); |
3980 const VRegister result = locs()->out(0).fpu_reg(); | 3950 const VRegister result = locs()->out(0).fpu_reg(); |
3981 | 3951 |
3982 // Convert to Float32. | 3952 // Convert to Float32. |
3983 __ fcvtsd(VTMP, value); | 3953 __ fcvtsd(VTMP, value); |
3984 | 3954 |
3985 // Splat across all lanes. | 3955 // Splat across all lanes. |
3986 __ vdups(result, VTMP, 0); | 3956 __ vdups(result, VTMP, 0); |
3987 } | 3957 } |
3988 | 3958 |
3989 | 3959 |
3990 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, | 3960 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, |
3991 bool opt) const { | 3961 bool opt) const { |
3992 const intptr_t kNumInputs = 2; | 3962 const intptr_t kNumInputs = 2; |
3993 const intptr_t kNumTemps = 0; | 3963 const intptr_t kNumTemps = 0; |
3994 LocationSummary* summary = new(zone) LocationSummary( | 3964 LocationSummary* summary = new (zone) |
3995 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3965 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3996 summary->set_in(0, Location::RequiresFpuRegister()); | 3966 summary->set_in(0, Location::RequiresFpuRegister()); |
3997 summary->set_in(1, Location::RequiresFpuRegister()); | 3967 summary->set_in(1, Location::RequiresFpuRegister()); |
3998 summary->set_out(0, Location::RequiresFpuRegister()); | 3968 summary->set_out(0, Location::RequiresFpuRegister()); |
3999 return summary; | 3969 return summary; |
4000 } | 3970 } |
4001 | 3971 |
4002 | 3972 |
4003 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3973 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4004 const VRegister left = locs()->in(0).fpu_reg(); | 3974 const VRegister left = locs()->in(0).fpu_reg(); |
4005 const VRegister right = locs()->in(1).fpu_reg(); | 3975 const VRegister right = locs()->in(1).fpu_reg(); |
(...skipping 14 matching lines...) Expand all Loading... |
4020 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: | 3990 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: |
4021 __ vcges(result, left, right); | 3991 __ vcges(result, left, right); |
4022 break; | 3992 break; |
4023 case MethodRecognizer::kFloat32x4LessThan: | 3993 case MethodRecognizer::kFloat32x4LessThan: |
4024 __ vcgts(result, right, left); | 3994 __ vcgts(result, right, left); |
4025 break; | 3995 break; |
4026 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 3996 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
4027 __ vcges(result, right, left); | 3997 __ vcges(result, right, left); |
4028 break; | 3998 break; |
4029 | 3999 |
4030 default: UNREACHABLE(); | 4000 default: |
| 4001 UNREACHABLE(); |
4031 } | 4002 } |
4032 } | 4003 } |
4033 | 4004 |
4034 | 4005 |
4035 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, | 4006 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, |
4036 bool opt) const { | 4007 bool opt) const { |
4037 const intptr_t kNumInputs = 2; | 4008 const intptr_t kNumInputs = 2; |
4038 const intptr_t kNumTemps = 0; | 4009 const intptr_t kNumTemps = 0; |
4039 LocationSummary* summary = new(zone) LocationSummary( | 4010 LocationSummary* summary = new (zone) |
4040 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4011 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4041 summary->set_in(0, Location::RequiresFpuRegister()); | 4012 summary->set_in(0, Location::RequiresFpuRegister()); |
4042 summary->set_in(1, Location::RequiresFpuRegister()); | 4013 summary->set_in(1, Location::RequiresFpuRegister()); |
4043 summary->set_out(0, Location::RequiresFpuRegister()); | 4014 summary->set_out(0, Location::RequiresFpuRegister()); |
4044 return summary; | 4015 return summary; |
4045 } | 4016 } |
4046 | 4017 |
4047 | 4018 |
4048 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4019 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4049 const VRegister left = locs()->in(0).fpu_reg(); | 4020 const VRegister left = locs()->in(0).fpu_reg(); |
4050 const VRegister right = locs()->in(1).fpu_reg(); | 4021 const VRegister right = locs()->in(1).fpu_reg(); |
4051 const VRegister result = locs()->out(0).fpu_reg(); | 4022 const VRegister result = locs()->out(0).fpu_reg(); |
4052 | 4023 |
4053 switch (op_kind()) { | 4024 switch (op_kind()) { |
4054 case MethodRecognizer::kFloat32x4Min: | 4025 case MethodRecognizer::kFloat32x4Min: |
4055 __ vmins(result, left, right); | 4026 __ vmins(result, left, right); |
4056 break; | 4027 break; |
4057 case MethodRecognizer::kFloat32x4Max: | 4028 case MethodRecognizer::kFloat32x4Max: |
4058 __ vmaxs(result, left, right); | 4029 __ vmaxs(result, left, right); |
4059 break; | 4030 break; |
4060 default: UNREACHABLE(); | 4031 default: |
| 4032 UNREACHABLE(); |
4061 } | 4033 } |
4062 } | 4034 } |
4063 | 4035 |
4064 | 4036 |
4065 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, | 4037 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, |
4066 bool opt) const { | 4038 bool opt) const { |
4067 const intptr_t kNumInputs = 1; | 4039 const intptr_t kNumInputs = 1; |
4068 const intptr_t kNumTemps = 0; | 4040 const intptr_t kNumTemps = 0; |
4069 LocationSummary* summary = new(zone) LocationSummary( | 4041 LocationSummary* summary = new (zone) |
4070 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4042 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4071 summary->set_in(0, Location::RequiresFpuRegister()); | 4043 summary->set_in(0, Location::RequiresFpuRegister()); |
4072 summary->set_out(0, Location::RequiresFpuRegister()); | 4044 summary->set_out(0, Location::RequiresFpuRegister()); |
4073 return summary; | 4045 return summary; |
4074 } | 4046 } |
4075 | 4047 |
4076 | 4048 |
4077 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4049 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4078 const VRegister left = locs()->in(0).fpu_reg(); | 4050 const VRegister left = locs()->in(0).fpu_reg(); |
4079 const VRegister result = locs()->out(0).fpu_reg(); | 4051 const VRegister result = locs()->out(0).fpu_reg(); |
4080 | 4052 |
4081 switch (op_kind()) { | 4053 switch (op_kind()) { |
4082 case MethodRecognizer::kFloat32x4Sqrt: | 4054 case MethodRecognizer::kFloat32x4Sqrt: |
4083 __ vsqrts(result, left); | 4055 __ vsqrts(result, left); |
4084 break; | 4056 break; |
4085 case MethodRecognizer::kFloat32x4Reciprocal: | 4057 case MethodRecognizer::kFloat32x4Reciprocal: |
4086 __ VRecps(result, left); | 4058 __ VRecps(result, left); |
4087 break; | 4059 break; |
4088 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 4060 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
4089 __ VRSqrts(result, left); | 4061 __ VRSqrts(result, left); |
4090 break; | 4062 break; |
4091 default: UNREACHABLE(); | 4063 default: |
| 4064 UNREACHABLE(); |
4092 } | 4065 } |
4093 } | 4066 } |
4094 | 4067 |
4095 | 4068 |
4096 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, | 4069 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, |
4097 bool opt) const { | 4070 bool opt) const { |
4098 const intptr_t kNumInputs = 2; | 4071 const intptr_t kNumInputs = 2; |
4099 const intptr_t kNumTemps = 0; | 4072 const intptr_t kNumTemps = 0; |
4100 LocationSummary* summary = new(zone) LocationSummary( | 4073 LocationSummary* summary = new (zone) |
4101 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4074 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4102 summary->set_in(0, Location::RequiresFpuRegister()); | 4075 summary->set_in(0, Location::RequiresFpuRegister()); |
4103 summary->set_in(1, Location::RequiresFpuRegister()); | 4076 summary->set_in(1, Location::RequiresFpuRegister()); |
4104 summary->set_out(0, Location::RequiresFpuRegister()); | 4077 summary->set_out(0, Location::RequiresFpuRegister()); |
4105 return summary; | 4078 return summary; |
4106 } | 4079 } |
4107 | 4080 |
4108 | 4081 |
4109 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4082 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4110 const VRegister left = locs()->in(0).fpu_reg(); | 4083 const VRegister left = locs()->in(0).fpu_reg(); |
4111 const VRegister right = locs()->in(1).fpu_reg(); | 4084 const VRegister right = locs()->in(1).fpu_reg(); |
4112 const VRegister result = locs()->out(0).fpu_reg(); | 4085 const VRegister result = locs()->out(0).fpu_reg(); |
4113 | 4086 |
4114 switch (op_kind()) { | 4087 switch (op_kind()) { |
4115 case MethodRecognizer::kFloat32x4Scale: | 4088 case MethodRecognizer::kFloat32x4Scale: |
4116 __ fcvtsd(VTMP, left); | 4089 __ fcvtsd(VTMP, left); |
4117 __ vdups(result, VTMP, 0); | 4090 __ vdups(result, VTMP, 0); |
4118 __ vmuls(result, result, right); | 4091 __ vmuls(result, result, right); |
4119 break; | 4092 break; |
4120 default: UNREACHABLE(); | 4093 default: |
| 4094 UNREACHABLE(); |
4121 } | 4095 } |
4122 } | 4096 } |
4123 | 4097 |
4124 | 4098 |
4125 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4099 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, |
4126 bool opt) const { | 4100 bool opt) const { |
4127 const intptr_t kNumInputs = 1; | 4101 const intptr_t kNumInputs = 1; |
4128 const intptr_t kNumTemps = 0; | 4102 const intptr_t kNumTemps = 0; |
4129 LocationSummary* summary = new LocationSummary( | 4103 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
4130 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4104 LocationSummary::kNoCall); |
4131 summary->set_in(0, Location::RequiresFpuRegister()); | 4105 summary->set_in(0, Location::RequiresFpuRegister()); |
4132 summary->set_out(0, Location::RequiresFpuRegister()); | 4106 summary->set_out(0, Location::RequiresFpuRegister()); |
4133 return summary; | 4107 return summary; |
4134 } | 4108 } |
4135 | 4109 |
4136 | 4110 |
4137 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4111 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4138 const VRegister left = locs()->in(0).fpu_reg(); | 4112 const VRegister left = locs()->in(0).fpu_reg(); |
4139 const VRegister result = locs()->out(0).fpu_reg(); | 4113 const VRegister result = locs()->out(0).fpu_reg(); |
4140 | 4114 |
4141 switch (op_kind()) { | 4115 switch (op_kind()) { |
4142 case MethodRecognizer::kFloat32x4Negate: | 4116 case MethodRecognizer::kFloat32x4Negate: |
4143 __ vnegs(result, left); | 4117 __ vnegs(result, left); |
4144 break; | 4118 break; |
4145 case MethodRecognizer::kFloat32x4Absolute: | 4119 case MethodRecognizer::kFloat32x4Absolute: |
4146 __ vabss(result, left); | 4120 __ vabss(result, left); |
4147 break; | 4121 break; |
4148 default: UNREACHABLE(); | 4122 default: |
| 4123 UNREACHABLE(); |
4149 } | 4124 } |
4150 } | 4125 } |
4151 | 4126 |
4152 | 4127 |
4153 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, | 4128 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, |
4154 bool opt) const { | 4129 bool opt) const { |
4155 const intptr_t kNumInputs = 3; | 4130 const intptr_t kNumInputs = 3; |
4156 const intptr_t kNumTemps = 0; | 4131 const intptr_t kNumTemps = 0; |
4157 LocationSummary* summary = new(zone) LocationSummary( | 4132 LocationSummary* summary = new (zone) |
4158 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4133 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4159 summary->set_in(0, Location::RequiresFpuRegister()); | 4134 summary->set_in(0, Location::RequiresFpuRegister()); |
4160 summary->set_in(1, Location::RequiresFpuRegister()); | 4135 summary->set_in(1, Location::RequiresFpuRegister()); |
4161 summary->set_in(2, Location::RequiresFpuRegister()); | 4136 summary->set_in(2, Location::RequiresFpuRegister()); |
4162 summary->set_out(0, Location::RequiresFpuRegister()); | 4137 summary->set_out(0, Location::RequiresFpuRegister()); |
4163 return summary; | 4138 return summary; |
4164 } | 4139 } |
4165 | 4140 |
4166 | 4141 |
4167 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4142 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4168 const VRegister left = locs()->in(0).fpu_reg(); | 4143 const VRegister left = locs()->in(0).fpu_reg(); |
4169 const VRegister lower = locs()->in(1).fpu_reg(); | 4144 const VRegister lower = locs()->in(1).fpu_reg(); |
4170 const VRegister upper = locs()->in(2).fpu_reg(); | 4145 const VRegister upper = locs()->in(2).fpu_reg(); |
4171 const VRegister result = locs()->out(0).fpu_reg(); | 4146 const VRegister result = locs()->out(0).fpu_reg(); |
4172 __ vmins(result, left, upper); | 4147 __ vmins(result, left, upper); |
4173 __ vmaxs(result, result, lower); | 4148 __ vmaxs(result, result, lower); |
4174 } | 4149 } |
4175 | 4150 |
4176 | 4151 |
4177 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, | 4152 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, |
4178 bool opt) const { | 4153 bool opt) const { |
4179 const intptr_t kNumInputs = 2; | 4154 const intptr_t kNumInputs = 2; |
4180 const intptr_t kNumTemps = 0; | 4155 const intptr_t kNumTemps = 0; |
4181 LocationSummary* summary = new LocationSummary( | 4156 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
4182 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4157 LocationSummary::kNoCall); |
4183 summary->set_in(0, Location::RequiresFpuRegister()); | 4158 summary->set_in(0, Location::RequiresFpuRegister()); |
4184 summary->set_in(1, Location::RequiresFpuRegister()); | 4159 summary->set_in(1, Location::RequiresFpuRegister()); |
4185 summary->set_out(0, Location::RequiresFpuRegister()); | 4160 summary->set_out(0, Location::RequiresFpuRegister()); |
4186 return summary; | 4161 return summary; |
4187 } | 4162 } |
4188 | 4163 |
4189 | 4164 |
4190 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4165 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4191 const VRegister replacement = locs()->in(0).fpu_reg(); | 4166 const VRegister replacement = locs()->in(0).fpu_reg(); |
4192 const VRegister value = locs()->in(1).fpu_reg(); | 4167 const VRegister value = locs()->in(1).fpu_reg(); |
(...skipping 10 matching lines...) Expand all Loading... |
4203 break; | 4178 break; |
4204 case MethodRecognizer::kFloat32x4WithY: | 4179 case MethodRecognizer::kFloat32x4WithY: |
4205 __ vinss(result, 1, VTMP, 0); | 4180 __ vinss(result, 1, VTMP, 0); |
4206 break; | 4181 break; |
4207 case MethodRecognizer::kFloat32x4WithZ: | 4182 case MethodRecognizer::kFloat32x4WithZ: |
4208 __ vinss(result, 2, VTMP, 0); | 4183 __ vinss(result, 2, VTMP, 0); |
4209 break; | 4184 break; |
4210 case MethodRecognizer::kFloat32x4WithW: | 4185 case MethodRecognizer::kFloat32x4WithW: |
4211 __ vinss(result, 3, VTMP, 0); | 4186 __ vinss(result, 3, VTMP, 0); |
4212 break; | 4187 break; |
4213 default: UNREACHABLE(); | 4188 default: |
| 4189 UNREACHABLE(); |
4214 } | 4190 } |
4215 } | 4191 } |
4216 | 4192 |
4217 | 4193 |
4218 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, | 4194 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, |
4219 bool opt) const { | 4195 bool opt) const { |
4220 const intptr_t kNumInputs = 1; | 4196 const intptr_t kNumInputs = 1; |
4221 const intptr_t kNumTemps = 0; | 4197 const intptr_t kNumTemps = 0; |
4222 LocationSummary* summary = new LocationSummary( | 4198 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
4223 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4199 LocationSummary::kNoCall); |
4224 summary->set_in(0, Location::RequiresFpuRegister()); | 4200 summary->set_in(0, Location::RequiresFpuRegister()); |
4225 summary->set_out(0, Location::RequiresFpuRegister()); | 4201 summary->set_out(0, Location::RequiresFpuRegister()); |
4226 return summary; | 4202 return summary; |
4227 } | 4203 } |
4228 | 4204 |
4229 | 4205 |
4230 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4206 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4231 const VRegister value = locs()->in(0).fpu_reg(); | 4207 const VRegister value = locs()->in(0).fpu_reg(); |
4232 const VRegister result = locs()->out(0).fpu_reg(); | 4208 const VRegister result = locs()->out(0).fpu_reg(); |
4233 | 4209 |
4234 if (value != result) { | 4210 if (value != result) { |
4235 __ vmov(result, value); | 4211 __ vmov(result, value); |
4236 } | 4212 } |
4237 } | 4213 } |
4238 | 4214 |
4239 | 4215 |
4240 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 4216 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |
4241 bool opt) const { | 4217 bool opt) const { |
4242 const intptr_t kNumInputs = 1; | 4218 const intptr_t kNumInputs = 1; |
4243 const intptr_t kNumTemps = 0; | 4219 const intptr_t kNumTemps = 0; |
4244 LocationSummary* summary = new(zone) LocationSummary( | 4220 LocationSummary* summary = new (zone) |
4245 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4221 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4246 summary->set_in(0, Location::RequiresFpuRegister()); | 4222 summary->set_in(0, Location::RequiresFpuRegister()); |
4247 summary->set_out(0, Location::RequiresFpuRegister()); | 4223 summary->set_out(0, Location::RequiresFpuRegister()); |
4248 return summary; | 4224 return summary; |
4249 } | 4225 } |
4250 | 4226 |
4251 | 4227 |
4252 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4228 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4253 const VRegister value = locs()->in(0).fpu_reg(); | 4229 const VRegister value = locs()->in(0).fpu_reg(); |
4254 const VRegister result = locs()->out(0).fpu_reg(); | 4230 const VRegister result = locs()->out(0).fpu_reg(); |
4255 | 4231 |
4256 switch (op_kind()) { | 4232 switch (op_kind()) { |
4257 case MethodRecognizer::kFloat64x2GetX: | 4233 case MethodRecognizer::kFloat64x2GetX: |
4258 __ vinsd(result, 0, value, 0); | 4234 __ vinsd(result, 0, value, 0); |
4259 break; | 4235 break; |
4260 case MethodRecognizer::kFloat64x2GetY: | 4236 case MethodRecognizer::kFloat64x2GetY: |
4261 __ vinsd(result, 0, value, 1); | 4237 __ vinsd(result, 0, value, 1); |
4262 break; | 4238 break; |
4263 default: UNREACHABLE(); | 4239 default: |
| 4240 UNREACHABLE(); |
4264 } | 4241 } |
4265 } | 4242 } |
4266 | 4243 |
4267 | 4244 |
4268 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 4245 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |
4269 bool opt) const { | 4246 bool opt) const { |
4270 const intptr_t kNumInputs = 0; | 4247 const intptr_t kNumInputs = 0; |
4271 const intptr_t kNumTemps = 0; | 4248 const intptr_t kNumTemps = 0; |
4272 LocationSummary* summary = new(zone) LocationSummary( | 4249 LocationSummary* summary = new (zone) |
4273 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4250 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4274 summary->set_out(0, Location::RequiresFpuRegister()); | 4251 summary->set_out(0, Location::RequiresFpuRegister()); |
4275 return summary; | 4252 return summary; |
4276 } | 4253 } |
4277 | 4254 |
4278 | 4255 |
4279 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4256 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4280 const VRegister v = locs()->out(0).fpu_reg(); | 4257 const VRegister v = locs()->out(0).fpu_reg(); |
4281 __ veor(v, v, v); | 4258 __ veor(v, v, v); |
4282 } | 4259 } |
4283 | 4260 |
4284 | 4261 |
4285 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 4262 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |
4286 bool opt) const { | 4263 bool opt) const { |
4287 const intptr_t kNumInputs = 1; | 4264 const intptr_t kNumInputs = 1; |
4288 const intptr_t kNumTemps = 0; | 4265 const intptr_t kNumTemps = 0; |
4289 LocationSummary* summary = new(zone) LocationSummary( | 4266 LocationSummary* summary = new (zone) |
4290 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4267 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4291 summary->set_in(0, Location::RequiresFpuRegister()); | 4268 summary->set_in(0, Location::RequiresFpuRegister()); |
4292 summary->set_out(0, Location::RequiresFpuRegister()); | 4269 summary->set_out(0, Location::RequiresFpuRegister()); |
4293 return summary; | 4270 return summary; |
4294 } | 4271 } |
4295 | 4272 |
4296 | 4273 |
4297 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4274 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4298 const VRegister value = locs()->in(0).fpu_reg(); | 4275 const VRegister value = locs()->in(0).fpu_reg(); |
4299 const VRegister result = locs()->out(0).fpu_reg(); | 4276 const VRegister result = locs()->out(0).fpu_reg(); |
4300 __ vdupd(result, value, 0); | 4277 __ vdupd(result, value, 0); |
4301 } | 4278 } |
4302 | 4279 |
4303 | 4280 |
4304 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 4281 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
4305 Zone* zone, bool opt) const { | 4282 Zone* zone, |
| 4283 bool opt) const { |
4306 const intptr_t kNumInputs = 2; | 4284 const intptr_t kNumInputs = 2; |
4307 const intptr_t kNumTemps = 0; | 4285 const intptr_t kNumTemps = 0; |
4308 LocationSummary* summary = new(zone) LocationSummary( | 4286 LocationSummary* summary = new (zone) |
4309 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4287 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4310 summary->set_in(0, Location::RequiresFpuRegister()); | 4288 summary->set_in(0, Location::RequiresFpuRegister()); |
4311 summary->set_in(1, Location::RequiresFpuRegister()); | 4289 summary->set_in(1, Location::RequiresFpuRegister()); |
4312 summary->set_out(0, Location::RequiresFpuRegister()); | 4290 summary->set_out(0, Location::RequiresFpuRegister()); |
4313 return summary; | 4291 return summary; |
4314 } | 4292 } |
4315 | 4293 |
4316 | 4294 |
4317 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4295 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4318 const VRegister v0 = locs()->in(0).fpu_reg(); | 4296 const VRegister v0 = locs()->in(0).fpu_reg(); |
4319 const VRegister v1 = locs()->in(1).fpu_reg(); | 4297 const VRegister v1 = locs()->in(1).fpu_reg(); |
4320 const VRegister r = locs()->out(0).fpu_reg(); | 4298 const VRegister r = locs()->out(0).fpu_reg(); |
4321 __ vinsd(r, 0, v0, 0); | 4299 __ vinsd(r, 0, v0, 0); |
4322 __ vinsd(r, 1, v1, 0); | 4300 __ vinsd(r, 1, v1, 0); |
4323 } | 4301 } |
4324 | 4302 |
4325 | 4303 |
4326 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 4304 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
4327 Zone* zone, bool opt) const { | 4305 Zone* zone, |
| 4306 bool opt) const { |
4328 const intptr_t kNumInputs = 1; | 4307 const intptr_t kNumInputs = 1; |
4329 const intptr_t kNumTemps = 0; | 4308 const intptr_t kNumTemps = 0; |
4330 LocationSummary* summary = new LocationSummary( | 4309 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
4331 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4310 LocationSummary::kNoCall); |
4332 summary->set_in(0, Location::RequiresFpuRegister()); | 4311 summary->set_in(0, Location::RequiresFpuRegister()); |
4333 summary->set_out(0, Location::RequiresFpuRegister()); | 4312 summary->set_out(0, Location::RequiresFpuRegister()); |
4334 return summary; | 4313 return summary; |
4335 } | 4314 } |
4336 | 4315 |
4337 | 4316 |
4338 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4317 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4339 const VRegister q = locs()->in(0).fpu_reg(); | 4318 const VRegister q = locs()->in(0).fpu_reg(); |
4340 const VRegister r = locs()->out(0).fpu_reg(); | 4319 const VRegister r = locs()->out(0).fpu_reg(); |
4341 | 4320 |
4342 // Zero register. | 4321 // Zero register. |
4343 __ veor(r, r, r); | 4322 __ veor(r, r, r); |
4344 // Set X lane. | 4323 // Set X lane. |
4345 __ vinsd(VTMP, 0, q, 0); | 4324 __ vinsd(VTMP, 0, q, 0); |
4346 __ fcvtsd(VTMP, VTMP); | 4325 __ fcvtsd(VTMP, VTMP); |
4347 __ vinss(r, 0, VTMP, 0); | 4326 __ vinss(r, 0, VTMP, 0); |
4348 // Set Y lane. | 4327 // Set Y lane. |
4349 __ vinsd(VTMP, 0, q, 1); | 4328 __ vinsd(VTMP, 0, q, 1); |
4350 __ fcvtsd(VTMP, VTMP); | 4329 __ fcvtsd(VTMP, VTMP); |
4351 __ vinss(r, 1, VTMP, 0); | 4330 __ vinss(r, 1, VTMP, 0); |
4352 } | 4331 } |
4353 | 4332 |
4354 | 4333 |
4355 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 4334 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
4356 Zone* zone, bool opt) const { | 4335 Zone* zone, |
| 4336 bool opt) const { |
4357 const intptr_t kNumInputs = 1; | 4337 const intptr_t kNumInputs = 1; |
4358 const intptr_t kNumTemps = 0; | 4338 const intptr_t kNumTemps = 0; |
4359 LocationSummary* summary = new LocationSummary( | 4339 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
4360 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4340 LocationSummary::kNoCall); |
4361 summary->set_in(0, Location::RequiresFpuRegister()); | 4341 summary->set_in(0, Location::RequiresFpuRegister()); |
4362 summary->set_out(0, Location::RequiresFpuRegister()); | 4342 summary->set_out(0, Location::RequiresFpuRegister()); |
4363 return summary; | 4343 return summary; |
4364 } | 4344 } |
4365 | 4345 |
4366 | 4346 |
4367 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4347 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4368 const VRegister q = locs()->in(0).fpu_reg(); | 4348 const VRegister q = locs()->in(0).fpu_reg(); |
4369 const VRegister r = locs()->out(0).fpu_reg(); | 4349 const VRegister r = locs()->out(0).fpu_reg(); |
4370 | 4350 |
4371 // Set X. | 4351 // Set X. |
4372 __ vinss(VTMP, 0, q, 0); | 4352 __ vinss(VTMP, 0, q, 0); |
4373 __ fcvtds(VTMP, VTMP); | 4353 __ fcvtds(VTMP, VTMP); |
4374 __ vinsd(r, 0, VTMP, 0); | 4354 __ vinsd(r, 0, VTMP, 0); |
4375 // Set Y. | 4355 // Set Y. |
4376 __ vinss(VTMP, 0, q, 1); | 4356 __ vinss(VTMP, 0, q, 1); |
4377 __ fcvtds(VTMP, VTMP); | 4357 __ fcvtds(VTMP, VTMP); |
4378 __ vinsd(r, 1, VTMP, 0); | 4358 __ vinsd(r, 1, VTMP, 0); |
4379 } | 4359 } |
4380 | 4360 |
4381 | 4361 |
4382 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4362 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, |
4383 bool opt) const { | 4363 bool opt) const { |
4384 const intptr_t kNumInputs = 1; | 4364 const intptr_t kNumInputs = 1; |
4385 const intptr_t kNumTemps = 0; | 4365 const intptr_t kNumTemps = 0; |
4386 LocationSummary* summary = new(zone) LocationSummary( | 4366 LocationSummary* summary = new (zone) |
4387 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4367 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4388 | 4368 |
4389 if (representation() == kTagged) { | 4369 if (representation() == kTagged) { |
4390 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 4370 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |
4391 summary->set_in(0, Location::RequiresFpuRegister()); | 4371 summary->set_in(0, Location::RequiresFpuRegister()); |
4392 summary->set_out(0, Location::RequiresRegister()); | 4372 summary->set_out(0, Location::RequiresRegister()); |
4393 } else { | 4373 } else { |
4394 summary->set_in(0, Location::RequiresFpuRegister()); | 4374 summary->set_in(0, Location::RequiresFpuRegister()); |
4395 summary->set_out(0, Location::RequiresFpuRegister()); | 4375 summary->set_out(0, Location::RequiresFpuRegister()); |
4396 } | 4376 } |
4397 return summary; | 4377 return summary; |
(...skipping 23 matching lines...) Expand all Loading... |
4421 switch (op_kind()) { | 4401 switch (op_kind()) { |
4422 case MethodRecognizer::kFloat64x2Negate: | 4402 case MethodRecognizer::kFloat64x2Negate: |
4423 __ vnegd(result, value); | 4403 __ vnegd(result, value); |
4424 break; | 4404 break; |
4425 case MethodRecognizer::kFloat64x2Abs: | 4405 case MethodRecognizer::kFloat64x2Abs: |
4426 __ vabsd(result, value); | 4406 __ vabsd(result, value); |
4427 break; | 4407 break; |
4428 case MethodRecognizer::kFloat64x2Sqrt: | 4408 case MethodRecognizer::kFloat64x2Sqrt: |
4429 __ vsqrtd(result, value); | 4409 __ vsqrtd(result, value); |
4430 break; | 4410 break; |
4431 default: UNREACHABLE(); | 4411 default: |
| 4412 UNREACHABLE(); |
4432 } | 4413 } |
4433 } | 4414 } |
4434 | 4415 |
4435 | 4416 |
4436 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, | 4417 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, |
4437 bool opt) const { | 4418 bool opt) const { |
4438 const intptr_t kNumInputs = 2; | 4419 const intptr_t kNumInputs = 2; |
4439 const intptr_t kNumTemps = 0; | 4420 const intptr_t kNumTemps = 0; |
4440 LocationSummary* summary = new LocationSummary( | 4421 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
4441 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4422 LocationSummary::kNoCall); |
4442 summary->set_in(0, Location::RequiresFpuRegister()); | 4423 summary->set_in(0, Location::RequiresFpuRegister()); |
4443 summary->set_in(1, Location::RequiresFpuRegister()); | 4424 summary->set_in(1, Location::RequiresFpuRegister()); |
4444 summary->set_out(0, Location::SameAsFirstInput()); | 4425 summary->set_out(0, Location::SameAsFirstInput()); |
4445 return summary; | 4426 return summary; |
4446 } | 4427 } |
4447 | 4428 |
4448 | 4429 |
4449 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4430 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4450 const VRegister left = locs()->in(0).fpu_reg(); | 4431 const VRegister left = locs()->in(0).fpu_reg(); |
4451 const VRegister right = locs()->in(1).fpu_reg(); | 4432 const VRegister right = locs()->in(1).fpu_reg(); |
(...skipping 10 matching lines...) Expand all Loading... |
4462 break; | 4443 break; |
4463 case MethodRecognizer::kFloat64x2WithY: | 4444 case MethodRecognizer::kFloat64x2WithY: |
4464 __ vinsd(out, 1, right, 0); | 4445 __ vinsd(out, 1, right, 0); |
4465 break; | 4446 break; |
4466 case MethodRecognizer::kFloat64x2Min: | 4447 case MethodRecognizer::kFloat64x2Min: |
4467 __ vmind(out, left, right); | 4448 __ vmind(out, left, right); |
4468 break; | 4449 break; |
4469 case MethodRecognizer::kFloat64x2Max: | 4450 case MethodRecognizer::kFloat64x2Max: |
4470 __ vmaxd(out, left, right); | 4451 __ vmaxd(out, left, right); |
4471 break; | 4452 break; |
4472 default: UNREACHABLE(); | 4453 default: |
| 4454 UNREACHABLE(); |
4473 } | 4455 } |
4474 } | 4456 } |
4475 | 4457 |
4476 | 4458 |
4477 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary( | 4459 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, |
4478 Zone* zone, bool opt) const { | 4460 bool opt) const { |
4479 const intptr_t kNumInputs = 4; | 4461 const intptr_t kNumInputs = 4; |
4480 const intptr_t kNumTemps = 0; | 4462 const intptr_t kNumTemps = 0; |
4481 LocationSummary* summary = new(zone) LocationSummary( | 4463 LocationSummary* summary = new (zone) |
4482 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4464 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4483 summary->set_in(0, Location::RequiresRegister()); | 4465 summary->set_in(0, Location::RequiresRegister()); |
4484 summary->set_in(1, Location::RequiresRegister()); | 4466 summary->set_in(1, Location::RequiresRegister()); |
4485 summary->set_in(2, Location::RequiresRegister()); | 4467 summary->set_in(2, Location::RequiresRegister()); |
4486 summary->set_in(3, Location::RequiresRegister()); | 4468 summary->set_in(3, Location::RequiresRegister()); |
4487 summary->set_out(0, Location::RequiresFpuRegister()); | 4469 summary->set_out(0, Location::RequiresFpuRegister()); |
4488 return summary; | 4470 return summary; |
4489 } | 4471 } |
4490 | 4472 |
4491 | 4473 |
4492 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4474 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4493 const Register v0 = locs()->in(0).reg(); | 4475 const Register v0 = locs()->in(0).reg(); |
4494 const Register v1 = locs()->in(1).reg(); | 4476 const Register v1 = locs()->in(1).reg(); |
4495 const Register v2 = locs()->in(2).reg(); | 4477 const Register v2 = locs()->in(2).reg(); |
4496 const Register v3 = locs()->in(3).reg(); | 4478 const Register v3 = locs()->in(3).reg(); |
4497 const VRegister result = locs()->out(0).fpu_reg(); | 4479 const VRegister result = locs()->out(0).fpu_reg(); |
4498 __ veor(result, result, result); | 4480 __ veor(result, result, result); |
4499 __ vinsw(result, 0, v0); | 4481 __ vinsw(result, 0, v0); |
4500 __ vinsw(result, 1, v1); | 4482 __ vinsw(result, 1, v1); |
4501 __ vinsw(result, 2, v2); | 4483 __ vinsw(result, 2, v2); |
4502 __ vinsw(result, 3, v3); | 4484 __ vinsw(result, 3, v3); |
4503 } | 4485 } |
4504 | 4486 |
4505 | 4487 |
4506 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 4488 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
4507 Zone* zone, bool opt) const { | 4489 Zone* zone, |
| 4490 bool opt) const { |
4508 const intptr_t kNumInputs = 4; | 4491 const intptr_t kNumInputs = 4; |
4509 const intptr_t kNumTemps = 1; | 4492 const intptr_t kNumTemps = 1; |
4510 LocationSummary* summary = new LocationSummary( | 4493 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
4511 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4494 LocationSummary::kNoCall); |
4512 summary->set_in(0, Location::RequiresRegister()); | 4495 summary->set_in(0, Location::RequiresRegister()); |
4513 summary->set_in(1, Location::RequiresRegister()); | 4496 summary->set_in(1, Location::RequiresRegister()); |
4514 summary->set_in(2, Location::RequiresRegister()); | 4497 summary->set_in(2, Location::RequiresRegister()); |
4515 summary->set_in(3, Location::RequiresRegister()); | 4498 summary->set_in(3, Location::RequiresRegister()); |
4516 summary->set_temp(0, Location::RequiresRegister()); | 4499 summary->set_temp(0, Location::RequiresRegister()); |
4517 summary->set_out(0, Location::RequiresFpuRegister()); | 4500 summary->set_out(0, Location::RequiresFpuRegister()); |
4518 return summary; | 4501 return summary; |
4519 } | 4502 } |
4520 | 4503 |
4521 | 4504 |
(...skipping 28 matching lines...) Expand all Loading... |
4550 __ CompareRegisters(v3, TMP2); | 4533 __ CompareRegisters(v3, TMP2); |
4551 __ csel(TMP, temp, ZR, EQ); | 4534 __ csel(TMP, temp, ZR, EQ); |
4552 __ vinsw(result, 3, TMP); | 4535 __ vinsw(result, 3, TMP); |
4553 } | 4536 } |
4554 | 4537 |
4555 | 4538 |
4556 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, | 4539 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, |
4557 bool opt) const { | 4540 bool opt) const { |
4558 const intptr_t kNumInputs = 1; | 4541 const intptr_t kNumInputs = 1; |
4559 const intptr_t kNumTemps = 0; | 4542 const intptr_t kNumTemps = 0; |
4560 LocationSummary* summary = new LocationSummary( | 4543 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
4561 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4544 LocationSummary::kNoCall); |
4562 summary->set_in(0, Location::RequiresFpuRegister()); | 4545 summary->set_in(0, Location::RequiresFpuRegister()); |
4563 summary->set_out(0, Location::RequiresRegister()); | 4546 summary->set_out(0, Location::RequiresRegister()); |
4564 return summary; | 4547 return summary; |
4565 } | 4548 } |
4566 | 4549 |
4567 | 4550 |
4568 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4551 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4569 const VRegister value = locs()->in(0).fpu_reg(); | 4552 const VRegister value = locs()->in(0).fpu_reg(); |
4570 const Register result = locs()->out(0).reg(); | 4553 const Register result = locs()->out(0).reg(); |
4571 | 4554 |
4572 switch (op_kind()) { | 4555 switch (op_kind()) { |
4573 case MethodRecognizer::kInt32x4GetFlagX: | 4556 case MethodRecognizer::kInt32x4GetFlagX: |
4574 __ vmovrs(result, value, 0); | 4557 __ vmovrs(result, value, 0); |
4575 break; | 4558 break; |
4576 case MethodRecognizer::kInt32x4GetFlagY: | 4559 case MethodRecognizer::kInt32x4GetFlagY: |
4577 __ vmovrs(result, value, 1); | 4560 __ vmovrs(result, value, 1); |
4578 break; | 4561 break; |
4579 case MethodRecognizer::kInt32x4GetFlagZ: | 4562 case MethodRecognizer::kInt32x4GetFlagZ: |
4580 __ vmovrs(result, value, 2); | 4563 __ vmovrs(result, value, 2); |
4581 break; | 4564 break; |
4582 case MethodRecognizer::kInt32x4GetFlagW: | 4565 case MethodRecognizer::kInt32x4GetFlagW: |
4583 __ vmovrs(result, value, 3); | 4566 __ vmovrs(result, value, 3); |
4584 break; | 4567 break; |
4585 default: UNREACHABLE(); | 4568 default: |
| 4569 UNREACHABLE(); |
4586 } | 4570 } |
4587 | 4571 |
4588 __ tst(result, Operand(result)); | 4572 __ tst(result, Operand(result)); |
4589 __ LoadObject(result, Bool::True()); | 4573 __ LoadObject(result, Bool::True()); |
4590 __ LoadObject(TMP, Bool::False()); | 4574 __ LoadObject(TMP, Bool::False()); |
4591 __ csel(result, TMP, result, EQ); | 4575 __ csel(result, TMP, result, EQ); |
4592 } | 4576 } |
4593 | 4577 |
4594 | 4578 |
4595 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, | 4579 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, |
4596 bool opt) const { | 4580 bool opt) const { |
4597 const intptr_t kNumInputs = 3; | 4581 const intptr_t kNumInputs = 3; |
4598 const intptr_t kNumTemps = 1; | 4582 const intptr_t kNumTemps = 1; |
4599 LocationSummary* summary = new LocationSummary( | 4583 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
4600 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4584 LocationSummary::kNoCall); |
4601 summary->set_in(0, Location::RequiresFpuRegister()); | 4585 summary->set_in(0, Location::RequiresFpuRegister()); |
4602 summary->set_in(1, Location::RequiresFpuRegister()); | 4586 summary->set_in(1, Location::RequiresFpuRegister()); |
4603 summary->set_in(2, Location::RequiresFpuRegister()); | 4587 summary->set_in(2, Location::RequiresFpuRegister()); |
4604 summary->set_temp(0, Location::RequiresFpuRegister()); | 4588 summary->set_temp(0, Location::RequiresFpuRegister()); |
4605 summary->set_out(0, Location::RequiresFpuRegister()); | 4589 summary->set_out(0, Location::RequiresFpuRegister()); |
4606 return summary; | 4590 return summary; |
4607 } | 4591 } |
4608 | 4592 |
4609 | 4593 |
4610 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4594 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(...skipping 13 matching lines...) Expand all Loading... |
4624 __ vand(temp, temp, falseValue); | 4608 __ vand(temp, temp, falseValue); |
4625 // out = mask | temp. | 4609 // out = mask | temp. |
4626 __ vorr(out, mask, temp); | 4610 __ vorr(out, mask, temp); |
4627 } | 4611 } |
4628 | 4612 |
4629 | 4613 |
4630 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, | 4614 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, |
4631 bool opt) const { | 4615 bool opt) const { |
4632 const intptr_t kNumInputs = 2; | 4616 const intptr_t kNumInputs = 2; |
4633 const intptr_t kNumTemps = 0; | 4617 const intptr_t kNumTemps = 0; |
4634 LocationSummary* summary = new LocationSummary( | 4618 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
4635 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4619 LocationSummary::kNoCall); |
4636 summary->set_in(0, Location::RequiresFpuRegister()); | 4620 summary->set_in(0, Location::RequiresFpuRegister()); |
4637 summary->set_in(1, Location::RequiresRegister()); | 4621 summary->set_in(1, Location::RequiresRegister()); |
4638 summary->set_out(0, Location::RequiresFpuRegister()); | 4622 summary->set_out(0, Location::RequiresFpuRegister()); |
4639 return summary; | 4623 return summary; |
4640 } | 4624 } |
4641 | 4625 |
4642 | 4626 |
4643 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4627 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4644 const VRegister mask = locs()->in(0).fpu_reg(); | 4628 const VRegister mask = locs()->in(0).fpu_reg(); |
4645 const Register flag = locs()->in(1).reg(); | 4629 const Register flag = locs()->in(1).reg(); |
(...skipping 12 matching lines...) Expand all Loading... |
4658 break; | 4642 break; |
4659 case MethodRecognizer::kInt32x4WithFlagY: | 4643 case MethodRecognizer::kInt32x4WithFlagY: |
4660 __ vinsw(result, 1, TMP); | 4644 __ vinsw(result, 1, TMP); |
4661 break; | 4645 break; |
4662 case MethodRecognizer::kInt32x4WithFlagZ: | 4646 case MethodRecognizer::kInt32x4WithFlagZ: |
4663 __ vinsw(result, 2, TMP); | 4647 __ vinsw(result, 2, TMP); |
4664 break; | 4648 break; |
4665 case MethodRecognizer::kInt32x4WithFlagW: | 4649 case MethodRecognizer::kInt32x4WithFlagW: |
4666 __ vinsw(result, 3, TMP); | 4650 __ vinsw(result, 3, TMP); |
4667 break; | 4651 break; |
4668 default: UNREACHABLE(); | 4652 default: |
| 4653 UNREACHABLE(); |
4669 } | 4654 } |
4670 } | 4655 } |
4671 | 4656 |
4672 | 4657 |
4673 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, | 4658 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, |
4674 bool opt) const { | 4659 bool opt) const { |
4675 const intptr_t kNumInputs = 1; | 4660 const intptr_t kNumInputs = 1; |
4676 const intptr_t kNumTemps = 0; | 4661 const intptr_t kNumTemps = 0; |
4677 LocationSummary* summary = new LocationSummary( | 4662 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
4678 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4663 LocationSummary::kNoCall); |
4679 summary->set_in(0, Location::RequiresFpuRegister()); | 4664 summary->set_in(0, Location::RequiresFpuRegister()); |
4680 summary->set_out(0, Location::RequiresFpuRegister()); | 4665 summary->set_out(0, Location::RequiresFpuRegister()); |
4681 return summary; | 4666 return summary; |
4682 } | 4667 } |
4683 | 4668 |
4684 | 4669 |
4685 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4670 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4686 const VRegister value = locs()->in(0).fpu_reg(); | 4671 const VRegister value = locs()->in(0).fpu_reg(); |
4687 const VRegister result = locs()->out(0).fpu_reg(); | 4672 const VRegister result = locs()->out(0).fpu_reg(); |
4688 | 4673 |
4689 if (value != result) { | 4674 if (value != result) { |
4690 __ vmov(result, value); | 4675 __ vmov(result, value); |
4691 } | 4676 } |
4692 } | 4677 } |
4693 | 4678 |
4694 | 4679 |
4695 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, | 4680 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, |
4696 bool opt) const { | 4681 bool opt) const { |
4697 const intptr_t kNumInputs = 2; | 4682 const intptr_t kNumInputs = 2; |
4698 const intptr_t kNumTemps = 0; | 4683 const intptr_t kNumTemps = 0; |
4699 LocationSummary* summary = new LocationSummary( | 4684 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
4700 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4685 LocationSummary::kNoCall); |
4701 summary->set_in(0, Location::RequiresFpuRegister()); | 4686 summary->set_in(0, Location::RequiresFpuRegister()); |
4702 summary->set_in(1, Location::RequiresFpuRegister()); | 4687 summary->set_in(1, Location::RequiresFpuRegister()); |
4703 summary->set_out(0, Location::RequiresFpuRegister()); | 4688 summary->set_out(0, Location::RequiresFpuRegister()); |
4704 return summary; | 4689 return summary; |
4705 } | 4690 } |
4706 | 4691 |
4707 | 4692 |
4708 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4693 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4709 const VRegister left = locs()->in(0).fpu_reg(); | 4694 const VRegister left = locs()->in(0).fpu_reg(); |
4710 const VRegister right = locs()->in(1).fpu_reg(); | 4695 const VRegister right = locs()->in(1).fpu_reg(); |
4711 const VRegister result = locs()->out(0).fpu_reg(); | 4696 const VRegister result = locs()->out(0).fpu_reg(); |
4712 switch (op_kind()) { | 4697 switch (op_kind()) { |
4713 case Token::kBIT_AND: __ vand(result, left, right); break; | 4698 case Token::kBIT_AND: |
4714 case Token::kBIT_OR: __ vorr(result, left, right); break; | 4699 __ vand(result, left, right); |
4715 case Token::kBIT_XOR: __ veor(result, left, right); break; | 4700 break; |
4716 case Token::kADD: __ vaddw(result, left, right); break; | 4701 case Token::kBIT_OR: |
4717 case Token::kSUB: __ vsubw(result, left, right); break; | 4702 __ vorr(result, left, right); |
4718 default: UNREACHABLE(); | 4703 break; |
| 4704 case Token::kBIT_XOR: |
| 4705 __ veor(result, left, right); |
| 4706 break; |
| 4707 case Token::kADD: |
| 4708 __ vaddw(result, left, right); |
| 4709 break; |
| 4710 case Token::kSUB: |
| 4711 __ vsubw(result, left, right); |
| 4712 break; |
| 4713 default: |
| 4714 UNREACHABLE(); |
4719 } | 4715 } |
4720 } | 4716 } |
4721 | 4717 |
4722 | 4718 |
4723 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 4719 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |
4724 bool opt) const { | 4720 bool opt) const { |
4725 ASSERT((kind() == MathUnaryInstr::kSqrt) || | 4721 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
4726 (kind() == MathUnaryInstr::kDoubleSquare)); | 4722 (kind() == MathUnaryInstr::kDoubleSquare)); |
4727 const intptr_t kNumInputs = 1; | 4723 const intptr_t kNumInputs = 1; |
4728 const intptr_t kNumTemps = 0; | 4724 const intptr_t kNumTemps = 0; |
4729 LocationSummary* summary = new(zone) LocationSummary( | 4725 LocationSummary* summary = new (zone) |
4730 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4726 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4731 summary->set_in(0, Location::RequiresFpuRegister()); | 4727 summary->set_in(0, Location::RequiresFpuRegister()); |
4732 summary->set_out(0, Location::RequiresFpuRegister()); | 4728 summary->set_out(0, Location::RequiresFpuRegister()); |
4733 return summary; | 4729 return summary; |
4734 } | 4730 } |
4735 | 4731 |
4736 | 4732 |
4737 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4733 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4738 if (kind() == MathUnaryInstr::kSqrt) { | 4734 if (kind() == MathUnaryInstr::kSqrt) { |
4739 const VRegister val = locs()->in(0).fpu_reg(); | 4735 const VRegister val = locs()->in(0).fpu_reg(); |
4740 const VRegister result = locs()->out(0).fpu_reg(); | 4736 const VRegister result = locs()->out(0).fpu_reg(); |
4741 __ fsqrtd(result, val); | 4737 __ fsqrtd(result, val); |
4742 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 4738 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
4743 const VRegister val = locs()->in(0).fpu_reg(); | 4739 const VRegister val = locs()->in(0).fpu_reg(); |
4744 const VRegister result = locs()->out(0).fpu_reg(); | 4740 const VRegister result = locs()->out(0).fpu_reg(); |
4745 __ fmuld(result, val, val); | 4741 __ fmuld(result, val, val); |
4746 } else { | 4742 } else { |
4747 UNREACHABLE(); | 4743 UNREACHABLE(); |
4748 } | 4744 } |
4749 } | 4745 } |
4750 | 4746 |
4751 | 4747 |
4752 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 4748 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |
4753 Zone* zone, bool opt) const { | 4749 Zone* zone, |
| 4750 bool opt) const { |
4754 const intptr_t kNumTemps = 0; | 4751 const intptr_t kNumTemps = 0; |
4755 LocationSummary* summary = new(zone) LocationSummary( | 4752 LocationSummary* summary = new (zone) |
4756 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 4753 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
4757 summary->set_in(0, Location::RegisterLocation(R0)); | 4754 summary->set_in(0, Location::RegisterLocation(R0)); |
4758 summary->set_in(1, Location::RegisterLocation(R1)); | 4755 summary->set_in(1, Location::RegisterLocation(R1)); |
4759 summary->set_in(2, Location::RegisterLocation(R2)); | 4756 summary->set_in(2, Location::RegisterLocation(R2)); |
4760 summary->set_in(3, Location::RegisterLocation(R3)); | 4757 summary->set_in(3, Location::RegisterLocation(R3)); |
4761 summary->set_out(0, Location::RegisterLocation(R0)); | 4758 summary->set_out(0, Location::RegisterLocation(R0)); |
4762 return summary; | 4759 return summary; |
4763 } | 4760 } |
4764 | 4761 |
4765 | 4762 |
4766 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 4763 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |
4767 FlowGraphCompiler* compiler) { | 4764 FlowGraphCompiler* compiler) { |
4768 | |
4769 // Call the function. | 4765 // Call the function. |
4770 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 4766 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |
4771 } | 4767 } |
4772 | 4768 |
4773 | 4769 |
4774 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 4770 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |
4775 bool opt) const { | 4771 bool opt) const { |
4776 if (result_cid() == kDoubleCid) { | 4772 if (result_cid() == kDoubleCid) { |
4777 const intptr_t kNumInputs = 2; | 4773 const intptr_t kNumInputs = 2; |
4778 const intptr_t kNumTemps = 0; | 4774 const intptr_t kNumTemps = 0; |
4779 LocationSummary* summary = new(zone) LocationSummary( | 4775 LocationSummary* summary = new (zone) |
4780 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4776 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4781 summary->set_in(0, Location::RequiresFpuRegister()); | 4777 summary->set_in(0, Location::RequiresFpuRegister()); |
4782 summary->set_in(1, Location::RequiresFpuRegister()); | 4778 summary->set_in(1, Location::RequiresFpuRegister()); |
4783 // Reuse the left register so that code can be made shorter. | 4779 // Reuse the left register so that code can be made shorter. |
4784 summary->set_out(0, Location::SameAsFirstInput()); | 4780 summary->set_out(0, Location::SameAsFirstInput()); |
4785 return summary; | 4781 return summary; |
4786 } | 4782 } |
4787 ASSERT(result_cid() == kSmiCid); | 4783 ASSERT(result_cid() == kSmiCid); |
4788 const intptr_t kNumInputs = 2; | 4784 const intptr_t kNumInputs = 2; |
4789 const intptr_t kNumTemps = 0; | 4785 const intptr_t kNumTemps = 0; |
4790 LocationSummary* summary = new(zone) LocationSummary( | 4786 LocationSummary* summary = new (zone) |
4791 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4787 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4792 summary->set_in(0, Location::RequiresRegister()); | 4788 summary->set_in(0, Location::RequiresRegister()); |
4793 summary->set_in(1, Location::RequiresRegister()); | 4789 summary->set_in(1, Location::RequiresRegister()); |
4794 // Reuse the left register so that code can be made shorter. | 4790 // Reuse the left register so that code can be made shorter. |
4795 summary->set_out(0, Location::SameAsFirstInput()); | 4791 summary->set_out(0, Location::SameAsFirstInput()); |
4796 return summary; | 4792 return summary; |
4797 } | 4793 } |
4798 | 4794 |
4799 | 4795 |
4800 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4796 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4801 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 4797 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4854 } else { | 4850 } else { |
4855 __ csel(result, right, left, LT); | 4851 __ csel(result, right, left, LT); |
4856 } | 4852 } |
4857 } | 4853 } |
4858 | 4854 |
4859 | 4855 |
4860 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 4856 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |
4861 bool opt) const { | 4857 bool opt) const { |
4862 const intptr_t kNumInputs = 1; | 4858 const intptr_t kNumInputs = 1; |
4863 const intptr_t kNumTemps = 0; | 4859 const intptr_t kNumTemps = 0; |
4864 LocationSummary* summary = new(zone) LocationSummary( | 4860 LocationSummary* summary = new (zone) |
4865 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4861 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4866 summary->set_in(0, Location::RequiresRegister()); | 4862 summary->set_in(0, Location::RequiresRegister()); |
4867 // We make use of 3-operand instructions by not requiring result register | 4863 // We make use of 3-operand instructions by not requiring result register |
4868 // to be identical to first input register as on Intel. | 4864 // to be identical to first input register as on Intel. |
4869 summary->set_out(0, Location::RequiresRegister()); | 4865 summary->set_out(0, Location::RequiresRegister()); |
4870 return summary; | 4866 return summary; |
4871 } | 4867 } |
4872 | 4868 |
4873 | 4869 |
4874 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4870 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4875 const Register value = locs()->in(0).reg(); | 4871 const Register value = locs()->in(0).reg(); |
(...skipping 13 matching lines...) Expand all Loading... |
4889 default: | 4885 default: |
4890 UNREACHABLE(); | 4886 UNREACHABLE(); |
4891 } | 4887 } |
4892 } | 4888 } |
4893 | 4889 |
4894 | 4890 |
4895 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 4891 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
4896 bool opt) const { | 4892 bool opt) const { |
4897 const intptr_t kNumInputs = 1; | 4893 const intptr_t kNumInputs = 1; |
4898 const intptr_t kNumTemps = 0; | 4894 const intptr_t kNumTemps = 0; |
4899 LocationSummary* summary = new(zone) LocationSummary( | 4895 LocationSummary* summary = new (zone) |
4900 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4896 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4901 summary->set_in(0, Location::RequiresFpuRegister()); | 4897 summary->set_in(0, Location::RequiresFpuRegister()); |
4902 summary->set_out(0, Location::RequiresFpuRegister()); | 4898 summary->set_out(0, Location::RequiresFpuRegister()); |
4903 return summary; | 4899 return summary; |
4904 } | 4900 } |
4905 | 4901 |
4906 | 4902 |
4907 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4903 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4908 const VRegister result = locs()->out(0).fpu_reg(); | 4904 const VRegister result = locs()->out(0).fpu_reg(); |
4909 const VRegister value = locs()->in(0).fpu_reg(); | 4905 const VRegister value = locs()->in(0).fpu_reg(); |
4910 __ fnegd(result, value); | 4906 __ fnegd(result, value); |
4911 } | 4907 } |
4912 | 4908 |
4913 | 4909 |
4914 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 4910 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |
4915 bool opt) const { | 4911 bool opt) const { |
4916 const intptr_t kNumInputs = 1; | 4912 const intptr_t kNumInputs = 1; |
4917 const intptr_t kNumTemps = 0; | 4913 const intptr_t kNumTemps = 0; |
4918 LocationSummary* result = new(zone) LocationSummary( | 4914 LocationSummary* result = new (zone) |
4919 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4915 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4920 result->set_in(0, Location::RequiresRegister()); | 4916 result->set_in(0, Location::RequiresRegister()); |
4921 result->set_out(0, Location::RequiresFpuRegister()); | 4917 result->set_out(0, Location::RequiresFpuRegister()); |
4922 return result; | 4918 return result; |
4923 } | 4919 } |
4924 | 4920 |
4925 | 4921 |
4926 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4922 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4927 const Register value = locs()->in(0).reg(); | 4923 const Register value = locs()->in(0).reg(); |
4928 const VRegister result = locs()->out(0).fpu_reg(); | 4924 const VRegister result = locs()->out(0).fpu_reg(); |
4929 __ scvtfdw(result, value); | 4925 __ scvtfdw(result, value); |
4930 } | 4926 } |
4931 | 4927 |
4932 | 4928 |
4933 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 4929 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |
4934 bool opt) const { | 4930 bool opt) const { |
4935 const intptr_t kNumInputs = 1; | 4931 const intptr_t kNumInputs = 1; |
4936 const intptr_t kNumTemps = 0; | 4932 const intptr_t kNumTemps = 0; |
4937 LocationSummary* result = new(zone) LocationSummary( | 4933 LocationSummary* result = new (zone) |
4938 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4934 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4939 result->set_in(0, Location::RequiresRegister()); | 4935 result->set_in(0, Location::RequiresRegister()); |
4940 result->set_out(0, Location::RequiresFpuRegister()); | 4936 result->set_out(0, Location::RequiresFpuRegister()); |
4941 return result; | 4937 return result; |
4942 } | 4938 } |
4943 | 4939 |
4944 | 4940 |
4945 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4941 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4946 const Register value = locs()->in(0).reg(); | 4942 const Register value = locs()->in(0).reg(); |
4947 const VRegister result = locs()->out(0).fpu_reg(); | 4943 const VRegister result = locs()->out(0).fpu_reg(); |
4948 __ SmiUntag(TMP, value); | 4944 __ SmiUntag(TMP, value); |
(...skipping 10 matching lines...) Expand all Loading... |
4959 | 4955 |
4960 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4956 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4961 UNIMPLEMENTED(); | 4957 UNIMPLEMENTED(); |
4962 } | 4958 } |
4963 | 4959 |
4964 | 4960 |
4965 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 4961 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |
4966 bool opt) const { | 4962 bool opt) const { |
4967 const intptr_t kNumInputs = 1; | 4963 const intptr_t kNumInputs = 1; |
4968 const intptr_t kNumTemps = 0; | 4964 const intptr_t kNumTemps = 0; |
4969 LocationSummary* result = new(zone) LocationSummary( | 4965 LocationSummary* result = new (zone) |
4970 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 4966 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
4971 result->set_in(0, Location::RegisterLocation(R1)); | 4967 result->set_in(0, Location::RegisterLocation(R1)); |
4972 result->set_out(0, Location::RegisterLocation(R0)); | 4968 result->set_out(0, Location::RegisterLocation(R0)); |
4973 return result; | 4969 return result; |
4974 } | 4970 } |
4975 | 4971 |
4976 | 4972 |
4977 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4973 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4978 const Register result = locs()->out(0).reg(); | 4974 const Register result = locs()->out(0).reg(); |
4979 const Register value_obj = locs()->in(0).reg(); | 4975 const Register value_obj = locs()->in(0).reg(); |
4980 ASSERT(result == R0); | 4976 ASSERT(result == R0); |
(...skipping 15 matching lines...) Expand all Loading... |
4996 __ SmiTag(result); | 4992 __ SmiTag(result); |
4997 __ b(&done); | 4993 __ b(&done); |
4998 __ Bind(&do_call); | 4994 __ Bind(&do_call); |
4999 __ Push(value_obj); | 4995 __ Push(value_obj); |
5000 ASSERT(instance_call()->HasICData()); | 4996 ASSERT(instance_call()->HasICData()); |
5001 const ICData& ic_data = *instance_call()->ic_data(); | 4997 const ICData& ic_data = *instance_call()->ic_data(); |
5002 ASSERT((ic_data.NumberOfChecks() == 1)); | 4998 ASSERT((ic_data.NumberOfChecks() == 1)); |
5003 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 4999 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
5004 | 5000 |
5005 const intptr_t kNumberOfArguments = 1; | 5001 const intptr_t kNumberOfArguments = 1; |
5006 compiler->GenerateStaticCall(deopt_id(), | 5002 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, |
5007 instance_call()->token_pos(), | |
5008 target, | |
5009 kNumberOfArguments, | 5003 kNumberOfArguments, |
5010 Object::null_array(), // No argument names., | 5004 Object::null_array(), // No argument names., |
5011 locs(), | 5005 locs(), ICData::Handle()); |
5012 ICData::Handle()); | |
5013 __ Bind(&done); | 5006 __ Bind(&done); |
5014 } | 5007 } |
5015 | 5008 |
5016 | 5009 |
5017 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 5010 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |
5018 bool opt) const { | 5011 bool opt) const { |
5019 const intptr_t kNumInputs = 1; | 5012 const intptr_t kNumInputs = 1; |
5020 const intptr_t kNumTemps = 0; | 5013 const intptr_t kNumTemps = 0; |
5021 LocationSummary* result = new(zone) LocationSummary( | 5014 LocationSummary* result = new (zone) |
5022 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5015 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5023 result->set_in(0, Location::RequiresFpuRegister()); | 5016 result->set_in(0, Location::RequiresFpuRegister()); |
5024 result->set_out(0, Location::RequiresRegister()); | 5017 result->set_out(0, Location::RequiresRegister()); |
5025 return result; | 5018 return result; |
5026 } | 5019 } |
5027 | 5020 |
5028 | 5021 |
5029 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5022 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5030 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 5023 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
5031 const Register result = locs()->out(0).reg(); | 5024 const Register result = locs()->out(0).reg(); |
5032 const VRegister value = locs()->in(0).fpu_reg(); | 5025 const VRegister value = locs()->in(0).fpu_reg(); |
(...skipping 20 matching lines...) Expand all Loading... |
5053 | 5046 |
5054 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5047 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5055 UNIMPLEMENTED(); | 5048 UNIMPLEMENTED(); |
5056 } | 5049 } |
5057 | 5050 |
5058 | 5051 |
5059 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 5052 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |
5060 bool opt) const { | 5053 bool opt) const { |
5061 const intptr_t kNumInputs = 1; | 5054 const intptr_t kNumInputs = 1; |
5062 const intptr_t kNumTemps = 0; | 5055 const intptr_t kNumTemps = 0; |
5063 LocationSummary* result = new(zone) LocationSummary( | 5056 LocationSummary* result = new (zone) |
5064 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5057 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5065 result->set_in(0, Location::RequiresFpuRegister()); | 5058 result->set_in(0, Location::RequiresFpuRegister()); |
5066 result->set_out(0, Location::RequiresFpuRegister()); | 5059 result->set_out(0, Location::RequiresFpuRegister()); |
5067 return result; | 5060 return result; |
5068 } | 5061 } |
5069 | 5062 |
5070 | 5063 |
5071 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5064 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5072 const VRegister value = locs()->in(0).fpu_reg(); | 5065 const VRegister value = locs()->in(0).fpu_reg(); |
5073 const VRegister result = locs()->out(0).fpu_reg(); | 5066 const VRegister result = locs()->out(0).fpu_reg(); |
5074 __ fcvtsd(result, value); | 5067 __ fcvtsd(result, value); |
5075 } | 5068 } |
5076 | 5069 |
5077 | 5070 |
5078 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 5071 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |
5079 bool opt) const { | 5072 bool opt) const { |
5080 const intptr_t kNumInputs = 1; | 5073 const intptr_t kNumInputs = 1; |
5081 const intptr_t kNumTemps = 0; | 5074 const intptr_t kNumTemps = 0; |
5082 LocationSummary* result = new(zone) LocationSummary( | 5075 LocationSummary* result = new (zone) |
5083 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5076 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5084 result->set_in(0, Location::RequiresFpuRegister()); | 5077 result->set_in(0, Location::RequiresFpuRegister()); |
5085 result->set_out(0, Location::RequiresFpuRegister()); | 5078 result->set_out(0, Location::RequiresFpuRegister()); |
5086 return result; | 5079 return result; |
5087 } | 5080 } |
5088 | 5081 |
5089 | 5082 |
5090 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5083 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5091 const VRegister value = locs()->in(0).fpu_reg(); | 5084 const VRegister value = locs()->in(0).fpu_reg(); |
5092 const VRegister result = locs()->out(0).fpu_reg(); | 5085 const VRegister result = locs()->out(0).fpu_reg(); |
5093 __ fcvtds(result, value); | 5086 __ fcvtds(result, value); |
5094 } | 5087 } |
5095 | 5088 |
5096 | 5089 |
5097 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 5090 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |
5098 bool opt) const { | 5091 bool opt) const { |
5099 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 5092 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
5100 const intptr_t kNumTemps = | 5093 const intptr_t kNumTemps = |
5101 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0; | 5094 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0; |
5102 LocationSummary* result = new(zone) LocationSummary( | 5095 LocationSummary* result = new (zone) |
5103 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5096 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
5104 result->set_in(0, Location::FpuRegisterLocation(V0)); | 5097 result->set_in(0, Location::FpuRegisterLocation(V0)); |
5105 if (InputCount() == 2) { | 5098 if (InputCount() == 2) { |
5106 result->set_in(1, Location::FpuRegisterLocation(V1)); | 5099 result->set_in(1, Location::FpuRegisterLocation(V1)); |
5107 } | 5100 } |
5108 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5101 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
5109 result->set_temp(0, Location::FpuRegisterLocation(V30)); | 5102 result->set_temp(0, Location::FpuRegisterLocation(V30)); |
5110 } | 5103 } |
5111 result->set_out(0, Location::FpuRegisterLocation(V0)); | 5104 result->set_out(0, Location::FpuRegisterLocation(V0)); |
5112 return result; | 5105 return result; |
5113 } | 5106 } |
(...skipping 26 matching lines...) Expand all Loading... |
5140 const VRegister result = locs->out(0).fpu_reg(); | 5133 const VRegister result = locs->out(0).fpu_reg(); |
5141 const VRegister saved_base = locs->temp(0).fpu_reg(); | 5134 const VRegister saved_base = locs->temp(0).fpu_reg(); |
5142 ASSERT((base == result) && (result != saved_base)); | 5135 ASSERT((base == result) && (result != saved_base)); |
5143 | 5136 |
5144 Label skip_call, try_sqrt, check_base, return_nan, do_pow; | 5137 Label skip_call, try_sqrt, check_base, return_nan, do_pow; |
5145 __ fmovdd(saved_base, base); | 5138 __ fmovdd(saved_base, base); |
5146 __ LoadDImmediate(result, 1.0); | 5139 __ LoadDImmediate(result, 1.0); |
5147 // exponent == 0.0 -> return 1.0; | 5140 // exponent == 0.0 -> return 1.0; |
5148 __ fcmpdz(exp); | 5141 __ fcmpdz(exp); |
5149 __ b(&check_base, VS); // NaN -> check base. | 5142 __ b(&check_base, VS); // NaN -> check base. |
5150 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. | 5143 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. |
5151 | 5144 |
5152 // exponent == 1.0 ? | 5145 // exponent == 1.0 ? |
5153 __ fcmpd(exp, result); | 5146 __ fcmpd(exp, result); |
5154 Label return_base; | 5147 Label return_base; |
5155 __ b(&return_base, EQ); | 5148 __ b(&return_base, EQ); |
5156 | 5149 |
5157 // exponent == 2.0 ? | 5150 // exponent == 2.0 ? |
5158 __ LoadDImmediate(VTMP, 2.0); | 5151 __ LoadDImmediate(VTMP, 2.0); |
5159 __ fcmpd(exp, VTMP); | 5152 __ fcmpd(exp, VTMP); |
5160 Label return_base_times_2; | 5153 Label return_base_times_2; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5233 } | 5226 } |
5234 __ CallRuntime(TargetFunction(), InputCount()); | 5227 __ CallRuntime(TargetFunction(), InputCount()); |
5235 } | 5228 } |
5236 | 5229 |
5237 | 5230 |
5238 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 5231 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |
5239 bool opt) const { | 5232 bool opt) const { |
5240 // Only use this instruction in optimized code. | 5233 // Only use this instruction in optimized code. |
5241 ASSERT(opt); | 5234 ASSERT(opt); |
5242 const intptr_t kNumInputs = 1; | 5235 const intptr_t kNumInputs = 1; |
5243 LocationSummary* summary = new(zone) LocationSummary( | 5236 LocationSummary* summary = |
5244 zone, kNumInputs, 0, LocationSummary::kNoCall); | 5237 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
5245 if (representation() == kUnboxedDouble) { | 5238 if (representation() == kUnboxedDouble) { |
5246 if (index() == 0) { | 5239 if (index() == 0) { |
5247 summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), | 5240 summary->set_in( |
5248 Location::Any())); | 5241 0, Location::Pair(Location::RequiresFpuRegister(), Location::Any())); |
5249 } else { | 5242 } else { |
5250 ASSERT(index() == 1); | 5243 ASSERT(index() == 1); |
5251 summary->set_in(0, Location::Pair(Location::Any(), | 5244 summary->set_in( |
5252 Location::RequiresFpuRegister())); | 5245 0, Location::Pair(Location::Any(), Location::RequiresFpuRegister())); |
5253 } | 5246 } |
5254 summary->set_out(0, Location::RequiresFpuRegister()); | 5247 summary->set_out(0, Location::RequiresFpuRegister()); |
5255 } else { | 5248 } else { |
5256 ASSERT(representation() == kTagged); | 5249 ASSERT(representation() == kTagged); |
5257 if (index() == 0) { | 5250 if (index() == 0) { |
5258 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5251 summary->set_in( |
5259 Location::Any())); | 5252 0, Location::Pair(Location::RequiresRegister(), Location::Any())); |
5260 } else { | 5253 } else { |
5261 ASSERT(index() == 1); | 5254 ASSERT(index() == 1); |
5262 summary->set_in(0, Location::Pair(Location::Any(), | 5255 summary->set_in( |
5263 Location::RequiresRegister())); | 5256 0, Location::Pair(Location::Any(), Location::RequiresRegister())); |
5264 } | 5257 } |
5265 summary->set_out(0, Location::RequiresRegister()); | 5258 summary->set_out(0, Location::RequiresRegister()); |
5266 } | 5259 } |
5267 return summary; | 5260 return summary; |
5268 } | 5261 } |
5269 | 5262 |
5270 | 5263 |
5271 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5264 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5272 ASSERT(locs()->in(0).IsPairLocation()); | 5265 ASSERT(locs()->in(0).IsPairLocation()); |
5273 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5266 PairLocation* pair = locs()->in(0).AsPairLocation(); |
5274 Location in_loc = pair->At(index()); | 5267 Location in_loc = pair->At(index()); |
5275 if (representation() == kUnboxedDouble) { | 5268 if (representation() == kUnboxedDouble) { |
5276 const VRegister out = locs()->out(0).fpu_reg(); | 5269 const VRegister out = locs()->out(0).fpu_reg(); |
5277 const VRegister in = in_loc.fpu_reg(); | 5270 const VRegister in = in_loc.fpu_reg(); |
5278 __ fmovdd(out, in); | 5271 __ fmovdd(out, in); |
5279 } else { | 5272 } else { |
5280 ASSERT(representation() == kTagged); | 5273 ASSERT(representation() == kTagged); |
5281 const Register out = locs()->out(0).reg(); | 5274 const Register out = locs()->out(0).reg(); |
5282 const Register in = in_loc.reg(); | 5275 const Register in = in_loc.reg(); |
5283 __ mov(out, in); | 5276 __ mov(out, in); |
5284 } | 5277 } |
5285 } | 5278 } |
5286 | 5279 |
5287 | 5280 |
5288 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, | 5281 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, |
5289 bool opt) const { | 5282 bool opt) const { |
5290 if (kind() == MergedMathInstr::kTruncDivMod) { | 5283 if (kind() == MergedMathInstr::kTruncDivMod) { |
5291 const intptr_t kNumInputs = 2; | 5284 const intptr_t kNumInputs = 2; |
5292 const intptr_t kNumTemps = 0; | 5285 const intptr_t kNumTemps = 0; |
5293 LocationSummary* summary = new(zone) LocationSummary( | 5286 LocationSummary* summary = new (zone) |
5294 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5287 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5295 summary->set_in(0, Location::RequiresRegister()); | 5288 summary->set_in(0, Location::RequiresRegister()); |
5296 summary->set_in(1, Location::RequiresRegister()); | 5289 summary->set_in(1, Location::RequiresRegister()); |
5297 // Output is a pair of registers. | 5290 // Output is a pair of registers. |
5298 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 5291 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
5299 Location::RequiresRegister())); | 5292 Location::RequiresRegister())); |
5300 return summary; | 5293 return summary; |
5301 } | 5294 } |
5302 UNIMPLEMENTED(); | 5295 UNIMPLEMENTED(); |
5303 return NULL; | 5296 return NULL; |
5304 } | 5297 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5357 return; | 5350 return; |
5358 } | 5351 } |
5359 if (kind() == MergedMathInstr::kSinCos) { | 5352 if (kind() == MergedMathInstr::kSinCos) { |
5360 UNIMPLEMENTED(); | 5353 UNIMPLEMENTED(); |
5361 } | 5354 } |
5362 UNIMPLEMENTED(); | 5355 UNIMPLEMENTED(); |
5363 } | 5356 } |
5364 | 5357 |
5365 | 5358 |
5366 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 5359 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
5367 Zone* zone, bool opt) const { | 5360 Zone* zone, |
| 5361 bool opt) const { |
5368 return MakeCallSummary(zone); | 5362 return MakeCallSummary(zone); |
5369 } | 5363 } |
5370 | 5364 |
5371 | 5365 |
5372 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, | 5366 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
5373 bool opt) const { | |
5374 comparison()->InitializeLocationSummary(zone, opt); | 5367 comparison()->InitializeLocationSummary(zone, opt); |
5375 // Branches don't produce a result. | 5368 // Branches don't produce a result. |
5376 comparison()->locs()->set_out(0, Location::NoLocation()); | 5369 comparison()->locs()->set_out(0, Location::NoLocation()); |
5377 return comparison()->locs(); | 5370 return comparison()->locs(); |
5378 } | 5371 } |
5379 | 5372 |
5380 | 5373 |
5381 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5374 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5382 comparison()->EmitBranchCode(compiler, this); | 5375 comparison()->EmitBranchCode(compiler, this); |
5383 } | 5376 } |
5384 | 5377 |
5385 | 5378 |
5386 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 5379 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
5387 bool opt) const { | 5380 bool opt) const { |
5388 const intptr_t kNumInputs = 1; | 5381 const intptr_t kNumInputs = 1; |
5389 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); | 5382 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); |
5390 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 5383 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
5391 LocationSummary* summary = new(zone) LocationSummary( | 5384 LocationSummary* summary = new (zone) |
5392 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5385 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5393 summary->set_in(0, Location::RequiresRegister()); | 5386 summary->set_in(0, Location::RequiresRegister()); |
5394 if (!IsNullCheck()) { | 5387 if (!IsNullCheck()) { |
5395 summary->set_temp(0, Location::RequiresRegister()); | 5388 summary->set_temp(0, Location::RequiresRegister()); |
5396 if (need_mask_temp) { | 5389 if (need_mask_temp) { |
5397 summary->set_temp(1, Location::RequiresRegister()); | 5390 summary->set_temp(1, Location::RequiresRegister()); |
5398 } | 5391 } |
5399 } | 5392 } |
5400 return summary; | 5393 return summary; |
5401 } | 5394 } |
5402 | 5395 |
5403 | 5396 |
5404 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5397 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5405 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5398 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass, |
5406 ICData::kDeoptCheckClass, | |
5407 licm_hoisted_ ? ICData::kHoisted : 0); | 5399 licm_hoisted_ ? ICData::kHoisted : 0); |
5408 if (IsNullCheck()) { | 5400 if (IsNullCheck()) { |
5409 __ CompareObject(locs()->in(0).reg(), Object::null_object()); | 5401 __ CompareObject(locs()->in(0).reg(), Object::null_object()); |
5410 ASSERT(DeoptIfNull() || DeoptIfNotNull()); | 5402 ASSERT(DeoptIfNull() || DeoptIfNotNull()); |
5411 Condition cond = DeoptIfNull() ? EQ : NE; | 5403 Condition cond = DeoptIfNull() ? EQ : NE; |
5412 __ b(deopt, cond); | 5404 __ b(deopt, cond); |
5413 return; | 5405 return; |
5414 } | 5406 } |
5415 | 5407 |
5416 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 5408 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
(...skipping 22 matching lines...) Expand all Loading... |
5439 ASSERT(cids_.length() > 2); | 5431 ASSERT(cids_.length() > 2); |
5440 Register mask_reg = locs()->temp(1).reg(); | 5432 Register mask_reg = locs()->temp(1).reg(); |
5441 __ LoadImmediate(mask_reg, 1); | 5433 __ LoadImmediate(mask_reg, 1); |
5442 __ lslv(mask_reg, mask_reg, temp); | 5434 __ lslv(mask_reg, mask_reg, temp); |
5443 __ TestImmediate(mask_reg, mask); | 5435 __ TestImmediate(mask_reg, mask); |
5444 __ b(deopt, EQ); | 5436 __ b(deopt, EQ); |
5445 } | 5437 } |
5446 | 5438 |
5447 } else { | 5439 } else { |
5448 GrowableArray<CidTarget> sorted_ic_data; | 5440 GrowableArray<CidTarget> sorted_ic_data; |
5449 FlowGraphCompiler::SortICDataByCount(unary_checks(), | 5441 FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data, |
5450 &sorted_ic_data, | |
5451 /* drop_smi = */ true); | 5442 /* drop_smi = */ true); |
5452 const intptr_t num_checks = sorted_ic_data.length(); | 5443 const intptr_t num_checks = sorted_ic_data.length(); |
5453 for (intptr_t i = 0; i < num_checks; i++) { | 5444 for (intptr_t i = 0; i < num_checks; i++) { |
5454 const intptr_t cid = sorted_ic_data[i].cid; | 5445 const intptr_t cid = sorted_ic_data[i].cid; |
5455 ASSERT(cid != kSmiCid); | 5446 ASSERT(cid != kSmiCid); |
5456 __ CompareImmediate(temp, cid); | 5447 __ CompareImmediate(temp, cid); |
5457 if (i == (num_checks - 1)) { | 5448 if (i == (num_checks - 1)) { |
5458 __ b(deopt, NE); | 5449 __ b(deopt, NE); |
5459 } else { | 5450 } else { |
5460 __ b(&is_ok, EQ); | 5451 __ b(&is_ok, EQ); |
5461 } | 5452 } |
5462 } | 5453 } |
5463 } | 5454 } |
5464 __ Bind(&is_ok); | 5455 __ Bind(&is_ok); |
5465 } | 5456 } |
5466 | 5457 |
5467 | 5458 |
5468 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 5459 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
5469 bool opt) const { | 5460 bool opt) const { |
5470 const intptr_t kNumInputs = 1; | 5461 const intptr_t kNumInputs = 1; |
5471 const intptr_t kNumTemps = 0; | 5462 const intptr_t kNumTemps = 0; |
5472 LocationSummary* summary = new(zone) LocationSummary( | 5463 LocationSummary* summary = new (zone) |
5473 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5464 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5474 summary->set_in(0, Location::RequiresRegister()); | 5465 summary->set_in(0, Location::RequiresRegister()); |
5475 return summary; | 5466 return summary; |
5476 } | 5467 } |
5477 | 5468 |
5478 | 5469 |
5479 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5470 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5480 Register value = locs()->in(0).reg(); | 5471 Register value = locs()->in(0).reg(); |
5481 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 5472 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
5482 __ CompareImmediate(value, Smi::RawValue(cid_)); | 5473 __ CompareImmediate(value, Smi::RawValue(cid_)); |
5483 __ b(deopt, NE); | 5474 __ b(deopt, NE); |
5484 } | 5475 } |
5485 | 5476 |
5486 | 5477 |
5487 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 5478 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
5488 bool opt) const { | 5479 bool opt) const { |
5489 const intptr_t kNumInputs = 1; | 5480 const intptr_t kNumInputs = 1; |
5490 const intptr_t kNumTemps = 0; | 5481 const intptr_t kNumTemps = 0; |
5491 LocationSummary* summary = new(zone) LocationSummary( | 5482 LocationSummary* summary = new (zone) |
5492 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5483 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5493 summary->set_in(0, Location::RequiresRegister()); | 5484 summary->set_in(0, Location::RequiresRegister()); |
5494 return summary; | 5485 return summary; |
5495 } | 5486 } |
5496 | 5487 |
5497 | 5488 |
5498 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5489 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5499 const Register value = locs()->in(0).reg(); | 5490 const Register value = locs()->in(0).reg(); |
5500 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5491 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, |
5501 ICData::kDeoptCheckSmi, | |
5502 licm_hoisted_ ? ICData::kHoisted : 0); | 5492 licm_hoisted_ ? ICData::kHoisted : 0); |
5503 __ BranchIfNotSmi(value, deopt); | 5493 __ BranchIfNotSmi(value, deopt); |
5504 } | 5494 } |
5505 | 5495 |
5506 | 5496 |
5507 | |
5508 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, | 5497 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, |
5509 bool opt) const { | 5498 bool opt) const { |
5510 const intptr_t kNumInputs = 2; | 5499 const intptr_t kNumInputs = 2; |
5511 const intptr_t kNumTemps = 0; | 5500 const intptr_t kNumTemps = 0; |
5512 LocationSummary* locs = new(zone) LocationSummary( | 5501 LocationSummary* locs = new (zone) LocationSummary( |
5513 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 5502 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
5514 locs->set_in(kLengthPos, Location::RequiresRegister()); | 5503 locs->set_in(kLengthPos, Location::RequiresRegister()); |
5515 locs->set_in(kIndexPos, Location::RequiresRegister()); | 5504 locs->set_in(kIndexPos, Location::RequiresRegister()); |
5516 return locs; | 5505 return locs; |
5517 } | 5506 } |
5518 | 5507 |
5519 | 5508 |
5520 class RangeErrorSlowPath : public SlowPathCode { | 5509 class RangeErrorSlowPath : public SlowPathCode { |
5521 public: | 5510 public: |
5522 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) | 5511 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) |
5523 : instruction_(instruction), try_index_(try_index) { } | 5512 : instruction_(instruction), try_index_(try_index) {} |
5524 | 5513 |
5525 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 5514 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
5526 if (Assembler::EmittingComments()) { | 5515 if (Assembler::EmittingComments()) { |
5527 __ Comment("slow path check bound operation"); | 5516 __ Comment("slow path check bound operation"); |
5528 } | 5517 } |
5529 __ Bind(entry_label()); | 5518 __ Bind(entry_label()); |
5530 LocationSummary* locs = instruction_->locs(); | 5519 LocationSummary* locs = instruction_->locs(); |
5531 __ Push(locs->in(0).reg()); | 5520 __ Push(locs->in(0).reg()); |
5532 __ Push(locs->in(1).reg()); | 5521 __ Push(locs->in(1).reg()); |
5533 __ CallRuntime(kRangeErrorRuntimeEntry, 2); | 5522 __ CallRuntime(kRangeErrorRuntimeEntry, 2); |
5534 compiler->pc_descriptors_list()->AddDescriptor( | 5523 compiler->pc_descriptors_list()->AddDescriptor( |
5535 RawPcDescriptors::kOther, | 5524 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), |
5536 compiler->assembler()->CodeSize(), | 5525 instruction_->deopt_id(), instruction_->token_pos(), try_index_); |
5537 instruction_->deopt_id(), | |
5538 instruction_->token_pos(), | |
5539 try_index_); | |
5540 compiler->RecordSafepoint(locs, 2); | 5526 compiler->RecordSafepoint(locs, 2); |
5541 __ brk(0); | 5527 __ brk(0); |
5542 } | 5528 } |
5543 | 5529 |
5544 private: | 5530 private: |
5545 GenericCheckBoundInstr* instruction_; | 5531 GenericCheckBoundInstr* instruction_; |
5546 intptr_t try_index_; | 5532 intptr_t try_index_; |
5547 }; | 5533 }; |
5548 | 5534 |
5549 | 5535 |
(...skipping 12 matching lines...) Expand all Loading... |
5562 } | 5548 } |
5563 __ cmp(index, Operand(length)); | 5549 __ cmp(index, Operand(length)); |
5564 __ b(slow_path->entry_label(), CS); | 5550 __ b(slow_path->entry_label(), CS); |
5565 } | 5551 } |
5566 | 5552 |
5567 | 5553 |
5568 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 5554 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
5569 bool opt) const { | 5555 bool opt) const { |
5570 const intptr_t kNumInputs = 2; | 5556 const intptr_t kNumInputs = 2; |
5571 const intptr_t kNumTemps = 0; | 5557 const intptr_t kNumTemps = 0; |
5572 LocationSummary* locs = new(zone) LocationSummary( | 5558 LocationSummary* locs = new (zone) |
5573 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5559 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5574 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 5560 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
5575 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 5561 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
5576 return locs; | 5562 return locs; |
5577 } | 5563 } |
5578 | 5564 |
5579 | 5565 |
5580 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5566 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5581 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 5567 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |
5582 flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 5568 flags |= licm_hoisted_ ? ICData::kHoisted : 0; |
5583 Label* deopt = compiler->AddDeoptStub( | 5569 Label* deopt = |
5584 deopt_id(), | 5570 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); |
5585 ICData::kDeoptCheckArrayBound, | |
5586 flags); | |
5587 | 5571 |
5588 Location length_loc = locs()->in(kLengthPos); | 5572 Location length_loc = locs()->in(kLengthPos); |
5589 Location index_loc = locs()->in(kIndexPos); | 5573 Location index_loc = locs()->in(kIndexPos); |
5590 | 5574 |
5591 const intptr_t index_cid = index()->Type()->ToCid(); | 5575 const intptr_t index_cid = index()->Type()->ToCid(); |
5592 if (length_loc.IsConstant() && index_loc.IsConstant()) { | 5576 if (length_loc.IsConstant() && index_loc.IsConstant()) { |
5593 // TODO(srdjan): remove this code once failures are fixed. | 5577 // TODO(srdjan): remove this code once failures are fixed. |
5594 if ((Smi::Cast(length_loc.constant()).Value() > | 5578 if ((Smi::Cast(length_loc.constant()).Value() > |
5595 Smi::Cast(index_loc.constant()).Value()) && | 5579 Smi::Cast(index_loc.constant()).Value()) && |
5596 (Smi::Cast(index_loc.constant()).Value() >= 0)) { | 5580 (Smi::Cast(index_loc.constant()).Value() >= 0)) { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5696 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) | 5680 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) |
5697 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) | 5681 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) |
5698 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) | 5682 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) |
5699 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 5683 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
5700 | 5684 |
5701 | 5685 |
5702 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 5686 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |
5703 bool opt) const { | 5687 bool opt) const { |
5704 const intptr_t kNumInputs = 1; | 5688 const intptr_t kNumInputs = 1; |
5705 const intptr_t kNumTemps = 0; | 5689 const intptr_t kNumTemps = 0; |
5706 LocationSummary* summary = new(zone) LocationSummary( | 5690 LocationSummary* summary = new (zone) |
5707 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5691 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5708 if (from() == kUnboxedMint) { | 5692 if (from() == kUnboxedMint) { |
5709 UNREACHABLE(); | 5693 UNREACHABLE(); |
5710 } else if (to() == kUnboxedMint) { | 5694 } else if (to() == kUnboxedMint) { |
5711 UNREACHABLE(); | 5695 UNREACHABLE(); |
5712 } else { | 5696 } else { |
5713 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 5697 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
5714 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 5698 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
5715 summary->set_in(0, Location::RequiresRegister()); | 5699 summary->set_in(0, Location::RequiresRegister()); |
5716 summary->set_out(0, Location::RequiresRegister()); | 5700 summary->set_out(0, Location::RequiresRegister()); |
5717 } | 5701 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5749 UNREACHABLE(); | 5733 UNREACHABLE(); |
5750 } else if (to() == kUnboxedMint) { | 5734 } else if (to() == kUnboxedMint) { |
5751 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 5735 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
5752 UNREACHABLE(); | 5736 UNREACHABLE(); |
5753 } else { | 5737 } else { |
5754 UNREACHABLE(); | 5738 UNREACHABLE(); |
5755 } | 5739 } |
5756 } | 5740 } |
5757 | 5741 |
5758 | 5742 |
5759 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, | 5743 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
5760 bool opt) const { | 5744 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
5761 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
5762 } | 5745 } |
5763 | 5746 |
5764 | 5747 |
5765 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5748 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5766 compiler->GenerateRuntimeCall(token_pos(), | 5749 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, |
5767 deopt_id(), | |
5768 kThrowRuntimeEntry, | |
5769 1, | |
5770 locs()); | 5750 locs()); |
5771 __ brk(0); | 5751 __ brk(0); |
5772 } | 5752 } |
5773 | 5753 |
5774 | 5754 |
5775 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, | 5755 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
5776 bool opt) const { | 5756 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
5777 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
5778 } | 5757 } |
5779 | 5758 |
5780 | 5759 |
5781 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5760 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5782 compiler->SetNeedsStacktrace(catch_try_index()); | 5761 compiler->SetNeedsStacktrace(catch_try_index()); |
5783 compiler->GenerateRuntimeCall(token_pos(), | 5762 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, |
5784 deopt_id(), | 5763 2, locs()); |
5785 kReThrowRuntimeEntry, | |
5786 2, | |
5787 locs()); | |
5788 __ brk(0); | 5764 __ brk(0); |
5789 } | 5765 } |
5790 | 5766 |
5791 | 5767 |
5792 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, | 5768 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
5793 bool opt) const { | 5769 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
5794 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
5795 } | 5770 } |
5796 | 5771 |
5797 | 5772 |
5798 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5773 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5799 __ Stop(message()); | 5774 __ Stop(message()); |
5800 } | 5775 } |
5801 | 5776 |
5802 | 5777 |
5803 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5778 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5804 if (!compiler->CanFallThroughTo(normal_entry())) { | 5779 if (!compiler->CanFallThroughTo(normal_entry())) { |
5805 __ b(compiler->GetJumpLabel(normal_entry())); | 5780 __ b(compiler->GetJumpLabel(normal_entry())); |
5806 } | 5781 } |
5807 } | 5782 } |
5808 | 5783 |
5809 | 5784 |
5810 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, | 5785 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
5811 bool opt) const { | 5786 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
5812 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
5813 } | 5787 } |
5814 | 5788 |
5815 | 5789 |
5816 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5790 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5817 if (!compiler->is_optimizing()) { | 5791 if (!compiler->is_optimizing()) { |
5818 if (FLAG_reorder_basic_blocks) { | 5792 if (FLAG_reorder_basic_blocks) { |
5819 compiler->EmitEdgeCounter(block()->preorder_number()); | 5793 compiler->EmitEdgeCounter(block()->preorder_number()); |
5820 } | 5794 } |
5821 // Add a deoptimization descriptor for deoptimizing instructions that | 5795 // Add a deoptimization descriptor for deoptimizing instructions that |
5822 // may be inserted before this instruction. | 5796 // may be inserted before this instruction. |
5823 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 5797 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), |
5824 GetDeoptId(), | |
5825 TokenPosition::kNoSource); | 5798 TokenPosition::kNoSource); |
5826 } | 5799 } |
5827 if (HasParallelMove()) { | 5800 if (HasParallelMove()) { |
5828 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 5801 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
5829 } | 5802 } |
5830 | 5803 |
5831 // We can fall through if the successor is the next block in the list. | 5804 // We can fall through if the successor is the next block in the list. |
5832 // Otherwise, we need a jump. | 5805 // Otherwise, we need a jump. |
5833 if (!compiler->CanFallThroughTo(successor())) { | 5806 if (!compiler->CanFallThroughTo(successor())) { |
5834 __ b(compiler->GetJumpLabel(successor())); | 5807 __ b(compiler->GetJumpLabel(successor())); |
5835 } | 5808 } |
5836 } | 5809 } |
5837 | 5810 |
5838 | 5811 |
5839 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 5812 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |
5840 bool opt) const { | 5813 bool opt) const { |
5841 const intptr_t kNumInputs = 1; | 5814 const intptr_t kNumInputs = 1; |
5842 const intptr_t kNumTemps = 1; | 5815 const intptr_t kNumTemps = 1; |
5843 | 5816 |
5844 LocationSummary* summary = new(zone) LocationSummary( | 5817 LocationSummary* summary = new (zone) |
5845 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5818 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5846 | 5819 |
5847 summary->set_in(0, Location::RequiresRegister()); | 5820 summary->set_in(0, Location::RequiresRegister()); |
5848 summary->set_temp(0, Location::RequiresRegister()); | 5821 summary->set_temp(0, Location::RequiresRegister()); |
5849 | 5822 |
5850 return summary; | 5823 return summary; |
5851 } | 5824 } |
5852 | 5825 |
5853 | 5826 |
5854 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5827 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5855 Register target_address_reg = locs()->temp_slot(0)->reg(); | 5828 Register target_address_reg = locs()->temp_slot(0)->reg(); |
5856 | 5829 |
5857 // Load code entry point. | 5830 // Load code entry point. |
5858 const intptr_t entry_offset = __ CodeSize(); | 5831 const intptr_t entry_offset = __ CodeSize(); |
5859 if (Utils::IsInt(21, -entry_offset)) { | 5832 if (Utils::IsInt(21, -entry_offset)) { |
5860 __ adr(target_address_reg, Immediate(-entry_offset)); | 5833 __ adr(target_address_reg, Immediate(-entry_offset)); |
5861 } else { | 5834 } else { |
5862 __ adr(target_address_reg, Immediate(0)); | 5835 __ adr(target_address_reg, Immediate(0)); |
5863 __ AddImmediate(target_address_reg, target_address_reg, -entry_offset); | 5836 __ AddImmediate(target_address_reg, target_address_reg, -entry_offset); |
5864 } | 5837 } |
5865 | 5838 |
5866 // Add the offset. | 5839 // Add the offset. |
5867 Register offset_reg = locs()->in(0).reg(); | 5840 Register offset_reg = locs()->in(0).reg(); |
5868 Operand offset_opr = | 5841 Operand offset_opr = (offset()->definition()->representation() == kTagged) |
5869 (offset()->definition()->representation() == kTagged) ? | 5842 ? Operand(offset_reg, ASR, kSmiTagSize) |
5870 Operand(offset_reg, ASR, kSmiTagSize) : | 5843 : Operand(offset_reg); |
5871 Operand(offset_reg); | |
5872 __ add(target_address_reg, target_address_reg, offset_opr); | 5844 __ add(target_address_reg, target_address_reg, offset_opr); |
5873 | 5845 |
5874 // Jump to the absolute address. | 5846 // Jump to the absolute address. |
5875 __ br(target_address_reg); | 5847 __ br(target_address_reg); |
5876 } | 5848 } |
5877 | 5849 |
5878 | 5850 |
5879 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, | 5851 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, |
5880 bool opt) const { | 5852 bool opt) const { |
5881 const intptr_t kNumInputs = 2; | 5853 const intptr_t kNumInputs = 2; |
5882 const intptr_t kNumTemps = 0; | 5854 const intptr_t kNumTemps = 0; |
5883 if (needs_number_check()) { | 5855 if (needs_number_check()) { |
5884 LocationSummary* locs = new(zone) LocationSummary( | 5856 LocationSummary* locs = new (zone) |
5885 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5857 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
5886 locs->set_in(0, Location::RegisterLocation(R0)); | 5858 locs->set_in(0, Location::RegisterLocation(R0)); |
5887 locs->set_in(1, Location::RegisterLocation(R1)); | 5859 locs->set_in(1, Location::RegisterLocation(R1)); |
5888 locs->set_out(0, Location::RegisterLocation(R0)); | 5860 locs->set_out(0, Location::RegisterLocation(R0)); |
5889 return locs; | 5861 return locs; |
5890 } | 5862 } |
5891 LocationSummary* locs = new(zone) LocationSummary( | 5863 LocationSummary* locs = new (zone) |
5892 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5864 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5893 locs->set_in(0, Location::RegisterOrConstant(left())); | 5865 locs->set_in(0, Location::RegisterOrConstant(left())); |
5894 // Only one of the inputs can be a constant. Choose register if the first one | 5866 // Only one of the inputs can be a constant. Choose register if the first one |
5895 // is a constant. | 5867 // is a constant. |
5896 locs->set_in(1, locs->in(0).IsConstant() | 5868 locs->set_in(1, locs->in(0).IsConstant() |
5897 ? Location::RequiresRegister() | 5869 ? Location::RequiresRegister() |
5898 : Location::RegisterOrConstant(right())); | 5870 : Location::RegisterOrConstant(right())); |
5899 locs->set_out(0, Location::RequiresRegister()); | 5871 locs->set_out(0, Location::RequiresRegister()); |
5900 return locs; | 5872 return locs; |
5901 } | 5873 } |
5902 | 5874 |
5903 | 5875 |
5904 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 5876 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
5905 BranchLabels labels) { | 5877 BranchLabels labels) { |
5906 Location left = locs()->in(0); | 5878 Location left = locs()->in(0); |
5907 Location right = locs()->in(1); | 5879 Location right = locs()->in(1); |
5908 ASSERT(!left.IsConstant() || !right.IsConstant()); | 5880 ASSERT(!left.IsConstant() || !right.IsConstant()); |
5909 Condition true_condition; | 5881 Condition true_condition; |
5910 if (left.IsConstant()) { | 5882 if (left.IsConstant()) { |
5911 true_condition = compiler->EmitEqualityRegConstCompare(right.reg(), | 5883 true_condition = compiler->EmitEqualityRegConstCompare( |
5912 left.constant(), | 5884 right.reg(), left.constant(), needs_number_check(), token_pos()); |
5913 needs_number_check(), | |
5914 token_pos()); | |
5915 } else if (right.IsConstant()) { | 5885 } else if (right.IsConstant()) { |
5916 true_condition = compiler->EmitEqualityRegConstCompare(left.reg(), | 5886 true_condition = compiler->EmitEqualityRegConstCompare( |
5917 right.constant(), | 5887 left.reg(), right.constant(), needs_number_check(), token_pos()); |
5918 needs_number_check(), | |
5919 token_pos()); | |
5920 } else { | 5888 } else { |
5921 true_condition = compiler->EmitEqualityRegRegCompare(left.reg(), | 5889 true_condition = compiler->EmitEqualityRegRegCompare( |
5922 right.reg(), | 5890 left.reg(), right.reg(), needs_number_check(), token_pos()); |
5923 needs_number_check(), | |
5924 token_pos()); | |
5925 } | 5891 } |
5926 if (kind() != Token::kEQ_STRICT) { | 5892 if (kind() != Token::kEQ_STRICT) { |
5927 ASSERT(kind() == Token::kNE_STRICT); | 5893 ASSERT(kind() == Token::kNE_STRICT); |
5928 true_condition = NegateCondition(true_condition); | 5894 true_condition = NegateCondition(true_condition); |
5929 } | 5895 } |
5930 return true_condition; | 5896 return true_condition; |
5931 } | 5897 } |
5932 | 5898 |
5933 | 5899 |
5934 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5900 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5935 __ Comment("StrictCompareInstr"); | 5901 __ Comment("StrictCompareInstr"); |
5936 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 5902 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
5937 | 5903 |
5938 Label is_true, is_false; | 5904 Label is_true, is_false; |
5939 BranchLabels labels = { &is_true, &is_false, &is_false }; | 5905 BranchLabels labels = {&is_true, &is_false, &is_false}; |
5940 Condition true_condition = EmitComparisonCode(compiler, labels); | 5906 Condition true_condition = EmitComparisonCode(compiler, labels); |
5941 EmitBranchOnCondition(compiler, true_condition, labels); | 5907 EmitBranchOnCondition(compiler, true_condition, labels); |
5942 | 5908 |
5943 const Register result = locs()->out(0).reg(); | 5909 const Register result = locs()->out(0).reg(); |
5944 Label done; | 5910 Label done; |
5945 __ Bind(&is_false); | 5911 __ Bind(&is_false); |
5946 __ LoadObject(result, Bool::False()); | 5912 __ LoadObject(result, Bool::False()); |
5947 __ b(&done); | 5913 __ b(&done); |
5948 __ Bind(&is_true); | 5914 __ Bind(&is_true); |
5949 __ LoadObject(result, Bool::True()); | 5915 __ LoadObject(result, Bool::True()); |
5950 __ Bind(&done); | 5916 __ Bind(&done); |
5951 } | 5917 } |
5952 | 5918 |
5953 | 5919 |
5954 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 5920 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
5955 BranchInstr* branch) { | 5921 BranchInstr* branch) { |
5956 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 5922 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
5957 | 5923 |
5958 BranchLabels labels = compiler->CreateBranchLabels(branch); | 5924 BranchLabels labels = compiler->CreateBranchLabels(branch); |
5959 Condition true_condition = EmitComparisonCode(compiler, labels); | 5925 Condition true_condition = EmitComparisonCode(compiler, labels); |
5960 EmitBranchOnCondition(compiler, true_condition, labels); | 5926 EmitBranchOnCondition(compiler, true_condition, labels); |
5961 } | 5927 } |
5962 | 5928 |
5963 | 5929 |
5964 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 5930 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
5965 bool opt) const { | 5931 bool opt) const { |
5966 return LocationSummary::Make(zone, | 5932 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
5967 1, | |
5968 Location::RequiresRegister(), | |
5969 LocationSummary::kNoCall); | 5933 LocationSummary::kNoCall); |
5970 } | 5934 } |
5971 | 5935 |
5972 | 5936 |
5973 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5937 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5974 const Register value = locs()->in(0).reg(); | 5938 const Register value = locs()->in(0).reg(); |
5975 const Register result = locs()->out(0).reg(); | 5939 const Register result = locs()->out(0).reg(); |
5976 | 5940 |
5977 __ LoadObject(result, Bool::True()); | 5941 __ LoadObject(result, Bool::True()); |
5978 __ LoadObject(TMP, Bool::False()); | 5942 __ LoadObject(TMP, Bool::False()); |
5979 __ CompareRegisters(result, value); | 5943 __ CompareRegisters(result, value); |
5980 __ csel(result, TMP, result, EQ); | 5944 __ csel(result, TMP, result, EQ); |
5981 } | 5945 } |
5982 | 5946 |
5983 | 5947 |
5984 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 5948 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
5985 bool opt) const { | 5949 bool opt) const { |
5986 return MakeCallSummary(zone); | 5950 return MakeCallSummary(zone); |
5987 } | 5951 } |
5988 | 5952 |
5989 | 5953 |
5990 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5954 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5991 const Code& stub = Code::ZoneHandle( | 5955 const Code& stub = Code::ZoneHandle( |
5992 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 5956 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |
5993 const StubEntry stub_entry(stub); | 5957 const StubEntry stub_entry(stub); |
5994 compiler->GenerateCall(token_pos(), | 5958 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, |
5995 stub_entry, | |
5996 RawPcDescriptors::kOther, | |
5997 locs()); | 5959 locs()); |
5998 compiler->AddStubCallTarget(stub); | 5960 compiler->AddStubCallTarget(stub); |
5999 __ Drop(ArgumentCount()); // Discard arguments. | 5961 __ Drop(ArgumentCount()); // Discard arguments. |
6000 } | 5962 } |
6001 | 5963 |
6002 | 5964 |
6003 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5965 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6004 ASSERT(!compiler->is_optimizing()); | 5966 ASSERT(!compiler->is_optimizing()); |
6005 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); | 5967 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); |
6006 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); | 5968 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); |
6007 compiler->RecordSafepoint(locs()); | 5969 compiler->RecordSafepoint(locs()); |
6008 } | 5970 } |
6009 | 5971 |
6010 | 5972 |
6011 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary( | 5973 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary(Zone* zone, |
6012 Zone* zone, bool opt) const { | 5974 bool opt) const { |
6013 const intptr_t kNumInputs = 1; | 5975 const intptr_t kNumInputs = 1; |
6014 const intptr_t kNumTemps = 0; | 5976 const intptr_t kNumTemps = 0; |
6015 LocationSummary* locs = new(zone) LocationSummary( | 5977 LocationSummary* locs = new (zone) |
6016 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5978 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
6017 locs->set_in(0, Location::RegisterLocation(R0)); | 5979 locs->set_in(0, Location::RegisterLocation(R0)); |
6018 locs->set_out(0, Location::RegisterLocation(R0)); | 5980 locs->set_out(0, Location::RegisterLocation(R0)); |
6019 return locs; | 5981 return locs; |
6020 } | 5982 } |
6021 | 5983 |
6022 | 5984 |
6023 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5985 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6024 const Register typed_data = locs()->in(0).reg(); | 5986 const Register typed_data = locs()->in(0).reg(); |
6025 const Register result = locs()->out(0).reg(); | 5987 const Register result = locs()->out(0).reg(); |
6026 __ PushObject(Object::null_object()); | 5988 __ PushObject(Object::null_object()); |
6027 __ Push(typed_data); | 5989 __ Push(typed_data); |
6028 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, | 5990 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
6029 deopt_id(), | 5991 kGrowRegExpStackRuntimeEntry, 1, locs()); |
6030 kGrowRegExpStackRuntimeEntry, | |
6031 1, | |
6032 locs()); | |
6033 __ Drop(1); | 5992 __ Drop(1); |
6034 __ Pop(result); | 5993 __ Pop(result); |
6035 } | 5994 } |
6036 | 5995 |
6037 | 5996 |
6038 } // namespace dart | 5997 } // namespace dart |
6039 | 5998 |
6040 #endif // defined TARGET_ARCH_ARM64 | 5999 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |