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

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

Powered by Google App Engine
This is Rietveld 408576698