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

Side by Side Diff: runtime/vm/intermediate_language_arm.cc

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

Powered by Google App Engine
This is Rietveld 408576698