OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "vm/symbols.h" | 22 #include "vm/symbols.h" |
23 | 23 |
24 #define __ compiler->assembler()-> | 24 #define __ compiler->assembler()-> |
25 #define Z (compiler->zone()) | 25 #define Z (compiler->zone()) |
26 | 26 |
27 namespace dart { | 27 namespace dart { |
28 | 28 |
29 // Generic summary for call instructions that have all arguments pushed | 29 // Generic summary for call instructions that have all arguments pushed |
30 // on the stack and return the result in a fixed register V0. | 30 // on the stack and return the result in a fixed register V0. |
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(V0)); | 34 result->set_out(0, Location::RegisterLocation(V0)); |
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 __ Comment("PushArgumentInstr"); | 53 __ Comment("PushArgumentInstr"); |
54 if (compiler->is_optimizing()) { | 54 if (compiler->is_optimizing()) { |
55 Location value = locs()->in(0); | 55 Location value = locs()->in(0); |
56 if (value.IsRegister()) { | 56 if (value.IsRegister()) { |
57 __ Push(value.reg()); | 57 __ Push(value.reg()); |
58 } else if (value.IsConstant()) { | 58 } else if (value.IsConstant()) { |
59 __ PushObject(value.constant()); | 59 __ PushObject(value.constant()); |
60 } else { | 60 } else { |
61 ASSERT(value.IsStackSlot()); | 61 ASSERT(value.IsStackSlot()); |
62 const intptr_t value_offset = value.ToStackSlotOffset(); | 62 const intptr_t value_offset = value.ToStackSlotOffset(); |
63 __ LoadFromOffset(TMP, FP, value_offset); | 63 __ LoadFromOffset(TMP, FP, value_offset); |
64 __ Push(TMP); | 64 __ Push(TMP); |
65 } | 65 } |
66 } | 66 } |
67 } | 67 } |
68 | 68 |
69 | 69 |
70 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, | 70 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
71 bool opt) const { | |
72 const intptr_t kNumInputs = 1; | 71 const intptr_t kNumInputs = 1; |
73 const intptr_t kNumTemps = 0; | 72 const intptr_t kNumTemps = 0; |
74 LocationSummary* locs = new(zone) LocationSummary( | 73 LocationSummary* locs = new (zone) |
75 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 74 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
76 locs->set_in(0, Location::RegisterLocation(V0)); | 75 locs->set_in(0, Location::RegisterLocation(V0)); |
77 return locs; | 76 return locs; |
78 } | 77 } |
79 | 78 |
80 | 79 |
81 // Attempt optimized compilation at return instruction instead of at the entry. | 80 // Attempt optimized compilation at return instruction instead of at the entry. |
82 // The entry needs to be patchable, no inlined objects are allowed in the area | 81 // The entry needs to be patchable, no inlined objects are allowed in the area |
83 // that will be overwritten by the patch instructions: a branch macro sequence. | 82 // that will be overwritten by the patch instructions: a branch macro sequence. |
84 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 83 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
85 __ Comment("ReturnInstr"); | 84 __ Comment("ReturnInstr"); |
(...skipping 18 matching lines...) Expand all Loading... |
104 __ break_(0); | 103 __ break_(0); |
105 | 104 |
106 __ Bind(&stack_ok); | 105 __ Bind(&stack_ok); |
107 #endif | 106 #endif |
108 __ LeaveDartFrameAndReturn(); | 107 __ LeaveDartFrameAndReturn(); |
109 } | 108 } |
110 | 109 |
111 | 110 |
112 static Condition NegateCondition(Condition condition) { | 111 static Condition NegateCondition(Condition condition) { |
113 switch (condition.rel_op()) { | 112 switch (condition.rel_op()) { |
114 case AL: condition.set_rel_op(NV); break; | 113 case AL: |
115 case NV: condition.set_rel_op(AL); break; | 114 condition.set_rel_op(NV); |
116 case EQ: condition.set_rel_op(NE); break; | 115 break; |
117 case NE: condition.set_rel_op(EQ); break; | 116 case NV: |
118 case LT: condition.set_rel_op(GE); break; | 117 condition.set_rel_op(AL); |
119 case LE: condition.set_rel_op(GT); break; | 118 break; |
120 case GT: condition.set_rel_op(LE); break; | 119 case EQ: |
121 case GE: condition.set_rel_op(LT); break; | 120 condition.set_rel_op(NE); |
122 case ULT: condition.set_rel_op(UGE); break; | 121 break; |
123 case ULE: condition.set_rel_op(UGT); break; | 122 case NE: |
124 case UGT: condition.set_rel_op(ULE); break; | 123 condition.set_rel_op(EQ); |
125 case UGE: condition.set_rel_op(ULT); break; | 124 break; |
| 125 case LT: |
| 126 condition.set_rel_op(GE); |
| 127 break; |
| 128 case LE: |
| 129 condition.set_rel_op(GT); |
| 130 break; |
| 131 case GT: |
| 132 condition.set_rel_op(LE); |
| 133 break; |
| 134 case GE: |
| 135 condition.set_rel_op(LT); |
| 136 break; |
| 137 case ULT: |
| 138 condition.set_rel_op(UGE); |
| 139 break; |
| 140 case ULE: |
| 141 condition.set_rel_op(UGT); |
| 142 break; |
| 143 case UGT: |
| 144 condition.set_rel_op(ULE); |
| 145 break; |
| 146 case UGE: |
| 147 condition.set_rel_op(ULT); |
| 148 break; |
126 default: | 149 default: |
127 UNREACHABLE(); | 150 UNREACHABLE(); |
128 } | 151 } |
129 return condition; | 152 return condition; |
130 } | 153 } |
131 | 154 |
132 | 155 |
133 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, | 156 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, |
134 bool opt) const { | 157 bool opt) const { |
135 comparison()->InitializeLocationSummary(zone, opt); | 158 comparison()->InitializeLocationSummary(zone, opt); |
(...skipping 12 matching lines...) Expand all Loading... |
148 intptr_t temp = true_value; | 171 intptr_t temp = true_value; |
149 true_value = false_value; | 172 true_value = false_value; |
150 false_value = temp; | 173 false_value = temp; |
151 swapped = true; | 174 swapped = true; |
152 } | 175 } |
153 | 176 |
154 // Initialize result with the true value. | 177 // Initialize result with the true value. |
155 __ LoadImmediate(result, Smi::RawValue(true_value)); | 178 __ LoadImmediate(result, Smi::RawValue(true_value)); |
156 | 179 |
157 // Emit comparison code. This must not overwrite the result register. | 180 // Emit comparison code. This must not overwrite the result register. |
158 BranchLabels labels = { NULL, NULL, NULL }; // Emit branch-free code. | 181 BranchLabels labels = {NULL, NULL, NULL}; // Emit branch-free code. |
159 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 182 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
160 if (swapped) { | 183 if (swapped) { |
161 true_condition = NegateCondition(true_condition); | 184 true_condition = NegateCondition(true_condition); |
162 } | 185 } |
163 | 186 |
164 // Evaluate condition and provide result in CMPRES1. | 187 // Evaluate condition and provide result in CMPRES1. |
165 Register left = true_condition.left(); | 188 Register left = true_condition.left(); |
166 Register right = true_condition.right(); | 189 Register right = true_condition.right(); |
167 bool zero_is_false = true; // Zero in CMPRES1 indicates a false condition. | 190 bool zero_is_false = true; // Zero in CMPRES1 indicates a false condition. |
168 switch (true_condition.rel_op()) { | 191 switch (true_condition.rel_op()) { |
169 case AL: return; // Result holds true_value. | 192 case AL: |
170 case NV: __ LoadImmediate(result, false_value); return; | 193 return; // Result holds true_value. |
| 194 case NV: |
| 195 __ LoadImmediate(result, false_value); |
| 196 return; |
171 case EQ: | 197 case EQ: |
172 zero_is_false = false; | 198 zero_is_false = false; |
173 // fall through. | 199 // fall through. |
174 case NE: { | 200 case NE: { |
175 if (left == IMM) { | 201 if (left == IMM) { |
176 __ XorImmediate(CMPRES1, right, true_condition.imm()); | 202 __ XorImmediate(CMPRES1, right, true_condition.imm()); |
177 } else if (right == IMM) { | 203 } else if (right == IMM) { |
178 __ XorImmediate(CMPRES1, left, true_condition.imm()); | 204 __ XorImmediate(CMPRES1, left, true_condition.imm()); |
179 } else { | 205 } else { |
180 __ xor_(CMPRES1, left, right); | 206 __ xor_(CMPRES1, left, right); |
181 } | 207 } |
182 break; | 208 break; |
183 } | 209 } |
184 case GE: | 210 case GE: |
185 zero_is_false = false; | 211 zero_is_false = false; |
186 // fall through. | 212 // fall through. |
187 case LT: { | 213 case LT: { |
188 if (left == IMM) { | 214 if (left == IMM) { |
189 __ slti(CMPRES1, right, Immediate(true_condition.imm() + 1)); | 215 __ slti(CMPRES1, right, Immediate(true_condition.imm() + 1)); |
190 zero_is_false = !zero_is_false; | 216 zero_is_false = !zero_is_false; |
191 } else if (right == IMM) { | 217 } else if (right == IMM) { |
192 __ slti(CMPRES1, left, Immediate(true_condition.imm())); | 218 __ slti(CMPRES1, left, Immediate(true_condition.imm())); |
193 } else { | 219 } else { |
194 __ slt(CMPRES1, left, right); | 220 __ slt(CMPRES1, left, right); |
195 } | 221 } |
196 break; | 222 break; |
197 } | 223 } |
198 case LE: | 224 case LE: |
199 zero_is_false = false; | 225 zero_is_false = false; |
200 // fall through. | 226 // fall through. |
201 case GT: { | 227 case GT: { |
202 if (left == IMM) { | 228 if (left == IMM) { |
203 __ slti(CMPRES1, right, Immediate(true_condition.imm())); | 229 __ slti(CMPRES1, right, Immediate(true_condition.imm())); |
204 } else if (right == IMM) { | 230 } else if (right == IMM) { |
205 __ slti(CMPRES1, left, Immediate(true_condition.imm() + 1)); | 231 __ slti(CMPRES1, left, Immediate(true_condition.imm() + 1)); |
206 zero_is_false = !zero_is_false; | 232 zero_is_false = !zero_is_false; |
207 } else { | 233 } else { |
208 __ slt(CMPRES1, right, left); | 234 __ slt(CMPRES1, right, left); |
209 } | 235 } |
210 break; | 236 break; |
211 } | 237 } |
212 case UGE: | 238 case UGE: |
213 zero_is_false = false; | 239 zero_is_false = false; |
214 // fall through. | 240 // fall through. |
215 case ULT: { | 241 case ULT: { |
216 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used. | 242 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used. |
217 __ sltu(CMPRES1, left, right); | 243 __ sltu(CMPRES1, left, right); |
218 break; | 244 break; |
219 } | 245 } |
220 case ULE: | 246 case ULE: |
221 zero_is_false = false; | 247 zero_is_false = false; |
222 // fall through. | 248 // fall through. |
223 case UGT: { | 249 case UGT: { |
224 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used. | 250 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used. |
225 __ sltu(CMPRES1, right, left); | 251 __ sltu(CMPRES1, right, left); |
226 break; | 252 break; |
227 } | 253 } |
228 default: | 254 default: |
229 UNREACHABLE(); | 255 UNREACHABLE(); |
230 } | 256 } |
231 | 257 |
232 // CMPRES1 is the evaluated condition, zero or non-zero, as specified by the | 258 // CMPRES1 is the evaluated condition, zero or non-zero, as specified by the |
(...skipping 10 matching lines...) Expand all Loading... |
243 } else { | 269 } else { |
244 __ movn(result, false_value_reg, CMPRES1); | 270 __ movn(result, false_value_reg, CMPRES1); |
245 } | 271 } |
246 } | 272 } |
247 | 273 |
248 | 274 |
249 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 275 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |
250 bool opt) const { | 276 bool opt) const { |
251 const intptr_t kNumInputs = 1; | 277 const intptr_t kNumInputs = 1; |
252 const intptr_t kNumTemps = 0; | 278 const intptr_t kNumTemps = 0; |
253 LocationSummary* summary = new(zone) LocationSummary( | 279 LocationSummary* summary = new (zone) |
254 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 280 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
255 summary->set_in(0, Location::RegisterLocation(T0)); // Function. | 281 summary->set_in(0, Location::RegisterLocation(T0)); // Function. |
256 summary->set_out(0, Location::RegisterLocation(V0)); | 282 summary->set_out(0, Location::RegisterLocation(V0)); |
257 return summary; | 283 return summary; |
258 } | 284 } |
259 | 285 |
260 | 286 |
261 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 287 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
262 // Load arguments descriptor in S4. | 288 // Load arguments descriptor in S4. |
263 int argument_count = ArgumentCount(); | 289 int argument_count = ArgumentCount(); |
264 const Array& arguments_descriptor = | 290 const Array& arguments_descriptor = Array::ZoneHandle( |
265 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 291 ArgumentsDescriptor::New(argument_count, argument_names())); |
266 argument_names())); | |
267 __ LoadObject(S4, arguments_descriptor); | 292 __ LoadObject(S4, arguments_descriptor); |
268 | 293 |
269 // Load closure function code in T2. | 294 // Load closure function code in T2. |
270 // S4: arguments descriptor array. | 295 // S4: arguments descriptor array. |
271 // S5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). | 296 // S5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). |
272 ASSERT(locs()->in(0).reg() == T0); | 297 ASSERT(locs()->in(0).reg() == T0); |
273 __ LoadImmediate(S5, 0); | 298 __ LoadImmediate(S5, 0); |
274 __ lw(T2, FieldAddress(T0, Function::entry_point_offset())); | 299 __ lw(T2, FieldAddress(T0, Function::entry_point_offset())); |
275 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); | 300 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); |
276 __ jalr(T2); | 301 __ jalr(T2); |
277 compiler->RecordSafepoint(locs()); | 302 compiler->RecordSafepoint(locs()); |
278 // Marks either the continuation point in unoptimized code or the | 303 // Marks either the continuation point in unoptimized code or the |
279 // deoptimization point in optimized code, after call. | 304 // deoptimization point in optimized code, after call. |
280 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); | 305 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); |
281 if (compiler->is_optimizing()) { | 306 if (compiler->is_optimizing()) { |
282 compiler->AddDeoptIndexAtCall(deopt_id_after); | 307 compiler->AddDeoptIndexAtCall(deopt_id_after); |
283 } | 308 } |
284 // Add deoptimization continuation point after the call and before the | 309 // Add deoptimization continuation point after the call and before the |
285 // arguments are removed. | 310 // arguments are removed. |
286 // In optimized code this descriptor is needed for exception handling. | 311 // In optimized code this descriptor is needed for exception handling. |
287 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 312 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, |
288 deopt_id_after, | |
289 token_pos()); | 313 token_pos()); |
290 __ Drop(argument_count); | 314 __ Drop(argument_count); |
291 } | 315 } |
292 | 316 |
293 | 317 |
294 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 318 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
295 bool opt) const { | 319 bool opt) const { |
296 return LocationSummary::Make(zone, | 320 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), |
297 0, | |
298 Location::RequiresRegister(), | |
299 LocationSummary::kNoCall); | 321 LocationSummary::kNoCall); |
300 } | 322 } |
301 | 323 |
302 | 324 |
303 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 325 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
304 __ Comment("LoadLocalInstr"); | 326 __ Comment("LoadLocalInstr"); |
305 Register result = locs()->out(0).reg(); | 327 Register result = locs()->out(0).reg(); |
306 __ LoadFromOffset(result, FP, local().index() * kWordSize); | 328 __ LoadFromOffset(result, FP, local().index() * kWordSize); |
307 } | 329 } |
308 | 330 |
309 | 331 |
310 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 332 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |
311 bool opt) const { | 333 bool opt) const { |
312 return LocationSummary::Make(zone, | 334 return LocationSummary::Make(zone, 1, Location::SameAsFirstInput(), |
313 1, | |
314 Location::SameAsFirstInput(), | |
315 LocationSummary::kNoCall); | 335 LocationSummary::kNoCall); |
316 } | 336 } |
317 | 337 |
318 | 338 |
319 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 339 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
320 __ Comment("StoreLocalInstr"); | 340 __ Comment("StoreLocalInstr"); |
321 Register value = locs()->in(0).reg(); | 341 Register value = locs()->in(0).reg(); |
322 Register result = locs()->out(0).reg(); | 342 Register result = locs()->out(0).reg(); |
323 ASSERT(result == value); // Assert that register assignment is correct. | 343 ASSERT(result == value); // Assert that register assignment is correct. |
324 __ StoreToOffset(value, FP, local().index() * kWordSize); | 344 __ StoreToOffset(value, FP, local().index() * kWordSize); |
325 } | 345 } |
326 | 346 |
327 | 347 |
328 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 348 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |
329 bool opt) const { | 349 bool opt) const { |
330 return LocationSummary::Make(zone, | 350 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), |
331 0, | |
332 Location::RequiresRegister(), | |
333 LocationSummary::kNoCall); | 351 LocationSummary::kNoCall); |
334 } | 352 } |
335 | 353 |
336 | 354 |
337 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 355 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
338 // The register allocator drops constant definitions that have no uses. | 356 // The register allocator drops constant definitions that have no uses. |
339 if (!locs()->out(0).IsInvalid()) { | 357 if (!locs()->out(0).IsInvalid()) { |
340 __ Comment("ConstantInstr"); | 358 __ Comment("ConstantInstr"); |
341 Register result = locs()->out(0).reg(); | 359 Register result = locs()->out(0).reg(); |
342 __ LoadObject(result, value()); | 360 __ LoadObject(result, value()); |
343 } | 361 } |
344 } | 362 } |
345 | 363 |
346 | 364 |
347 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 365 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
348 bool opt) const { | 366 bool opt) const { |
349 const intptr_t kNumInputs = 0; | 367 const intptr_t kNumInputs = 0; |
350 const intptr_t kNumTemps = (representation_ == kUnboxedInt32) ? 0 : 1; | 368 const intptr_t kNumTemps = (representation_ == kUnboxedInt32) ? 0 : 1; |
351 LocationSummary* locs = new(zone) LocationSummary( | 369 LocationSummary* locs = new (zone) |
352 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 370 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
353 if (representation_ == kUnboxedInt32) { | 371 if (representation_ == kUnboxedInt32) { |
354 locs->set_out(0, Location::RequiresRegister()); | 372 locs->set_out(0, Location::RequiresRegister()); |
355 } else { | 373 } else { |
356 ASSERT(representation_ == kUnboxedDouble); | 374 ASSERT(representation_ == kUnboxedDouble); |
357 locs->set_out(0, Location::RequiresFpuRegister()); | 375 locs->set_out(0, Location::RequiresFpuRegister()); |
358 } | 376 } |
359 if (kNumTemps > 0) { | 377 if (kNumTemps > 0) { |
360 locs->set_temp(0, Location::RequiresRegister()); | 378 locs->set_temp(0, Location::RequiresRegister()); |
361 } | 379 } |
362 return locs; | 380 return locs; |
363 } | 381 } |
364 | 382 |
365 | 383 |
366 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 384 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
367 // The register allocator drops constant definitions that have no uses. | 385 // The register allocator drops constant definitions that have no uses. |
368 if (!locs()->out(0).IsInvalid()) { | 386 if (!locs()->out(0).IsInvalid()) { |
369 switch (representation_) { | 387 switch (representation_) { |
370 case kUnboxedDouble: { | 388 case kUnboxedDouble: { |
371 ASSERT(value().IsDouble()); | 389 ASSERT(value().IsDouble()); |
372 const Register const_value = locs()->temp(0).reg(); | 390 const Register const_value = locs()->temp(0).reg(); |
373 const DRegister result = locs()->out(0).fpu_reg(); | 391 const DRegister result = locs()->out(0).fpu_reg(); |
374 __ LoadObject(const_value, value()); | 392 __ LoadObject(const_value, value()); |
375 __ LoadDFromOffset(result, const_value, | 393 __ LoadDFromOffset(result, const_value, |
376 Double::value_offset() - kHeapObjectTag); | 394 Double::value_offset() - kHeapObjectTag); |
377 break; | 395 break; |
378 } | 396 } |
379 | 397 |
380 case kUnboxedInt32: | 398 case kUnboxedInt32: |
381 __ LoadImmediate(locs()->out(0).reg(), | 399 __ LoadImmediate(locs()->out(0).reg(), Smi::Cast(value()).Value()); |
382 Smi::Cast(value()).Value()); | |
383 break; | 400 break; |
384 | 401 |
385 default: | 402 default: |
386 UNREACHABLE(); | 403 UNREACHABLE(); |
387 } | 404 } |
388 } | 405 } |
389 } | 406 } |
390 | 407 |
391 | 408 |
392 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 409 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
393 bool opt) const { | 410 bool opt) const { |
394 const intptr_t kNumInputs = 2; | 411 const intptr_t kNumInputs = 2; |
395 const intptr_t kNumTemps = 0; | 412 const intptr_t kNumTemps = 0; |
396 LocationSummary* summary = new(zone) LocationSummary( | 413 LocationSummary* summary = new (zone) |
397 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 414 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
398 summary->set_in(0, Location::RegisterLocation(A0)); // Value. | 415 summary->set_in(0, Location::RegisterLocation(A0)); // Value. |
399 summary->set_in(1, Location::RegisterLocation(A1)); // Type arguments. | 416 summary->set_in(1, Location::RegisterLocation(A1)); // Type arguments. |
400 summary->set_out(0, Location::RegisterLocation(A0)); | 417 summary->set_out(0, Location::RegisterLocation(A0)); |
401 return summary; | 418 return summary; |
402 } | 419 } |
403 | 420 |
404 | 421 |
405 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 422 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
406 bool opt) const { | 423 bool opt) const { |
407 const intptr_t kNumInputs = 1; | 424 const intptr_t kNumInputs = 1; |
408 const intptr_t kNumTemps = 0; | 425 const intptr_t kNumTemps = 0; |
409 LocationSummary* locs = new(zone) LocationSummary( | 426 LocationSummary* locs = new (zone) |
410 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 427 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
411 locs->set_in(0, Location::RegisterLocation(A0)); | 428 locs->set_in(0, Location::RegisterLocation(A0)); |
412 locs->set_out(0, Location::RegisterLocation(A0)); | 429 locs->set_out(0, Location::RegisterLocation(A0)); |
413 return locs; | 430 return locs; |
414 } | 431 } |
415 | 432 |
416 | 433 |
417 static void EmitAssertBoolean(Register reg, | 434 static void EmitAssertBoolean(Register reg, |
418 TokenPosition token_pos, | 435 TokenPosition token_pos, |
419 intptr_t deopt_id, | 436 intptr_t deopt_id, |
420 LocationSummary* locs, | 437 LocationSummary* locs, |
421 FlowGraphCompiler* compiler) { | 438 FlowGraphCompiler* compiler) { |
422 // Check that the type of the value is allowed in conditional context. | 439 // Check that the type of the value is allowed in conditional context. |
423 // Call the runtime if the object is not bool::true or bool::false. | 440 // Call the runtime if the object is not bool::true or bool::false. |
424 ASSERT(locs->always_calls()); | 441 ASSERT(locs->always_calls()); |
425 Label done; | 442 Label done; |
426 | 443 |
427 if (Isolate::Current()->type_checks()) { | 444 if (Isolate::Current()->type_checks()) { |
428 __ BranchEqual(reg, Bool::True(), &done); | 445 __ BranchEqual(reg, Bool::True(), &done); |
429 __ BranchEqual(reg, Bool::False(), &done); | 446 __ BranchEqual(reg, Bool::False(), &done); |
430 } else { | 447 } else { |
431 ASSERT(Isolate::Current()->asserts()); | 448 ASSERT(Isolate::Current()->asserts()); |
432 __ BranchNotEqual(reg, Object::null_instance(), &done); | 449 __ BranchNotEqual(reg, Object::null_instance(), &done); |
433 } | 450 } |
434 | 451 |
435 __ Push(reg); // Push the source object. | 452 __ Push(reg); // Push the source object. |
436 compiler->GenerateRuntimeCall(token_pos, | 453 compiler->GenerateRuntimeCall(token_pos, deopt_id, |
437 deopt_id, | 454 kNonBoolTypeErrorRuntimeEntry, 1, locs); |
438 kNonBoolTypeErrorRuntimeEntry, | |
439 1, | |
440 locs); | |
441 // We should never return here. | 455 // We should never return here. |
442 __ break_(0); | 456 __ break_(0); |
443 __ Bind(&done); | 457 __ Bind(&done); |
444 } | 458 } |
445 | 459 |
446 | 460 |
447 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 461 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
448 Register obj = locs()->in(0).reg(); | 462 Register obj = locs()->in(0).reg(); |
449 Register result = locs()->out(0).reg(); | 463 Register result = locs()->out(0).reg(); |
450 | 464 |
451 __ Comment("AssertBooleanInstr"); | 465 __ Comment("AssertBooleanInstr"); |
452 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 466 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
453 ASSERT(obj == result); | 467 ASSERT(obj == result); |
454 } | 468 } |
455 | 469 |
456 | 470 |
457 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 471 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |
458 bool opt) const { | 472 bool opt) const { |
459 const intptr_t kNumInputs = 2; | 473 const intptr_t kNumInputs = 2; |
460 if (operation_cid() == kMintCid) { | 474 if (operation_cid() == kMintCid) { |
461 const intptr_t kNumTemps = 0; | 475 const intptr_t kNumTemps = 0; |
462 LocationSummary* locs = new(zone) LocationSummary( | 476 LocationSummary* locs = new (zone) |
463 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 477 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
464 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 478 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
465 Location::RequiresRegister())); | 479 Location::RequiresRegister())); |
466 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 480 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
467 Location::RequiresRegister())); | 481 Location::RequiresRegister())); |
468 locs->set_out(0, Location::RequiresRegister()); | 482 locs->set_out(0, Location::RequiresRegister()); |
469 return locs; | 483 return locs; |
470 } | 484 } |
471 if (operation_cid() == kDoubleCid) { | 485 if (operation_cid() == kDoubleCid) { |
472 const intptr_t kNumTemps = 0; | 486 const intptr_t kNumTemps = 0; |
473 LocationSummary* locs = new(zone) LocationSummary( | 487 LocationSummary* locs = new (zone) |
474 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 488 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
475 locs->set_in(0, Location::RequiresFpuRegister()); | 489 locs->set_in(0, Location::RequiresFpuRegister()); |
476 locs->set_in(1, Location::RequiresFpuRegister()); | 490 locs->set_in(1, Location::RequiresFpuRegister()); |
477 locs->set_out(0, Location::RequiresRegister()); | 491 locs->set_out(0, Location::RequiresRegister()); |
478 return locs; | 492 return locs; |
479 } | 493 } |
480 if (operation_cid() == kSmiCid) { | 494 if (operation_cid() == kSmiCid) { |
481 const intptr_t kNumTemps = 0; | 495 const intptr_t kNumTemps = 0; |
482 LocationSummary* locs = new(zone) LocationSummary( | 496 LocationSummary* locs = new (zone) |
483 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 497 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
484 locs->set_in(0, Location::RegisterOrConstant(left())); | 498 locs->set_in(0, Location::RegisterOrConstant(left())); |
485 // Only one input can be a constant operand. The case of two constant | 499 // Only one input can be a constant operand. The case of two constant |
486 // operands should be handled by constant propagation. | 500 // operands should be handled by constant propagation. |
487 locs->set_in(1, locs->in(0).IsConstant() | 501 locs->set_in(1, locs->in(0).IsConstant() |
488 ? Location::RequiresRegister() | 502 ? Location::RequiresRegister() |
489 : Location::RegisterOrConstant(right())); | 503 : Location::RegisterOrConstant(right())); |
490 locs->set_out(0, Location::RequiresRegister()); | 504 locs->set_out(0, Location::RequiresRegister()); |
491 return locs; | 505 return locs; |
492 } | 506 } |
493 UNREACHABLE(); | 507 UNREACHABLE(); |
(...skipping 16 matching lines...) Expand all Loading... |
510 } else { | 524 } else { |
511 __ beq(CMPRES1, ZR, value_is_smi); | 525 __ beq(CMPRES1, ZR, value_is_smi); |
512 } | 526 } |
513 __ LoadClassId(value_cid_reg, value_reg); | 527 __ LoadClassId(value_cid_reg, value_reg); |
514 __ Bind(&done); | 528 __ Bind(&done); |
515 } | 529 } |
516 | 530 |
517 | 531 |
518 static RelationOperator TokenKindToIntRelOp(Token::Kind kind) { | 532 static RelationOperator TokenKindToIntRelOp(Token::Kind kind) { |
519 switch (kind) { | 533 switch (kind) { |
520 case Token::kEQ: return EQ; | 534 case Token::kEQ: |
521 case Token::kNE: return NE; | 535 return EQ; |
522 case Token::kLT: return LT; | 536 case Token::kNE: |
523 case Token::kGT: return GT; | 537 return NE; |
524 case Token::kLTE: return LE; | 538 case Token::kLT: |
525 case Token::kGTE: return GE; | 539 return LT; |
| 540 case Token::kGT: |
| 541 return GT; |
| 542 case Token::kLTE: |
| 543 return LE; |
| 544 case Token::kGTE: |
| 545 return GE; |
526 default: | 546 default: |
527 UNREACHABLE(); | 547 UNREACHABLE(); |
528 return NV; | 548 return NV; |
529 } | 549 } |
530 } | 550 } |
531 | 551 |
532 | 552 |
533 static RelationOperator TokenKindToUintRelOp(Token::Kind kind) { | 553 static RelationOperator TokenKindToUintRelOp(Token::Kind kind) { |
534 switch (kind) { | 554 switch (kind) { |
535 case Token::kEQ: return EQ; | 555 case Token::kEQ: |
536 case Token::kNE: return NE; | 556 return EQ; |
537 case Token::kLT: return ULT; | 557 case Token::kNE: |
538 case Token::kGT: return UGT; | 558 return NE; |
539 case Token::kLTE: return ULE; | 559 case Token::kLT: |
540 case Token::kGTE: return UGE; | 560 return ULT; |
| 561 case Token::kGT: |
| 562 return UGT; |
| 563 case Token::kLTE: |
| 564 return ULE; |
| 565 case Token::kGTE: |
| 566 return UGE; |
541 default: | 567 default: |
542 UNREACHABLE(); | 568 UNREACHABLE(); |
543 return NV; | 569 return NV; |
544 } | 570 } |
545 } | 571 } |
546 | 572 |
547 | 573 |
548 // The comparison code to emit is specified by true_condition. | 574 // The comparison code to emit is specified by true_condition. |
549 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 575 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
550 Condition true_condition, | 576 Condition true_condition, |
(...skipping 18 matching lines...) Expand all Loading... |
569 const LocationSummary& locs, | 595 const LocationSummary& locs, |
570 Token::Kind kind) { | 596 Token::Kind kind) { |
571 __ Comment("EmitSmiComparisonOp"); | 597 __ Comment("EmitSmiComparisonOp"); |
572 const Location left = locs.in(0); | 598 const Location left = locs.in(0); |
573 const Location right = locs.in(1); | 599 const Location right = locs.in(1); |
574 ASSERT(!left.IsConstant() || !right.IsConstant()); | 600 ASSERT(!left.IsConstant() || !right.IsConstant()); |
575 ASSERT(left.IsRegister() || left.IsConstant()); | 601 ASSERT(left.IsRegister() || left.IsConstant()); |
576 ASSERT(right.IsRegister() || right.IsConstant()); | 602 ASSERT(right.IsRegister() || right.IsConstant()); |
577 | 603 |
578 int16_t imm = 0; | 604 int16_t imm = 0; |
579 const Register left_reg = left.IsRegister() ? | 605 const Register left_reg = |
580 left.reg() : __ LoadConditionOperand(CMPRES1, left.constant(), &imm); | 606 left.IsRegister() ? left.reg() : __ LoadConditionOperand( |
581 const Register right_reg = right.IsRegister() ? | 607 CMPRES1, left.constant(), &imm); |
582 right.reg() : __ LoadConditionOperand(CMPRES2, right.constant(), &imm); | 608 const Register right_reg = |
| 609 right.IsRegister() ? right.reg() : __ LoadConditionOperand( |
| 610 CMPRES2, right.constant(), &imm); |
583 return Condition(left_reg, right_reg, TokenKindToIntRelOp(kind), imm); | 611 return Condition(left_reg, right_reg, TokenKindToIntRelOp(kind), imm); |
584 } | 612 } |
585 | 613 |
586 | 614 |
587 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 615 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
588 const LocationSummary& locs, | 616 const LocationSummary& locs, |
589 Token::Kind kind, | 617 Token::Kind kind, |
590 BranchLabels labels) { | 618 BranchLabels labels) { |
591 __ Comment("EmitUnboxedMintEqualityOp"); | 619 __ Comment("EmitUnboxedMintEqualityOp"); |
592 ASSERT(Token::IsEqualityOperator(kind)); | 620 ASSERT(Token::IsEqualityOperator(kind)); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 698 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
671 const LocationSummary& locs, | 699 const LocationSummary& locs, |
672 Token::Kind kind, | 700 Token::Kind kind, |
673 BranchLabels labels) { | 701 BranchLabels labels) { |
674 DRegister left = locs.in(0).fpu_reg(); | 702 DRegister left = locs.in(0).fpu_reg(); |
675 DRegister right = locs.in(1).fpu_reg(); | 703 DRegister right = locs.in(1).fpu_reg(); |
676 | 704 |
677 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right); | 705 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right); |
678 | 706 |
679 __ cund(left, right); | 707 __ cund(left, right); |
680 Label* nan_label = (kind == Token::kNE) | 708 Label* nan_label = |
681 ? labels.true_label : labels.false_label; | 709 (kind == Token::kNE) ? labels.true_label : labels.false_label; |
682 __ bc1t(nan_label); | 710 __ bc1t(nan_label); |
683 | 711 |
684 switch (kind) { | 712 switch (kind) { |
685 case Token::kEQ: __ ceqd(left, right); break; | 713 case Token::kEQ: |
686 case Token::kNE: __ ceqd(left, right); break; | 714 __ ceqd(left, right); |
687 case Token::kLT: __ coltd(left, right); break; | 715 break; |
688 case Token::kLTE: __ coled(left, right); break; | 716 case Token::kNE: |
689 case Token::kGT: __ coltd(right, left); break; | 717 __ ceqd(left, right); |
690 case Token::kGTE: __ coled(right, left); break; | 718 break; |
| 719 case Token::kLT: |
| 720 __ coltd(left, right); |
| 721 break; |
| 722 case Token::kLTE: |
| 723 __ coled(left, right); |
| 724 break; |
| 725 case Token::kGT: |
| 726 __ coltd(right, left); |
| 727 break; |
| 728 case Token::kGTE: |
| 729 __ coled(right, left); |
| 730 break; |
691 default: { | 731 default: { |
692 // We should only be passing the above conditions to this function. | 732 // We should only be passing the above conditions to this function. |
693 UNREACHABLE(); | 733 UNREACHABLE(); |
694 break; | 734 break; |
695 } | 735 } |
696 } | 736 } |
697 | 737 |
698 if (labels.false_label == NULL) { | 738 if (labels.false_label == NULL) { |
699 // Generate branch-free code and return result in condition. | 739 // Generate branch-free code and return result in condition. |
700 __ LoadImmediate(CMPRES1, 1); | 740 __ LoadImmediate(CMPRES1, 1); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 777 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
738 } | 778 } |
739 } | 779 } |
740 | 780 |
741 | 781 |
742 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 782 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
743 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 783 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
744 __ Comment("EqualityCompareInstr"); | 784 __ Comment("EqualityCompareInstr"); |
745 | 785 |
746 Label is_true, is_false; | 786 Label is_true, is_false; |
747 BranchLabels labels = { &is_true, &is_false, &is_false }; | 787 BranchLabels labels = {&is_true, &is_false, &is_false}; |
748 Condition true_condition = EmitComparisonCode(compiler, labels); | 788 Condition true_condition = EmitComparisonCode(compiler, labels); |
749 EmitBranchOnCondition(compiler, true_condition, labels); | 789 EmitBranchOnCondition(compiler, true_condition, labels); |
750 | 790 |
751 Register result = locs()->out(0).reg(); | 791 Register result = locs()->out(0).reg(); |
752 Label done; | 792 Label done; |
753 __ Bind(&is_false); | 793 __ Bind(&is_false); |
754 __ LoadObject(result, Bool::False()); | 794 __ LoadObject(result, Bool::False()); |
755 __ b(&done); | 795 __ b(&done); |
756 __ Bind(&is_true); | 796 __ Bind(&is_true); |
757 __ LoadObject(result, Bool::True()); | 797 __ LoadObject(result, Bool::True()); |
758 __ Bind(&done); | 798 __ Bind(&done); |
759 } | 799 } |
760 | 800 |
761 | 801 |
762 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 802 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
763 BranchInstr* branch) { | 803 BranchInstr* branch) { |
764 __ Comment("EqualityCompareInstr::EmitBranchCode"); | 804 __ Comment("EqualityCompareInstr::EmitBranchCode"); |
765 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 805 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
766 | 806 |
767 BranchLabels labels = compiler->CreateBranchLabels(branch); | 807 BranchLabels labels = compiler->CreateBranchLabels(branch); |
768 Condition true_condition = EmitComparisonCode(compiler, labels); | 808 Condition true_condition = EmitComparisonCode(compiler, labels); |
769 EmitBranchOnCondition(compiler, true_condition, labels); | 809 EmitBranchOnCondition(compiler, true_condition, labels); |
770 } | 810 } |
771 | 811 |
772 | 812 |
773 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, | 813 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
774 bool opt) const { | |
775 const intptr_t kNumInputs = 2; | 814 const intptr_t kNumInputs = 2; |
776 const intptr_t kNumTemps = 0; | 815 const intptr_t kNumTemps = 0; |
777 LocationSummary* locs = new(zone) LocationSummary( | 816 LocationSummary* locs = new (zone) |
778 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 817 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
779 locs->set_in(0, Location::RequiresRegister()); | 818 locs->set_in(0, Location::RequiresRegister()); |
780 // Only one input can be a constant operand. The case of two constant | 819 // Only one input can be a constant operand. The case of two constant |
781 // operands should be handled by constant propagation. | 820 // operands should be handled by constant propagation. |
782 locs->set_in(1, Location::RegisterOrConstant(right())); | 821 locs->set_in(1, Location::RegisterOrConstant(right())); |
783 return locs; | 822 return locs; |
784 } | 823 } |
785 | 824 |
786 | 825 |
787 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 826 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
788 BranchLabels labels) { | 827 BranchLabels labels) { |
789 Register left = locs()->in(0).reg(); | 828 Register left = locs()->in(0).reg(); |
790 Location right = locs()->in(1); | 829 Location right = locs()->in(1); |
791 if (right.IsConstant()) { | 830 if (right.IsConstant()) { |
792 ASSERT(right.constant().IsSmi()); | 831 ASSERT(right.constant().IsSmi()); |
793 const int32_t imm = | 832 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); |
794 reinterpret_cast<int32_t>(right.constant().raw()); | |
795 __ AndImmediate(CMPRES1, left, imm); | 833 __ AndImmediate(CMPRES1, left, imm); |
796 } else { | 834 } else { |
797 __ and_(CMPRES1, left, right.reg()); | 835 __ and_(CMPRES1, left, right.reg()); |
798 } | 836 } |
799 return Condition(CMPRES1, ZR, (kind() == Token::kNE) ? NE : EQ); | 837 return Condition(CMPRES1, ZR, (kind() == Token::kNE) ? NE : EQ); |
800 } | 838 } |
801 | 839 |
802 | 840 |
803 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 841 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
804 // Never emitted outside of the BranchInstr. | 842 // Never emitted outside of the BranchInstr. |
805 UNREACHABLE(); | 843 UNREACHABLE(); |
806 } | 844 } |
807 | 845 |
808 | 846 |
809 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 847 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
810 BranchInstr* branch) { | 848 BranchInstr* branch) { |
811 BranchLabels labels = compiler->CreateBranchLabels(branch); | 849 BranchLabels labels = compiler->CreateBranchLabels(branch); |
812 Condition true_condition = EmitComparisonCode(compiler, labels); | 850 Condition true_condition = EmitComparisonCode(compiler, labels); |
813 EmitBranchOnCondition(compiler, true_condition, labels); | 851 EmitBranchOnCondition(compiler, true_condition, labels); |
814 } | 852 } |
815 | 853 |
816 | 854 |
817 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 855 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
818 bool opt) const { | 856 bool opt) const { |
819 const intptr_t kNumInputs = 1; | 857 const intptr_t kNumInputs = 1; |
820 const intptr_t kNumTemps = 1; | 858 const intptr_t kNumTemps = 1; |
821 LocationSummary* locs = new(zone) LocationSummary( | 859 LocationSummary* locs = new (zone) |
822 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 860 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
823 locs->set_in(0, Location::RequiresRegister()); | 861 locs->set_in(0, Location::RequiresRegister()); |
824 locs->set_temp(0, Location::RequiresRegister()); | 862 locs->set_temp(0, Location::RequiresRegister()); |
825 locs->set_out(0, Location::RequiresRegister()); | 863 locs->set_out(0, Location::RequiresRegister()); |
826 return locs; | 864 return locs; |
827 } | 865 } |
828 | 866 |
829 | 867 |
830 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 868 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
831 BranchLabels labels) { | 869 BranchLabels labels) { |
832 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 870 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
833 Register val_reg = locs()->in(0).reg(); | 871 Register val_reg = locs()->in(0).reg(); |
834 Register cid_reg = locs()->temp(0).reg(); | 872 Register cid_reg = locs()->temp(0).reg(); |
835 | 873 |
836 Label* deopt = CanDeoptimize() | 874 Label* deopt = |
837 ? compiler->AddDeoptStub(deopt_id(), | 875 CanDeoptimize() |
838 ICData::kDeoptTestCids, | 876 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, |
839 licm_hoisted_ ? ICData::kHoisted : 0) | 877 licm_hoisted_ ? ICData::kHoisted : 0) |
840 : NULL; | 878 : NULL; |
841 | 879 |
842 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 880 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
843 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 881 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
844 ASSERT(data[0] == kSmiCid); | 882 ASSERT(data[0] == kSmiCid); |
845 bool result = data[1] == true_result; | 883 bool result = data[1] == true_result; |
846 __ andi(CMPRES1, val_reg, Immediate(kSmiTagMask)); | 884 __ andi(CMPRES1, val_reg, Immediate(kSmiTagMask)); |
847 __ beq(CMPRES1, ZR, result ? labels.true_label : labels.false_label); | 885 __ beq(CMPRES1, ZR, result ? labels.true_label : labels.false_label); |
848 | 886 |
849 __ LoadClassId(cid_reg, val_reg); | 887 __ LoadClassId(cid_reg, val_reg); |
850 for (intptr_t i = 2; i < data.length(); i += 2) { | 888 for (intptr_t i = 2; i < data.length(); i += 2) { |
(...skipping 20 matching lines...) Expand all Loading... |
871 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 909 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
872 BranchInstr* branch) { | 910 BranchInstr* branch) { |
873 BranchLabels labels = compiler->CreateBranchLabels(branch); | 911 BranchLabels labels = compiler->CreateBranchLabels(branch); |
874 EmitComparisonCode(compiler, labels); | 912 EmitComparisonCode(compiler, labels); |
875 } | 913 } |
876 | 914 |
877 | 915 |
878 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 916 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
879 Register result_reg = locs()->out(0).reg(); | 917 Register result_reg = locs()->out(0).reg(); |
880 Label is_true, is_false, done; | 918 Label is_true, is_false, done; |
881 BranchLabels labels = { &is_true, &is_false, &is_false }; | 919 BranchLabels labels = {&is_true, &is_false, &is_false}; |
882 EmitComparisonCode(compiler, labels); | 920 EmitComparisonCode(compiler, labels); |
883 __ Bind(&is_false); | 921 __ Bind(&is_false); |
884 __ LoadObject(result_reg, Bool::False()); | 922 __ LoadObject(result_reg, Bool::False()); |
885 __ b(&done); | 923 __ b(&done); |
886 __ Bind(&is_true); | 924 __ Bind(&is_true); |
887 __ LoadObject(result_reg, Bool::True()); | 925 __ LoadObject(result_reg, Bool::True()); |
888 __ Bind(&done); | 926 __ Bind(&done); |
889 } | 927 } |
890 | 928 |
891 | 929 |
892 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 930 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
893 bool opt) const { | 931 bool opt) const { |
894 const intptr_t kNumInputs = 2; | 932 const intptr_t kNumInputs = 2; |
895 const intptr_t kNumTemps = 0; | 933 const intptr_t kNumTemps = 0; |
896 if (operation_cid() == kMintCid) { | 934 if (operation_cid() == kMintCid) { |
897 const intptr_t kNumTemps = 0; | 935 const intptr_t kNumTemps = 0; |
898 LocationSummary* locs = new(zone) LocationSummary( | 936 LocationSummary* locs = new (zone) |
899 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 937 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
900 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 938 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
901 Location::RequiresRegister())); | 939 Location::RequiresRegister())); |
902 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 940 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
903 Location::RequiresRegister())); | 941 Location::RequiresRegister())); |
904 locs->set_out(0, Location::RequiresRegister()); | 942 locs->set_out(0, Location::RequiresRegister()); |
905 return locs; | 943 return locs; |
906 } | 944 } |
907 if (operation_cid() == kDoubleCid) { | 945 if (operation_cid() == kDoubleCid) { |
908 LocationSummary* summary = new(zone) LocationSummary( | 946 LocationSummary* summary = new (zone) |
909 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 947 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
910 summary->set_in(0, Location::RequiresFpuRegister()); | 948 summary->set_in(0, Location::RequiresFpuRegister()); |
911 summary->set_in(1, Location::RequiresFpuRegister()); | 949 summary->set_in(1, Location::RequiresFpuRegister()); |
912 summary->set_out(0, Location::RequiresRegister()); | 950 summary->set_out(0, Location::RequiresRegister()); |
913 return summary; | 951 return summary; |
914 } | 952 } |
915 ASSERT(operation_cid() == kSmiCid); | 953 ASSERT(operation_cid() == kSmiCid); |
916 LocationSummary* summary = new(zone) LocationSummary( | 954 LocationSummary* summary = new (zone) |
917 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 955 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
918 summary->set_in(0, Location::RegisterOrConstant(left())); | 956 summary->set_in(0, Location::RegisterOrConstant(left())); |
919 // Only one input can be a constant operand. The case of two constant | 957 // Only one input can be a constant operand. The case of two constant |
920 // operands should be handled by constant propagation. | 958 // operands should be handled by constant propagation. |
921 summary->set_in(1, summary->in(0).IsConstant() | 959 summary->set_in(1, summary->in(0).IsConstant() |
922 ? Location::RequiresRegister() | 960 ? Location::RequiresRegister() |
923 : Location::RegisterOrConstant(right())); | 961 : Location::RegisterOrConstant(right())); |
924 summary->set_out(0, Location::RequiresRegister()); | 962 summary->set_out(0, Location::RequiresRegister()); |
925 return summary; | 963 return summary; |
926 } | 964 } |
927 | 965 |
928 | 966 |
929 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 967 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
930 BranchLabels labels) { | 968 BranchLabels labels) { |
931 if (operation_cid() == kSmiCid) { | 969 if (operation_cid() == kSmiCid) { |
932 return EmitSmiComparisonOp(compiler, *locs(), kind()); | 970 return EmitSmiComparisonOp(compiler, *locs(), kind()); |
933 } else if (operation_cid() == kMintCid) { | 971 } else if (operation_cid() == kMintCid) { |
934 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); | 972 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); |
935 } else { | 973 } else { |
936 ASSERT(operation_cid() == kDoubleCid); | 974 ASSERT(operation_cid() == kDoubleCid); |
937 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 975 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
938 } | 976 } |
939 } | 977 } |
940 | 978 |
941 | 979 |
942 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 980 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
943 __ Comment("RelationalOpInstr"); | 981 __ Comment("RelationalOpInstr"); |
944 | 982 |
945 Label is_true, is_false; | 983 Label is_true, is_false; |
946 BranchLabels labels = { &is_true, &is_false, &is_false }; | 984 BranchLabels labels = {&is_true, &is_false, &is_false}; |
947 Condition true_condition = EmitComparisonCode(compiler, labels); | 985 Condition true_condition = EmitComparisonCode(compiler, labels); |
948 EmitBranchOnCondition(compiler, true_condition, labels); | 986 EmitBranchOnCondition(compiler, true_condition, labels); |
949 | 987 |
950 Register result = locs()->out(0).reg(); | 988 Register result = locs()->out(0).reg(); |
951 Label done; | 989 Label done; |
952 __ Bind(&is_false); | 990 __ Bind(&is_false); |
953 __ LoadObject(result, Bool::False()); | 991 __ LoadObject(result, Bool::False()); |
954 __ b(&done); | 992 __ b(&done); |
955 __ Bind(&is_true); | 993 __ Bind(&is_true); |
956 __ LoadObject(result, Bool::True()); | 994 __ LoadObject(result, Bool::True()); |
(...skipping 19 matching lines...) Expand all Loading... |
976 | 1014 |
977 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1015 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
978 SetupNative(); | 1016 SetupNative(); |
979 __ Comment("NativeCallInstr"); | 1017 __ Comment("NativeCallInstr"); |
980 Register result = locs()->out(0).reg(); | 1018 Register result = locs()->out(0).reg(); |
981 | 1019 |
982 // Push the result place holder initialized to NULL. | 1020 // Push the result place holder initialized to NULL. |
983 __ PushObject(Object::null_object()); | 1021 __ PushObject(Object::null_object()); |
984 // Pass a pointer to the first argument in A2. | 1022 // Pass a pointer to the first argument in A2. |
985 if (!function().HasOptionalParameters()) { | 1023 if (!function().HasOptionalParameters()) { |
986 __ AddImmediate(A2, FP, (kParamEndSlotFromFp + | 1024 __ AddImmediate( |
987 function().NumParameters()) * kWordSize); | 1025 A2, FP, (kParamEndSlotFromFp + function().NumParameters()) * kWordSize); |
988 } else { | 1026 } else { |
989 __ AddImmediate(A2, FP, kFirstLocalSlotFromFp * kWordSize); | 1027 __ AddImmediate(A2, FP, kFirstLocalSlotFromFp * kWordSize); |
990 } | 1028 } |
991 // Compute the effective address. When running under the simulator, | 1029 // Compute the effective address. When running under the simulator, |
992 // this is a redirection address that forces the simulator to call | 1030 // this is a redirection address that forces the simulator to call |
993 // into the runtime system. | 1031 // into the runtime system. |
994 uword entry; | 1032 uword entry; |
995 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 1033 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
996 const StubEntry* stub_entry; | 1034 const StubEntry* stub_entry; |
997 if (link_lazily()) { | 1035 if (link_lazily()) { |
(...skipping 10 matching lines...) Expand all Loading... |
1008 } else { | 1046 } else { |
1009 // In the case of non bootstrap native methods the CallNativeCFunction | 1047 // In the case of non bootstrap native methods the CallNativeCFunction |
1010 // stub generates the redirection address when running under the simulator | 1048 // stub generates the redirection address when running under the simulator |
1011 // and hence we do not change 'entry' here. | 1049 // and hence we do not change 'entry' here. |
1012 stub_entry = StubCode::CallNativeCFunction_entry(); | 1050 stub_entry = StubCode::CallNativeCFunction_entry(); |
1013 } | 1051 } |
1014 } | 1052 } |
1015 __ LoadImmediate(A1, argc_tag); | 1053 __ LoadImmediate(A1, argc_tag); |
1016 ExternalLabel label(entry); | 1054 ExternalLabel label(entry); |
1017 __ LoadNativeEntry(T5, &label, kNotPatchable); | 1055 __ LoadNativeEntry(T5, &label, kNotPatchable); |
1018 compiler->GenerateCall(token_pos(), | 1056 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, |
1019 *stub_entry, | |
1020 RawPcDescriptors::kOther, | |
1021 locs()); | 1057 locs()); |
1022 __ Pop(result); | 1058 __ Pop(result); |
1023 } | 1059 } |
1024 | 1060 |
1025 | 1061 |
1026 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 1062 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |
1027 Zone* zone, bool opt) const { | 1063 Zone* zone, |
| 1064 bool opt) const { |
1028 const intptr_t kNumInputs = 1; | 1065 const intptr_t kNumInputs = 1; |
1029 // TODO(fschneider): Allow immediate operands for the char code. | 1066 // TODO(fschneider): Allow immediate operands for the char code. |
1030 return LocationSummary::Make(zone, | 1067 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
1031 kNumInputs, | |
1032 Location::RequiresRegister(), | |
1033 LocationSummary::kNoCall); | 1068 LocationSummary::kNoCall); |
1034 } | 1069 } |
1035 | 1070 |
1036 | 1071 |
1037 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 1072 void OneByteStringFromCharCodeInstr::EmitNativeCode( |
1038 FlowGraphCompiler* compiler) { | 1073 FlowGraphCompiler* compiler) { |
1039 ASSERT(compiler->is_optimizing()); | 1074 ASSERT(compiler->is_optimizing()); |
1040 Register char_code = locs()->in(0).reg(); | 1075 Register char_code = locs()->in(0).reg(); |
1041 Register result = locs()->out(0).reg(); | 1076 Register result = locs()->out(0).reg(); |
1042 | 1077 |
1043 __ lw(result, Address(THR, Thread::predefined_symbols_address_offset())); | 1078 __ lw(result, Address(THR, Thread::predefined_symbols_address_offset())); |
1044 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); | 1079 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); |
1045 __ sll(TMP, char_code, 1); // Char code is a smi. | 1080 __ sll(TMP, char_code, 1); // Char code is a smi. |
1046 __ addu(TMP, TMP, result); | 1081 __ addu(TMP, TMP, result); |
1047 __ lw(result, Address(TMP)); | 1082 __ lw(result, Address(TMP)); |
1048 } | 1083 } |
1049 | 1084 |
1050 | 1085 |
1051 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 1086 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
1052 bool opt) const { | 1087 bool opt) const { |
1053 const intptr_t kNumInputs = 1; | 1088 const intptr_t kNumInputs = 1; |
1054 return LocationSummary::Make(zone, | 1089 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
1055 kNumInputs, | |
1056 Location::RequiresRegister(), | |
1057 LocationSummary::kNoCall); | 1090 LocationSummary::kNoCall); |
1058 } | 1091 } |
1059 | 1092 |
1060 | 1093 |
1061 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1094 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1062 __ Comment("StringToCharCodeInstr"); | 1095 __ Comment("StringToCharCodeInstr"); |
1063 | 1096 |
1064 ASSERT(cid_ == kOneByteStringCid); | 1097 ASSERT(cid_ == kOneByteStringCid); |
1065 Register str = locs()->in(0).reg(); | 1098 Register str = locs()->in(0).reg(); |
1066 Register result = locs()->out(0).reg(); | 1099 Register result = locs()->out(0).reg(); |
1067 ASSERT(str != result); | 1100 ASSERT(str != result); |
1068 Label done; | 1101 Label done; |
1069 __ lw(result, FieldAddress(str, String::length_offset())); | 1102 __ lw(result, FieldAddress(str, String::length_offset())); |
1070 __ BranchNotEqual(result, Immediate(Smi::RawValue(1)), &done); | 1103 __ BranchNotEqual(result, Immediate(Smi::RawValue(1)), &done); |
1071 __ delay_slot()->addiu(result, ZR, Immediate(Smi::RawValue(-1))); | 1104 __ delay_slot()->addiu(result, ZR, Immediate(Smi::RawValue(-1))); |
1072 __ lbu(result, FieldAddress(str, OneByteString::data_offset())); | 1105 __ lbu(result, FieldAddress(str, OneByteString::data_offset())); |
1073 __ SmiTag(result); | 1106 __ SmiTag(result); |
1074 __ Bind(&done); | 1107 __ Bind(&done); |
1075 } | 1108 } |
1076 | 1109 |
1077 | 1110 |
1078 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 1111 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |
1079 bool opt) const { | 1112 bool opt) const { |
1080 const intptr_t kNumInputs = 1; | 1113 const intptr_t kNumInputs = 1; |
1081 const intptr_t kNumTemps = 0; | 1114 const intptr_t kNumTemps = 0; |
1082 LocationSummary* summary = new(zone) LocationSummary( | 1115 LocationSummary* summary = new (zone) |
1083 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 1116 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
1084 summary->set_in(0, Location::RegisterLocation(A0)); | 1117 summary->set_in(0, Location::RegisterLocation(A0)); |
1085 summary->set_out(0, Location::RegisterLocation(V0)); | 1118 summary->set_out(0, Location::RegisterLocation(V0)); |
1086 return summary; | 1119 return summary; |
1087 } | 1120 } |
1088 | 1121 |
1089 | 1122 |
1090 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1123 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1091 Register array = locs()->in(0).reg(); | 1124 Register array = locs()->in(0).reg(); |
1092 __ Push(array); | 1125 __ Push(array); |
1093 const int kNumberOfArguments = 1; | 1126 const int kNumberOfArguments = 1; |
1094 const Array& kNoArgumentNames = Object::null_array(); | 1127 const Array& kNoArgumentNames = Object::null_array(); |
1095 compiler->GenerateStaticCall(deopt_id(), | 1128 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), |
1096 token_pos(), | 1129 kNumberOfArguments, kNoArgumentNames, locs(), |
1097 CallFunction(), | |
1098 kNumberOfArguments, | |
1099 kNoArgumentNames, | |
1100 locs(), | |
1101 ICData::Handle()); | 1130 ICData::Handle()); |
1102 ASSERT(locs()->out(0).reg() == V0); | 1131 ASSERT(locs()->out(0).reg() == V0); |
1103 } | 1132 } |
1104 | 1133 |
1105 | 1134 |
1106 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 1135 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |
1107 bool opt) const { | 1136 bool opt) const { |
1108 const intptr_t kNumInputs = 1; | 1137 const intptr_t kNumInputs = 1; |
1109 return LocationSummary::Make(zone, | 1138 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
1110 kNumInputs, | |
1111 Location::RequiresRegister(), | |
1112 LocationSummary::kNoCall); | 1139 LocationSummary::kNoCall); |
1113 } | 1140 } |
1114 | 1141 |
1115 | 1142 |
1116 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1143 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1117 Register obj = locs()->in(0).reg(); | 1144 Register obj = locs()->in(0).reg(); |
1118 Register result = locs()->out(0).reg(); | 1145 Register result = locs()->out(0).reg(); |
1119 if (object()->definition()->representation() == kUntagged) { | 1146 if (object()->definition()->representation() == kUntagged) { |
1120 __ LoadFromOffset(result, obj, offset()); | 1147 __ LoadFromOffset(result, obj, offset()); |
1121 } else { | 1148 } else { |
1122 ASSERT(object()->definition()->representation() == kTagged); | 1149 ASSERT(object()->definition()->representation() == kTagged); |
1123 __ LoadFieldFromOffset(result, obj, offset()); | 1150 __ LoadFieldFromOffset(result, obj, offset()); |
1124 } | 1151 } |
1125 } | 1152 } |
1126 | 1153 |
1127 | 1154 |
1128 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 1155 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |
1129 bool opt) const { | 1156 bool opt) const { |
1130 const intptr_t kNumInputs = 1; | 1157 const intptr_t kNumInputs = 1; |
1131 return LocationSummary::Make(zone, | 1158 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
1132 kNumInputs, | |
1133 Location::RequiresRegister(), | |
1134 LocationSummary::kNoCall); | 1159 LocationSummary::kNoCall); |
1135 } | 1160 } |
1136 | 1161 |
1137 | 1162 |
1138 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1163 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1139 Register object = locs()->in(0).reg(); | 1164 Register object = locs()->in(0).reg(); |
1140 Register result = locs()->out(0).reg(); | 1165 Register result = locs()->out(0).reg(); |
1141 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 1166 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |
1142 if (CompileType::Smi().IsAssignableTo(value_type) || | 1167 if (CompileType::Smi().IsAssignableTo(value_type) || |
1143 value_type.IsTypeParameter()) { | 1168 value_type.IsTypeParameter()) { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1221 } | 1246 } |
1222 | 1247 |
1223 | 1248 |
1224 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) { | 1249 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) { |
1225 ConstantInstr* constant = value->definition()->AsConstant(); | 1250 ConstantInstr* constant = value->definition()->AsConstant(); |
1226 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) { | 1251 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) { |
1227 return false; | 1252 return false; |
1228 } | 1253 } |
1229 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); | 1254 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); |
1230 const intptr_t scale = Instance::ElementSizeFor(cid); | 1255 const intptr_t scale = Instance::ElementSizeFor(cid); |
1231 const int64_t offset = index * scale + | 1256 const int64_t offset = |
| 1257 index * scale + |
1232 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); | 1258 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); |
1233 if (!Utils::IsInt(32, offset)) { | 1259 if (!Utils::IsInt(32, offset)) { |
1234 return false; | 1260 return false; |
1235 } | 1261 } |
1236 return Address::CanHoldOffset(static_cast<int32_t>(offset)); | 1262 return Address::CanHoldOffset(static_cast<int32_t>(offset)); |
1237 } | 1263 } |
1238 | 1264 |
1239 | 1265 |
1240 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 1266 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
1241 bool opt) const { | 1267 bool opt) const { |
1242 const intptr_t kNumInputs = 2; | 1268 const intptr_t kNumInputs = 2; |
1243 const intptr_t kNumTemps = aligned() ? 0 : 1; | 1269 const intptr_t kNumTemps = aligned() ? 0 : 1; |
1244 LocationSummary* locs = new(zone) LocationSummary( | 1270 LocationSummary* locs = new (zone) |
1245 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1271 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1246 locs->set_in(0, Location::RequiresRegister()); | 1272 locs->set_in(0, Location::RequiresRegister()); |
1247 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { | 1273 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { |
1248 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1274 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
1249 } else { | 1275 } else { |
1250 locs->set_in(1, Location::RequiresRegister()); | 1276 locs->set_in(1, Location::RequiresRegister()); |
1251 } | 1277 } |
1252 if ((representation() == kUnboxedDouble) || | 1278 if ((representation() == kUnboxedDouble) || |
1253 (representation() == kUnboxedFloat32x4) || | 1279 (representation() == kUnboxedFloat32x4) || |
1254 (representation() == kUnboxedInt32x4)) { | 1280 (representation() == kUnboxedInt32x4)) { |
1255 locs->set_out(0, Location::RequiresFpuRegister()); | 1281 locs->set_out(0, Location::RequiresFpuRegister()); |
1256 } else { | 1282 } else { |
1257 locs->set_out(0, Location::RequiresRegister()); | 1283 locs->set_out(0, Location::RequiresRegister()); |
1258 } | 1284 } |
1259 if (!aligned()) { | 1285 if (!aligned()) { |
1260 locs->set_temp(0, Location::RequiresRegister()); | 1286 locs->set_temp(0, Location::RequiresRegister()); |
1261 } | 1287 } |
1262 return locs; | 1288 return locs; |
1263 } | 1289 } |
1264 | 1290 |
1265 | 1291 |
1266 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1292 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1267 __ Comment("LoadIndexedInstr"); | 1293 __ Comment("LoadIndexedInstr"); |
1268 // The array register points to the backing store for external arrays. | 1294 // The array register points to the backing store for external arrays. |
1269 const Register array = locs()->in(0).reg(); | 1295 const Register array = locs()->in(0).reg(); |
1270 const Location index = locs()->in(1); | 1296 const Location index = locs()->in(1); |
1271 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); | 1297 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |
1272 | 1298 |
1273 Address element_address(kNoRegister); | 1299 Address element_address(kNoRegister); |
1274 if (aligned()) { | 1300 if (aligned()) { |
1275 element_address = index.IsRegister() | 1301 element_address = |
1276 ? __ ElementAddressForRegIndex(true, // Load. | 1302 index.IsRegister() |
1277 IsExternal(), class_id(), index_scale(), | 1303 ? __ ElementAddressForRegIndex(true, // Load. |
1278 array, index.reg()) | 1304 IsExternal(), class_id(), |
1279 : __ ElementAddressForIntIndex( | 1305 index_scale(), array, index.reg()) |
1280 IsExternal(), class_id(), index_scale(), | 1306 : __ ElementAddressForIntIndex(IsExternal(), class_id(), |
1281 array, Smi::Cast(index.constant()).Value()); | 1307 index_scale(), array, |
| 1308 Smi::Cast(index.constant()).Value()); |
1282 // Warning: element_address may use register TMP as base. | 1309 // Warning: element_address may use register TMP as base. |
1283 } else { | 1310 } else { |
1284 if (index.IsRegister()) { | 1311 if (index.IsRegister()) { |
1285 __ LoadElementAddressForRegIndex(address, | 1312 __ LoadElementAddressForRegIndex(address, |
1286 true, // Load. | 1313 true, // Load. |
1287 IsExternal(), class_id(), index_scale(), | 1314 IsExternal(), class_id(), index_scale(), |
1288 array, index.reg()); | 1315 array, index.reg()); |
1289 } else { | 1316 } else { |
1290 __ LoadElementAddressForIntIndex(address, | 1317 __ LoadElementAddressForIntIndex(address, IsExternal(), class_id(), |
1291 IsExternal(), class_id(), index_scale(), | 1318 index_scale(), array, |
1292 array, | |
1293 Smi::Cast(index.constant()).Value()); | 1319 Smi::Cast(index.constant()).Value()); |
1294 } | 1320 } |
1295 } | 1321 } |
1296 | 1322 |
1297 if ((representation() == kUnboxedDouble) || | 1323 if ((representation() == kUnboxedDouble) || |
1298 (representation() == kUnboxedFloat32x4) || | 1324 (representation() == kUnboxedFloat32x4) || |
1299 (representation() == kUnboxedInt32x4)) { | 1325 (representation() == kUnboxedInt32x4)) { |
1300 DRegister result = locs()->out(0).fpu_reg(); | 1326 DRegister result = locs()->out(0).fpu_reg(); |
1301 switch (class_id()) { | 1327 switch (class_id()) { |
1302 case kTypedDataFloat32ArrayCid: | 1328 case kTypedDataFloat32ArrayCid: |
1303 // Load single precision float. | 1329 // Load single precision float. |
1304 __ lwc1(EvenFRegisterOf(result), element_address); | 1330 __ lwc1(EvenFRegisterOf(result), element_address); |
1305 break; | 1331 break; |
1306 case kTypedDataFloat64ArrayCid: | 1332 case kTypedDataFloat64ArrayCid: |
1307 __ LoadDFromOffset(result, | 1333 __ LoadDFromOffset(result, element_address.base(), |
1308 element_address.base(), element_address.offset()); | 1334 element_address.offset()); |
1309 break; | 1335 break; |
1310 case kTypedDataInt32x4ArrayCid: | 1336 case kTypedDataInt32x4ArrayCid: |
1311 case kTypedDataFloat32x4ArrayCid: | 1337 case kTypedDataFloat32x4ArrayCid: |
1312 UNIMPLEMENTED(); | 1338 UNIMPLEMENTED(); |
1313 break; | 1339 break; |
1314 } | 1340 } |
1315 return; | 1341 return; |
1316 } | 1342 } |
1317 | 1343 |
1318 if ((representation() == kUnboxedUint32) || | 1344 if ((representation() == kUnboxedUint32) || |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1384 __ lw(result, element_address); | 1410 __ lw(result, element_address); |
1385 break; | 1411 break; |
1386 } | 1412 } |
1387 } | 1413 } |
1388 | 1414 |
1389 | 1415 |
1390 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 1416 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |
1391 bool opt) const { | 1417 bool opt) const { |
1392 const intptr_t kNumInputs = 2; | 1418 const intptr_t kNumInputs = 2; |
1393 const intptr_t kNumTemps = 0; | 1419 const intptr_t kNumTemps = 0; |
1394 LocationSummary* summary = new(zone) LocationSummary( | 1420 LocationSummary* summary = new (zone) |
1395 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1421 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1396 summary->set_in(0, Location::RequiresRegister()); | 1422 summary->set_in(0, Location::RequiresRegister()); |
1397 summary->set_in(1, Location::RequiresRegister()); | 1423 summary->set_in(1, Location::RequiresRegister()); |
1398 | 1424 |
1399 // TODO(zerny): Handle mints properly once possible. | 1425 // TODO(zerny): Handle mints properly once possible. |
1400 ASSERT(representation() == kTagged); | 1426 ASSERT(representation() == kTagged); |
1401 summary->set_out(0, Location::RequiresRegister()); | 1427 summary->set_out(0, Location::RequiresRegister()); |
1402 | 1428 |
1403 return summary; | 1429 return summary; |
1404 } | 1430 } |
1405 | 1431 |
1406 | 1432 |
1407 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1433 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1408 // The string register points to the backing store for external strings. | 1434 // The string register points to the backing store for external strings. |
1409 const Register str = locs()->in(0).reg(); | 1435 const Register str = locs()->in(0).reg(); |
1410 const Location index = locs()->in(1); | 1436 const Location index = locs()->in(1); |
1411 | 1437 |
1412 Address element_address = __ ElementAddressForRegIndex( | 1438 Address element_address = __ ElementAddressForRegIndex( |
1413 true, IsExternal(), class_id(), index_scale(), str, index.reg()); | 1439 true, IsExternal(), class_id(), index_scale(), str, index.reg()); |
1414 // Warning: element_address may use register TMP as base. | 1440 // Warning: element_address may use register TMP as base. |
1415 | 1441 |
1416 ASSERT(representation() == kTagged); | 1442 ASSERT(representation() == kTagged); |
1417 Register result = locs()->out(0).reg(); | 1443 Register result = locs()->out(0).reg(); |
1418 switch (class_id()) { | 1444 switch (class_id()) { |
1419 case kOneByteStringCid: | 1445 case kOneByteStringCid: |
1420 case kExternalOneByteStringCid: | 1446 case kExternalOneByteStringCid: |
1421 switch (element_count()) { | 1447 switch (element_count()) { |
1422 case 1: __ lbu(result, element_address); break; | 1448 case 1: |
1423 case 2: __ lhu(result, element_address); break; | 1449 __ lbu(result, element_address); |
| 1450 break; |
| 1451 case 2: |
| 1452 __ lhu(result, element_address); |
| 1453 break; |
1424 case 4: // Loading multiple code units is disabled on MIPS. | 1454 case 4: // Loading multiple code units is disabled on MIPS. |
1425 default: UNREACHABLE(); | 1455 default: |
| 1456 UNREACHABLE(); |
1426 } | 1457 } |
1427 __ SmiTag(result); | 1458 __ SmiTag(result); |
1428 break; | 1459 break; |
1429 case kTwoByteStringCid: | 1460 case kTwoByteStringCid: |
1430 case kExternalTwoByteStringCid: | 1461 case kExternalTwoByteStringCid: |
1431 switch (element_count()) { | 1462 switch (element_count()) { |
1432 case 1: __ lhu(result, element_address); break; | 1463 case 1: |
| 1464 __ lhu(result, element_address); |
| 1465 break; |
1433 case 2: // Loading multiple code units is disabled on MIPS. | 1466 case 2: // Loading multiple code units is disabled on MIPS. |
1434 default: UNREACHABLE(); | 1467 default: |
| 1468 UNREACHABLE(); |
1435 } | 1469 } |
1436 __ SmiTag(result); | 1470 __ SmiTag(result); |
1437 break; | 1471 break; |
1438 default: | 1472 default: |
1439 UNREACHABLE(); | 1473 UNREACHABLE(); |
1440 break; | 1474 break; |
1441 } | 1475 } |
1442 } | 1476 } |
1443 | 1477 |
1444 | 1478 |
1445 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1479 Representation StoreIndexedInstr::RequiredInputRepresentation( |
1446 intptr_t idx) const { | 1480 intptr_t idx) const { |
1447 // Array can be a Dart object or a pointer to external data. | 1481 // Array can be a Dart object or a pointer to external data. |
1448 if (idx == 0) return kNoRepresentation; // Flexible input representation. | 1482 if (idx == 0) return kNoRepresentation; // Flexible input representation. |
1449 if (idx == 1) return kTagged; // Index is a smi. | 1483 if (idx == 1) return kTagged; // Index is a smi. |
1450 ASSERT(idx == 2); | 1484 ASSERT(idx == 2); |
1451 switch (class_id_) { | 1485 switch (class_id_) { |
1452 case kArrayCid: | 1486 case kArrayCid: |
1453 case kOneByteStringCid: | 1487 case kOneByteStringCid: |
1454 case kTypedDataInt8ArrayCid: | 1488 case kTypedDataInt8ArrayCid: |
1455 case kTypedDataUint8ArrayCid: | 1489 case kTypedDataUint8ArrayCid: |
1456 case kExternalTypedDataUint8ArrayCid: | 1490 case kExternalTypedDataUint8ArrayCid: |
1457 case kTypedDataUint8ClampedArrayCid: | 1491 case kTypedDataUint8ClampedArrayCid: |
1458 case kExternalTypedDataUint8ClampedArrayCid: | 1492 case kExternalTypedDataUint8ClampedArrayCid: |
1459 case kTypedDataInt16ArrayCid: | 1493 case kTypedDataInt16ArrayCid: |
(...skipping 14 matching lines...) Expand all Loading... |
1474 UNIMPLEMENTED(); | 1508 UNIMPLEMENTED(); |
1475 return kTagged; | 1509 return kTagged; |
1476 } | 1510 } |
1477 } | 1511 } |
1478 | 1512 |
1479 | 1513 |
1480 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1514 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
1481 bool opt) const { | 1515 bool opt) const { |
1482 const intptr_t kNumInputs = 3; | 1516 const intptr_t kNumInputs = 3; |
1483 const intptr_t kNumTemps = aligned() ? 0 : 2; | 1517 const intptr_t kNumTemps = aligned() ? 0 : 2; |
1484 LocationSummary* locs = new(zone) LocationSummary( | 1518 LocationSummary* locs = new (zone) |
1485 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1519 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1486 locs->set_in(0, Location::RequiresRegister()); | 1520 locs->set_in(0, Location::RequiresRegister()); |
1487 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { | 1521 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { |
1488 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1522 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
1489 } else { | 1523 } else { |
1490 locs->set_in(1, Location::WritableRegister()); | 1524 locs->set_in(1, Location::WritableRegister()); |
1491 } | 1525 } |
1492 switch (class_id()) { | 1526 switch (class_id()) { |
1493 case kArrayCid: | 1527 case kArrayCid: |
1494 locs->set_in(2, ShouldEmitStoreBarrier() | 1528 locs->set_in(2, ShouldEmitStoreBarrier() |
1495 ? Location::WritableRegister() | 1529 ? Location::WritableRegister() |
1496 : Location::RegisterOrConstant(value())); | 1530 : Location::RegisterOrConstant(value())); |
1497 break; | 1531 break; |
1498 case kExternalTypedDataUint8ArrayCid: | 1532 case kExternalTypedDataUint8ArrayCid: |
1499 case kExternalTypedDataUint8ClampedArrayCid: | 1533 case kExternalTypedDataUint8ClampedArrayCid: |
1500 case kTypedDataInt8ArrayCid: | 1534 case kTypedDataInt8ArrayCid: |
1501 case kTypedDataUint8ArrayCid: | 1535 case kTypedDataUint8ArrayCid: |
1502 case kTypedDataUint8ClampedArrayCid: | 1536 case kTypedDataUint8ClampedArrayCid: |
1503 case kOneByteStringCid: | 1537 case kOneByteStringCid: |
1504 case kTypedDataInt16ArrayCid: | 1538 case kTypedDataInt16ArrayCid: |
1505 case kTypedDataUint16ArrayCid: | 1539 case kTypedDataUint16ArrayCid: |
1506 case kTypedDataInt32ArrayCid: | 1540 case kTypedDataInt32ArrayCid: |
(...skipping 21 matching lines...) Expand all Loading... |
1528 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1562 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1529 __ Comment("StoreIndexedInstr"); | 1563 __ Comment("StoreIndexedInstr"); |
1530 // The array register points to the backing store for external arrays. | 1564 // The array register points to the backing store for external arrays. |
1531 const Register array = locs()->in(0).reg(); | 1565 const Register array = locs()->in(0).reg(); |
1532 const Location index = locs()->in(1); | 1566 const Location index = locs()->in(1); |
1533 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); | 1567 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |
1534 const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg(); | 1568 const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg(); |
1535 | 1569 |
1536 Address element_address(kNoRegister); | 1570 Address element_address(kNoRegister); |
1537 if (aligned()) { | 1571 if (aligned()) { |
1538 element_address = index.IsRegister() | 1572 element_address = |
1539 ? __ ElementAddressForRegIndex(false, // Store. | 1573 index.IsRegister() |
1540 IsExternal(), class_id(), index_scale(), | 1574 ? __ ElementAddressForRegIndex(false, // Store. |
1541 array, index.reg()) | 1575 IsExternal(), class_id(), |
1542 : __ ElementAddressForIntIndex( | 1576 index_scale(), array, index.reg()) |
1543 IsExternal(), class_id(), index_scale(), | 1577 : __ ElementAddressForIntIndex(IsExternal(), class_id(), |
1544 array, Smi::Cast(index.constant()).Value()); | 1578 index_scale(), array, |
| 1579 Smi::Cast(index.constant()).Value()); |
1545 ASSERT(element_address.base() != TMP); // Allowed for load only. | 1580 ASSERT(element_address.base() != TMP); // Allowed for load only. |
1546 } else { | 1581 } else { |
1547 if (index.IsRegister()) { | 1582 if (index.IsRegister()) { |
1548 __ LoadElementAddressForRegIndex(address, | 1583 __ LoadElementAddressForRegIndex(address, |
1549 false, // Store. | 1584 false, // Store. |
1550 IsExternal(), class_id(), index_scale(), | 1585 IsExternal(), class_id(), index_scale(), |
1551 array, index.reg()); | 1586 array, index.reg()); |
1552 } else { | 1587 } else { |
1553 __ LoadElementAddressForIntIndex(address, | 1588 __ LoadElementAddressForIntIndex(address, IsExternal(), class_id(), |
1554 IsExternal(), class_id(), index_scale(), | 1589 index_scale(), array, |
1555 array, | |
1556 Smi::Cast(index.constant()).Value()); | 1590 Smi::Cast(index.constant()).Value()); |
1557 } | 1591 } |
1558 } | 1592 } |
1559 | 1593 |
1560 switch (class_id()) { | 1594 switch (class_id()) { |
1561 case kArrayCid: | 1595 case kArrayCid: |
1562 ASSERT(aligned()); | 1596 ASSERT(aligned()); |
1563 if (ShouldEmitStoreBarrier()) { | 1597 if (ShouldEmitStoreBarrier()) { |
1564 Register value = locs()->in(2).reg(); | 1598 Register value = locs()->in(2).reg(); |
1565 __ StoreIntoObject(array, element_address, value); | 1599 __ StoreIntoObject(array, element_address, value); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1635 break; | 1669 break; |
1636 } | 1670 } |
1637 case kTypedDataFloat32ArrayCid: { | 1671 case kTypedDataFloat32ArrayCid: { |
1638 ASSERT(aligned()); | 1672 ASSERT(aligned()); |
1639 FRegister value = EvenFRegisterOf(locs()->in(2).fpu_reg()); | 1673 FRegister value = EvenFRegisterOf(locs()->in(2).fpu_reg()); |
1640 __ swc1(value, element_address); | 1674 __ swc1(value, element_address); |
1641 break; | 1675 break; |
1642 } | 1676 } |
1643 case kTypedDataFloat64ArrayCid: | 1677 case kTypedDataFloat64ArrayCid: |
1644 ASSERT(aligned()); | 1678 ASSERT(aligned()); |
1645 __ StoreDToOffset(locs()->in(2).fpu_reg(), | 1679 __ StoreDToOffset(locs()->in(2).fpu_reg(), element_address.base(), |
1646 element_address.base(), element_address.offset()); | 1680 element_address.offset()); |
1647 break; | 1681 break; |
1648 case kTypedDataInt32x4ArrayCid: | 1682 case kTypedDataInt32x4ArrayCid: |
1649 case kTypedDataFloat32x4ArrayCid: | 1683 case kTypedDataFloat32x4ArrayCid: |
1650 UNIMPLEMENTED(); | 1684 UNIMPLEMENTED(); |
1651 break; | 1685 break; |
1652 default: | 1686 default: |
1653 UNREACHABLE(); | 1687 UNREACHABLE(); |
1654 } | 1688 } |
1655 } | 1689 } |
1656 | 1690 |
1657 | 1691 |
1658 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 1692 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |
1659 bool opt) const { | 1693 bool opt) const { |
1660 const intptr_t kNumInputs = 1; | 1694 const intptr_t kNumInputs = 1; |
1661 | 1695 |
1662 const intptr_t value_cid = value()->Type()->ToCid(); | 1696 const intptr_t value_cid = value()->Type()->ToCid(); |
1663 const intptr_t field_cid = field().guarded_cid(); | 1697 const intptr_t field_cid = field().guarded_cid(); |
1664 | 1698 |
1665 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); | 1699 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); |
1666 const bool needs_value_cid_temp_reg = | 1700 const bool needs_value_cid_temp_reg = |
1667 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); | 1701 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); |
1668 const bool needs_field_temp_reg = emit_full_guard; | 1702 const bool needs_field_temp_reg = emit_full_guard; |
1669 | 1703 |
1670 intptr_t num_temps = 0; | 1704 intptr_t num_temps = 0; |
1671 if (needs_value_cid_temp_reg) { | 1705 if (needs_value_cid_temp_reg) { |
1672 num_temps++; | 1706 num_temps++; |
1673 } | 1707 } |
1674 if (needs_field_temp_reg) { | 1708 if (needs_field_temp_reg) { |
1675 num_temps++; | 1709 num_temps++; |
1676 } | 1710 } |
1677 | 1711 |
1678 LocationSummary* summary = new(zone) LocationSummary( | 1712 LocationSummary* summary = new (zone) |
1679 zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 1713 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
1680 summary->set_in(0, Location::RequiresRegister()); | 1714 summary->set_in(0, Location::RequiresRegister()); |
1681 | 1715 |
1682 for (intptr_t i = 0; i < num_temps; i++) { | 1716 for (intptr_t i = 0; i < num_temps; i++) { |
1683 summary->set_temp(i, Location::RequiresRegister()); | 1717 summary->set_temp(i, Location::RequiresRegister()); |
1684 } | 1718 } |
1685 | 1719 |
1686 return summary; | 1720 return summary; |
1687 } | 1721 } |
1688 | 1722 |
1689 | 1723 |
1690 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1724 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1691 ASSERT(sizeof(classid_t) == kInt16Size); | 1725 ASSERT(sizeof(classid_t) == kInt16Size); |
1692 __ Comment("GuardFieldClassInstr"); | 1726 __ Comment("GuardFieldClassInstr"); |
1693 | 1727 |
1694 const intptr_t value_cid = value()->Type()->ToCid(); | 1728 const intptr_t value_cid = value()->Type()->ToCid(); |
1695 const intptr_t field_cid = field().guarded_cid(); | 1729 const intptr_t field_cid = field().guarded_cid(); |
1696 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1730 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
1697 | 1731 |
1698 if (field_cid == kDynamicCid) { | 1732 if (field_cid == kDynamicCid) { |
1699 if (Compiler::IsBackgroundCompilation()) { | 1733 if (Compiler::IsBackgroundCompilation()) { |
1700 // Field state changed while compiling. | 1734 // Field state changed while compiling. |
1701 Compiler::AbortBackgroundCompilation(deopt_id(), | 1735 Compiler::AbortBackgroundCompilation( |
| 1736 deopt_id(), |
1702 "GuardFieldClassInstr: field state changed while compiling"); | 1737 "GuardFieldClassInstr: field state changed while compiling"); |
1703 } | 1738 } |
1704 ASSERT(!compiler->is_optimizing()); | 1739 ASSERT(!compiler->is_optimizing()); |
1705 return; // Nothing to emit. | 1740 return; // Nothing to emit. |
1706 } | 1741 } |
1707 | 1742 |
1708 const bool emit_full_guard = | 1743 const bool emit_full_guard = |
1709 !compiler->is_optimizing() || (field_cid == kIllegalCid); | 1744 !compiler->is_optimizing() || (field_cid == kIllegalCid); |
1710 | 1745 |
1711 const bool needs_value_cid_temp_reg = | 1746 const bool needs_value_cid_temp_reg = |
1712 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); | 1747 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); |
1713 | 1748 |
1714 const bool needs_field_temp_reg = emit_full_guard; | 1749 const bool needs_field_temp_reg = emit_full_guard; |
1715 | 1750 |
1716 const Register value_reg = locs()->in(0).reg(); | 1751 const Register value_reg = locs()->in(0).reg(); |
1717 | 1752 |
1718 const Register value_cid_reg = needs_value_cid_temp_reg ? | 1753 const Register value_cid_reg = |
1719 locs()->temp(0).reg() : kNoRegister; | 1754 needs_value_cid_temp_reg ? locs()->temp(0).reg() : kNoRegister; |
1720 | 1755 |
1721 const Register field_reg = needs_field_temp_reg ? | 1756 const Register field_reg = needs_field_temp_reg |
1722 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; | 1757 ? locs()->temp(locs()->temp_count() - 1).reg() |
| 1758 : kNoRegister; |
1723 | 1759 |
1724 Label ok, fail_label; | 1760 Label ok, fail_label; |
1725 | 1761 |
1726 Label* deopt = compiler->is_optimizing() ? | 1762 Label* deopt = |
1727 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1763 compiler->is_optimizing() |
| 1764 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1765 : NULL; |
1728 | 1766 |
1729 Label* fail = (deopt != NULL) ? deopt : &fail_label; | 1767 Label* fail = (deopt != NULL) ? deopt : &fail_label; |
1730 | 1768 |
1731 if (emit_full_guard) { | 1769 if (emit_full_guard) { |
1732 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1770 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
1733 | 1771 |
1734 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); | 1772 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); |
1735 FieldAddress field_nullability_operand( | 1773 FieldAddress field_nullability_operand(field_reg, |
1736 field_reg, Field::is_nullable_offset()); | 1774 Field::is_nullable_offset()); |
1737 | 1775 |
1738 if (value_cid == kDynamicCid) { | 1776 if (value_cid == kDynamicCid) { |
1739 LoadValueCid(compiler, value_cid_reg, value_reg); | 1777 LoadValueCid(compiler, value_cid_reg, value_reg); |
1740 | 1778 |
1741 __ lhu(CMPRES1, field_cid_operand); | 1779 __ lhu(CMPRES1, field_cid_operand); |
1742 __ beq(value_cid_reg, CMPRES1, &ok); | 1780 __ beq(value_cid_reg, CMPRES1, &ok); |
1743 __ lhu(TMP, field_nullability_operand); | 1781 __ lhu(TMP, field_nullability_operand); |
1744 __ subu(CMPRES1, value_cid_reg, TMP); | 1782 __ subu(CMPRES1, value_cid_reg, TMP); |
1745 } else if (value_cid == kNullCid) { | 1783 } else if (value_cid == kNullCid) { |
1746 __ lhu(TMP, field_nullability_operand); | 1784 __ lhu(TMP, field_nullability_operand); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1830 __ Bind(&ok); | 1868 __ Bind(&ok); |
1831 } | 1869 } |
1832 | 1870 |
1833 | 1871 |
1834 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 1872 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |
1835 bool opt) const { | 1873 bool opt) const { |
1836 const intptr_t kNumInputs = 1; | 1874 const intptr_t kNumInputs = 1; |
1837 | 1875 |
1838 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1876 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
1839 const intptr_t kNumTemps = 1; | 1877 const intptr_t kNumTemps = 1; |
1840 LocationSummary* summary = new(zone) LocationSummary( | 1878 LocationSummary* summary = new (zone) |
1841 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1879 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1842 summary->set_in(0, Location::RequiresRegister()); | 1880 summary->set_in(0, Location::RequiresRegister()); |
1843 // We need temporaries for field object. | 1881 // We need temporaries for field object. |
1844 summary->set_temp(0, Location::RequiresRegister()); | 1882 summary->set_temp(0, Location::RequiresRegister()); |
1845 return summary; | 1883 return summary; |
1846 } | 1884 } |
1847 LocationSummary* summary = new(zone) LocationSummary( | 1885 LocationSummary* summary = |
1848 zone, kNumInputs, 0, LocationSummary::kNoCall); | 1886 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
1849 summary->set_in(0, Location::RequiresRegister()); | 1887 summary->set_in(0, Location::RequiresRegister()); |
1850 return summary; | 1888 return summary; |
1851 } | 1889 } |
1852 | 1890 |
1853 | 1891 |
1854 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1892 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1855 if (field().guarded_list_length() == Field::kNoFixedLength) { | 1893 if (field().guarded_list_length() == Field::kNoFixedLength) { |
1856 if (Compiler::IsBackgroundCompilation()) { | 1894 if (Compiler::IsBackgroundCompilation()) { |
1857 // Field state changed while compiling. | 1895 // Field state changed while compiling. |
1858 Compiler::AbortBackgroundCompilation(deopt_id(), | 1896 Compiler::AbortBackgroundCompilation( |
| 1897 deopt_id(), |
1859 "GuardFieldLengthInstr: field state changed while compiling"); | 1898 "GuardFieldLengthInstr: field state changed while compiling"); |
1860 } | 1899 } |
1861 ASSERT(!compiler->is_optimizing()); | 1900 ASSERT(!compiler->is_optimizing()); |
1862 return; // Nothing to emit. | 1901 return; // Nothing to emit. |
1863 } | 1902 } |
1864 | 1903 |
1865 Label* deopt = compiler->is_optimizing() ? | 1904 Label* deopt = |
1866 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1905 compiler->is_optimizing() |
| 1906 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1907 : NULL; |
1867 | 1908 |
1868 const Register value_reg = locs()->in(0).reg(); | 1909 const Register value_reg = locs()->in(0).reg(); |
1869 | 1910 |
1870 if (!compiler->is_optimizing() || | 1911 if (!compiler->is_optimizing() || |
1871 (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1912 (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
1872 const Register field_reg = locs()->temp(0).reg(); | 1913 const Register field_reg = locs()->temp(0).reg(); |
1873 | 1914 |
1874 Label ok; | 1915 Label ok; |
1875 | 1916 |
1876 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1917 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
1877 | 1918 |
1878 __ lb(CMPRES1, FieldAddress(field_reg, | 1919 __ lb(CMPRES1, |
1879 Field::guarded_list_length_in_object_offset_offset())); | 1920 FieldAddress(field_reg, |
| 1921 Field::guarded_list_length_in_object_offset_offset())); |
1880 __ blez(CMPRES1, &ok); | 1922 __ blez(CMPRES1, &ok); |
1881 | 1923 |
1882 __ lw(CMPRES2, FieldAddress(field_reg, | 1924 __ lw(CMPRES2, |
1883 Field::guarded_list_length_offset())); | 1925 FieldAddress(field_reg, Field::guarded_list_length_offset())); |
1884 | 1926 |
1885 // Load the length from the value. GuardFieldClass already verified that | 1927 // Load the length from the value. GuardFieldClass already verified that |
1886 // value's class matches guarded class id of the field. | 1928 // value's class matches guarded class id of the field. |
1887 // CMPRES1 contains offset already corrected by -kHeapObjectTag that is | 1929 // CMPRES1 contains offset already corrected by -kHeapObjectTag that is |
1888 // why we can use Address instead of FieldAddress. | 1930 // why we can use Address instead of FieldAddress. |
1889 __ addu(TMP, value_reg, CMPRES1); | 1931 __ addu(TMP, value_reg, CMPRES1); |
1890 __ lw(TMP, Address(TMP)); | 1932 __ lw(TMP, Address(TMP)); |
1891 | 1933 |
1892 if (deopt == NULL) { | 1934 if (deopt == NULL) { |
1893 __ beq(CMPRES2, TMP, &ok); | 1935 __ beq(CMPRES2, TMP, &ok); |
1894 | 1936 |
1895 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1937 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
1896 __ sw(field_reg, Address(SP, 1 * kWordSize)); | 1938 __ sw(field_reg, Address(SP, 1 * kWordSize)); |
1897 __ sw(value_reg, Address(SP, 0 * kWordSize)); | 1939 __ sw(value_reg, Address(SP, 0 * kWordSize)); |
1898 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); | 1940 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); |
1899 __ Drop(2); // Drop the field and the value. | 1941 __ Drop(2); // Drop the field and the value. |
1900 } else { | 1942 } else { |
1901 __ bne(CMPRES2, TMP, deopt); | 1943 __ bne(CMPRES2, TMP, deopt); |
1902 } | 1944 } |
1903 | 1945 |
1904 __ Bind(&ok); | 1946 __ Bind(&ok); |
1905 } else { | 1947 } else { |
1906 ASSERT(compiler->is_optimizing()); | 1948 ASSERT(compiler->is_optimizing()); |
1907 ASSERT(field().guarded_list_length() >= 0); | 1949 ASSERT(field().guarded_list_length() >= 0); |
1908 ASSERT(field().guarded_list_length_in_object_offset() != | 1950 ASSERT(field().guarded_list_length_in_object_offset() != |
1909 Field::kUnknownLengthOffset); | 1951 Field::kUnknownLengthOffset); |
1910 | 1952 |
1911 __ lw(CMPRES1, | 1953 __ lw(CMPRES1, |
1912 FieldAddress(value_reg, | 1954 FieldAddress(value_reg, |
1913 field().guarded_list_length_in_object_offset())); | 1955 field().guarded_list_length_in_object_offset())); |
1914 __ LoadImmediate(TMP, Smi::RawValue(field().guarded_list_length())); | 1956 __ LoadImmediate(TMP, Smi::RawValue(field().guarded_list_length())); |
1915 __ bne(CMPRES1, TMP, deopt); | 1957 __ bne(CMPRES1, TMP, deopt); |
1916 } | 1958 } |
1917 } | 1959 } |
1918 | 1960 |
1919 | 1961 |
1920 class BoxAllocationSlowPath : public SlowPathCode { | 1962 class BoxAllocationSlowPath : public SlowPathCode { |
1921 public: | 1963 public: |
1922 BoxAllocationSlowPath(Instruction* instruction, | 1964 BoxAllocationSlowPath(Instruction* instruction, |
1923 const Class& cls, | 1965 const Class& cls, |
1924 Register result) | 1966 Register result) |
1925 : instruction_(instruction), | 1967 : instruction_(instruction), cls_(cls), result_(result) {} |
1926 cls_(cls), | |
1927 result_(result) { } | |
1928 | 1968 |
1929 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1969 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
1930 if (Assembler::EmittingComments()) { | 1970 if (Assembler::EmittingComments()) { |
1931 __ Comment("%s slow path allocation of %s", | 1971 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), |
1932 instruction_->DebugName(), | |
1933 String::Handle(cls_.ScrubbedName()).ToCString()); | 1972 String::Handle(cls_.ScrubbedName()).ToCString()); |
1934 } | 1973 } |
1935 __ Bind(entry_label()); | 1974 __ Bind(entry_label()); |
1936 const Code& stub = Code::ZoneHandle( | 1975 const Code& stub = Code::ZoneHandle( |
1937 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); | 1976 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); |
1938 const StubEntry stub_entry(stub); | 1977 const StubEntry stub_entry(stub); |
1939 | 1978 |
1940 LocationSummary* locs = instruction_->locs(); | 1979 LocationSummary* locs = instruction_->locs(); |
1941 locs->live_registers()->Remove(Location::RegisterLocation(result_)); | 1980 locs->live_registers()->Remove(Location::RegisterLocation(result_)); |
1942 | 1981 |
1943 compiler->SaveLiveRegisters(locs); | 1982 compiler->SaveLiveRegisters(locs); |
1944 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. | 1983 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. |
1945 stub_entry, | 1984 stub_entry, RawPcDescriptors::kOther, locs); |
1946 RawPcDescriptors::kOther, | |
1947 locs); | |
1948 compiler->AddStubCallTarget(stub); | 1985 compiler->AddStubCallTarget(stub); |
1949 if (result_ != V0) { | 1986 if (result_ != V0) { |
1950 __ mov(result_, V0); | 1987 __ mov(result_, V0); |
1951 } | 1988 } |
1952 compiler->RestoreLiveRegisters(locs); | 1989 compiler->RestoreLiveRegisters(locs); |
1953 __ b(exit_label()); | 1990 __ b(exit_label()); |
1954 } | 1991 } |
1955 | 1992 |
1956 static void Allocate(FlowGraphCompiler* compiler, | 1993 static void Allocate(FlowGraphCompiler* compiler, |
1957 Instruction* instruction, | 1994 Instruction* instruction, |
1958 const Class& cls, | 1995 const Class& cls, |
1959 Register result, | 1996 Register result, |
1960 Register temp) { | 1997 Register temp) { |
1961 if (compiler->intrinsic_mode()) { | 1998 if (compiler->intrinsic_mode()) { |
1962 __ TryAllocate(cls, | 1999 __ TryAllocate(cls, compiler->intrinsic_slow_path_label(), result, temp); |
1963 compiler->intrinsic_slow_path_label(), | |
1964 result, | |
1965 temp); | |
1966 } else { | 2000 } else { |
1967 BoxAllocationSlowPath* slow_path = | 2001 BoxAllocationSlowPath* slow_path = |
1968 new BoxAllocationSlowPath(instruction, cls, result); | 2002 new BoxAllocationSlowPath(instruction, cls, result); |
1969 compiler->AddSlowPathCode(slow_path); | 2003 compiler->AddSlowPathCode(slow_path); |
1970 | 2004 |
1971 __ TryAllocate(cls, | 2005 __ TryAllocate(cls, slow_path->entry_label(), result, temp); |
1972 slow_path->entry_label(), | |
1973 result, | |
1974 temp); | |
1975 __ Bind(slow_path->exit_label()); | 2006 __ Bind(slow_path->exit_label()); |
1976 } | 2007 } |
1977 } | 2008 } |
1978 | 2009 |
1979 private: | 2010 private: |
1980 Instruction* instruction_; | 2011 Instruction* instruction_; |
1981 const Class& cls_; | 2012 const Class& cls_; |
1982 const Register result_; | 2013 const Register result_; |
1983 }; | 2014 }; |
1984 | 2015 |
1985 | 2016 |
1986 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 2017 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |
1987 bool opt) const { | 2018 bool opt) const { |
1988 const intptr_t kNumInputs = 2; | 2019 const intptr_t kNumInputs = 2; |
1989 const intptr_t kNumTemps = | 2020 const intptr_t kNumTemps = |
1990 (IsUnboxedStore() && opt) ? 2 : | 2021 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); |
1991 ((IsPotentialUnboxedStore()) ? 3 : 0); | 2022 LocationSummary* summary = new (zone) |
1992 LocationSummary* summary = new(zone) LocationSummary( | 2023 LocationSummary(zone, kNumInputs, kNumTemps, |
1993 zone, kNumInputs, kNumTemps, | 2024 ((IsUnboxedStore() && opt && is_initialization()) || |
1994 ((IsUnboxedStore() && opt && is_initialization()) || | 2025 IsPotentialUnboxedStore()) |
1995 IsPotentialUnboxedStore()) | 2026 ? LocationSummary::kCallOnSlowPath |
1996 ? LocationSummary::kCallOnSlowPath | 2027 : LocationSummary::kNoCall); |
1997 : LocationSummary::kNoCall); | |
1998 | 2028 |
1999 summary->set_in(0, Location::RequiresRegister()); | 2029 summary->set_in(0, Location::RequiresRegister()); |
2000 if (IsUnboxedStore() && opt) { | 2030 if (IsUnboxedStore() && opt) { |
2001 summary->set_in(1, Location::RequiresFpuRegister()); | 2031 summary->set_in(1, Location::RequiresFpuRegister()); |
2002 summary->set_temp(0, Location::RequiresRegister()); | 2032 summary->set_temp(0, Location::RequiresRegister()); |
2003 summary->set_temp(1, Location::RequiresRegister()); | 2033 summary->set_temp(1, Location::RequiresRegister()); |
2004 } else if (IsPotentialUnboxedStore()) { | 2034 } else if (IsPotentialUnboxedStore()) { |
2005 summary->set_in(1, ShouldEmitStoreBarrier() | 2035 summary->set_in(1, ShouldEmitStoreBarrier() ? Location::WritableRegister() |
2006 ? Location::WritableRegister() | 2036 : Location::RequiresRegister()); |
2007 : Location::RequiresRegister()); | |
2008 summary->set_temp(0, Location::RequiresRegister()); | 2037 summary->set_temp(0, Location::RequiresRegister()); |
2009 summary->set_temp(1, Location::RequiresRegister()); | 2038 summary->set_temp(1, Location::RequiresRegister()); |
2010 summary->set_temp(2, opt ? Location::RequiresFpuRegister() | 2039 summary->set_temp(2, opt ? Location::RequiresFpuRegister() |
2011 : Location::FpuRegisterLocation(D1)); | 2040 : Location::FpuRegisterLocation(D1)); |
2012 } else { | 2041 } else { |
2013 summary->set_in(1, ShouldEmitStoreBarrier() | 2042 summary->set_in(1, ShouldEmitStoreBarrier() |
2014 ? Location::WritableRegister() | 2043 ? Location::WritableRegister() |
2015 : Location::RegisterOrConstant(value())); | 2044 : Location::RegisterOrConstant(value())); |
2016 } | 2045 } |
2017 return summary; | 2046 return summary; |
2018 } | 2047 } |
2019 | 2048 |
2020 | 2049 |
2021 static void EnsureMutableBox(FlowGraphCompiler* compiler, | 2050 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
2022 StoreInstanceFieldInstr* instruction, | 2051 StoreInstanceFieldInstr* instruction, |
2023 Register box_reg, | 2052 Register box_reg, |
2024 const Class& cls, | 2053 const Class& cls, |
2025 Register instance_reg, | 2054 Register instance_reg, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2059 | 2088 |
2060 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2); | 2089 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2); |
2061 __ mov(temp2, temp); | 2090 __ mov(temp2, temp); |
2062 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2); | 2091 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2); |
2063 } else { | 2092 } else { |
2064 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes_)); | 2093 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes_)); |
2065 } | 2094 } |
2066 switch (cid) { | 2095 switch (cid) { |
2067 case kDoubleCid: | 2096 case kDoubleCid: |
2068 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); | 2097 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
2069 break; | 2098 break; |
2070 default: | 2099 default: |
2071 UNREACHABLE(); | 2100 UNREACHABLE(); |
2072 } | 2101 } |
2073 return; | 2102 return; |
2074 } | 2103 } |
2075 | 2104 |
2076 if (IsPotentialUnboxedStore()) { | 2105 if (IsPotentialUnboxedStore()) { |
2077 Register value_reg = locs()->in(1).reg(); | 2106 Register value_reg = locs()->in(1).reg(); |
2078 Register temp = locs()->temp(0).reg(); | 2107 Register temp = locs()->temp(0).reg(); |
2079 Register temp2 = locs()->temp(1).reg(); | 2108 Register temp2 = locs()->temp(1).reg(); |
(...skipping 23 matching lines...) Expand all Loading... |
2103 // Fall through. | 2132 // Fall through. |
2104 __ b(&store_pointer); | 2133 __ b(&store_pointer); |
2105 | 2134 |
2106 if (!compiler->is_optimizing()) { | 2135 if (!compiler->is_optimizing()) { |
2107 locs()->live_registers()->Add(locs()->in(0)); | 2136 locs()->live_registers()->Add(locs()->in(0)); |
2108 locs()->live_registers()->Add(locs()->in(1)); | 2137 locs()->live_registers()->Add(locs()->in(1)); |
2109 } | 2138 } |
2110 | 2139 |
2111 { | 2140 { |
2112 __ Bind(&store_double); | 2141 __ Bind(&store_double); |
2113 EnsureMutableBox(compiler, | 2142 EnsureMutableBox(compiler, this, temp, compiler->double_class(), |
2114 this, | 2143 instance_reg, offset_in_bytes_, temp2); |
2115 temp, | 2144 __ LoadDFromOffset(fpu_temp, value_reg, |
2116 compiler->double_class(), | |
2117 instance_reg, | |
2118 offset_in_bytes_, | |
2119 temp2); | |
2120 __ LoadDFromOffset(fpu_temp, | |
2121 value_reg, | |
2122 Double::value_offset() - kHeapObjectTag); | 2145 Double::value_offset() - kHeapObjectTag); |
2123 __ StoreDToOffset(fpu_temp, temp, | 2146 __ StoreDToOffset(fpu_temp, temp, |
2124 Double::value_offset() - kHeapObjectTag); | 2147 Double::value_offset() - kHeapObjectTag); |
2125 __ b(&skip_store); | 2148 __ b(&skip_store); |
2126 } | 2149 } |
2127 | 2150 |
2128 __ Bind(&store_pointer); | 2151 __ Bind(&store_pointer); |
2129 } | 2152 } |
2130 | 2153 |
2131 if (ShouldEmitStoreBarrier()) { | 2154 if (ShouldEmitStoreBarrier()) { |
2132 Register value_reg = locs()->in(1).reg(); | 2155 Register value_reg = locs()->in(1).reg(); |
2133 __ StoreIntoObjectOffset(instance_reg, | 2156 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, value_reg, |
2134 offset_in_bytes_, | |
2135 value_reg, | |
2136 CanValueBeSmi()); | 2157 CanValueBeSmi()); |
2137 } else { | 2158 } else { |
2138 if (locs()->in(1).IsConstant()) { | 2159 if (locs()->in(1).IsConstant()) { |
2139 __ StoreIntoObjectNoBarrierOffset( | 2160 __ StoreIntoObjectNoBarrierOffset(instance_reg, offset_in_bytes_, |
2140 instance_reg, | 2161 locs()->in(1).constant()); |
2141 offset_in_bytes_, | |
2142 locs()->in(1).constant()); | |
2143 } else { | 2162 } else { |
2144 Register value_reg = locs()->in(1).reg(); | 2163 Register value_reg = locs()->in(1).reg(); |
2145 __ StoreIntoObjectNoBarrierOffset(instance_reg, | 2164 __ StoreIntoObjectNoBarrierOffset(instance_reg, offset_in_bytes_, |
2146 offset_in_bytes_, | |
2147 value_reg); | 2165 value_reg); |
2148 } | 2166 } |
2149 } | 2167 } |
2150 __ Bind(&skip_store); | 2168 __ Bind(&skip_store); |
2151 } | 2169 } |
2152 | 2170 |
2153 | 2171 |
2154 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2172 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |
2155 bool opt) const { | 2173 bool opt) const { |
2156 const intptr_t kNumInputs = 1; | 2174 const intptr_t kNumInputs = 1; |
2157 const intptr_t kNumTemps = 0; | 2175 const intptr_t kNumTemps = 0; |
2158 LocationSummary* summary = new(zone) LocationSummary( | 2176 LocationSummary* summary = new (zone) |
2159 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2177 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2160 summary->set_in(0, Location::RequiresRegister()); | 2178 summary->set_in(0, Location::RequiresRegister()); |
2161 summary->set_out(0, Location::RequiresRegister()); | 2179 summary->set_out(0, Location::RequiresRegister()); |
2162 return summary; | 2180 return summary; |
2163 } | 2181 } |
2164 | 2182 |
2165 | 2183 |
2166 // When the parser is building an implicit static getter for optimization, | 2184 // When the parser is building an implicit static getter for optimization, |
2167 // it can generate a function body where deoptimization ids do not line up | 2185 // it can generate a function body where deoptimization ids do not line up |
2168 // with the unoptimized code. | 2186 // with the unoptimized code. |
2169 // | 2187 // |
2170 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 2188 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
2171 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2189 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2172 __ Comment("LoadStaticFieldInstr"); | 2190 __ Comment("LoadStaticFieldInstr"); |
2173 Register field = locs()->in(0).reg(); | 2191 Register field = locs()->in(0).reg(); |
2174 Register result = locs()->out(0).reg(); | 2192 Register result = locs()->out(0).reg(); |
2175 __ LoadFromOffset(result, | 2193 __ LoadFromOffset(result, field, |
2176 field, | |
2177 Field::static_value_offset() - kHeapObjectTag); | 2194 Field::static_value_offset() - kHeapObjectTag); |
2178 } | 2195 } |
2179 | 2196 |
2180 | 2197 |
2181 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2198 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |
2182 bool opt) const { | 2199 bool opt) const { |
2183 LocationSummary* locs = new(zone) LocationSummary( | 2200 LocationSummary* locs = |
2184 zone, 1, 1, LocationSummary::kNoCall); | 2201 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); |
2185 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 2202 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
2186 : Location::RequiresRegister()); | 2203 : Location::RequiresRegister()); |
2187 locs->set_temp(0, Location::RequiresRegister()); | 2204 locs->set_temp(0, Location::RequiresRegister()); |
2188 return locs; | 2205 return locs; |
2189 } | 2206 } |
2190 | 2207 |
2191 | 2208 |
2192 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2209 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2193 __ Comment("StoreStaticFieldInstr"); | 2210 __ Comment("StoreStaticFieldInstr"); |
2194 Register value = locs()->in(0).reg(); | 2211 Register value = locs()->in(0).reg(); |
2195 Register temp = locs()->temp(0).reg(); | 2212 Register temp = locs()->temp(0).reg(); |
2196 | 2213 |
2197 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 2214 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
2198 if (this->value()->NeedsStoreBuffer()) { | 2215 if (this->value()->NeedsStoreBuffer()) { |
2199 __ StoreIntoObject(temp, | 2216 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), |
2200 FieldAddress(temp, Field::static_value_offset()), | 2217 value, CanValueBeSmi()); |
2201 value, | |
2202 CanValueBeSmi()); | |
2203 } else { | 2218 } else { |
2204 __ StoreIntoObjectNoBarrier( | 2219 __ StoreIntoObjectNoBarrier( |
2205 temp, FieldAddress(temp, Field::static_value_offset()), value); | 2220 temp, FieldAddress(temp, Field::static_value_offset()), value); |
2206 } | 2221 } |
2207 } | 2222 } |
2208 | 2223 |
2209 | 2224 |
2210 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 2225 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
2211 bool opt) const { | 2226 bool opt) const { |
2212 const intptr_t kNumInputs = 2; | 2227 const intptr_t kNumInputs = 2; |
2213 const intptr_t kNumTemps = 0; | 2228 const intptr_t kNumTemps = 0; |
2214 LocationSummary* summary = new(zone) LocationSummary( | 2229 LocationSummary* summary = new (zone) |
2215 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2230 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2216 summary->set_in(0, Location::RegisterLocation(A0)); | 2231 summary->set_in(0, Location::RegisterLocation(A0)); |
2217 summary->set_in(1, Location::RegisterLocation(A1)); | 2232 summary->set_in(1, Location::RegisterLocation(A1)); |
2218 summary->set_out(0, Location::RegisterLocation(V0)); | 2233 summary->set_out(0, Location::RegisterLocation(V0)); |
2219 return summary; | 2234 return summary; |
2220 } | 2235 } |
2221 | 2236 |
2222 | 2237 |
2223 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2238 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2224 ASSERT(locs()->in(0).reg() == A0); // Value. | 2239 ASSERT(locs()->in(0).reg() == A0); // Value. |
2225 ASSERT(locs()->in(1).reg() == A1); // Instantiator type arguments. | 2240 ASSERT(locs()->in(1).reg() == A1); // Instantiator type arguments. |
2226 | 2241 |
2227 __ Comment("InstanceOfInstr"); | 2242 __ Comment("InstanceOfInstr"); |
2228 compiler->GenerateInstanceOf(token_pos(), | 2243 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), negate_result(), |
2229 deopt_id(), | |
2230 type(), | |
2231 negate_result(), | |
2232 locs()); | 2244 locs()); |
2233 ASSERT(locs()->out(0).reg() == V0); | 2245 ASSERT(locs()->out(0).reg() == V0); |
2234 } | 2246 } |
2235 | 2247 |
2236 | 2248 |
2237 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 2249 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
2238 bool opt) const { | 2250 bool opt) const { |
2239 const intptr_t kNumInputs = 2; | 2251 const intptr_t kNumInputs = 2; |
2240 const intptr_t kNumTemps = 0; | 2252 const intptr_t kNumTemps = 0; |
2241 LocationSummary* locs = new(zone) LocationSummary( | 2253 LocationSummary* locs = new (zone) |
2242 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2254 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2243 locs->set_in(0, Location::RegisterLocation(A0)); | 2255 locs->set_in(0, Location::RegisterLocation(A0)); |
2244 locs->set_in(1, Location::RegisterLocation(A1)); | 2256 locs->set_in(1, Location::RegisterLocation(A1)); |
2245 locs->set_out(0, Location::RegisterLocation(V0)); | 2257 locs->set_out(0, Location::RegisterLocation(V0)); |
2246 return locs; | 2258 return locs; |
2247 } | 2259 } |
2248 | 2260 |
2249 | 2261 |
2250 // Inlines array allocation for known constant values. | 2262 // Inlines array allocation for known constant values. |
2251 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 2263 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
2252 intptr_t num_elements, | 2264 intptr_t num_elements, |
2253 Label* slow_path, | 2265 Label* slow_path, |
2254 Label* done) { | 2266 Label* done) { |
2255 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. | 2267 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. |
2256 const Register kLengthReg = A1; | 2268 const Register kLengthReg = A1; |
2257 const Register kElemTypeReg = A0; | 2269 const Register kElemTypeReg = A0; |
2258 const intptr_t instance_size = Array::InstanceSize(num_elements); | 2270 const intptr_t instance_size = Array::InstanceSize(num_elements); |
2259 | 2271 |
2260 __ TryAllocateArray(kArrayCid, instance_size, slow_path, | 2272 __ TryAllocateArray(kArrayCid, instance_size, slow_path, |
2261 V0, // instance | 2273 V0, // instance |
2262 T1, // end address | 2274 T1, // end address |
2263 T2, | 2275 T2, T3); |
2264 T3); | |
2265 // V0: new object start as a tagged pointer. | 2276 // V0: new object start as a tagged pointer. |
2266 // T1: new object end address. | 2277 // T1: new object end address. |
2267 | 2278 |
2268 // Store the type argument field. | 2279 // Store the type argument field. |
2269 __ StoreIntoObjectNoBarrier(V0, | 2280 __ StoreIntoObjectNoBarrier( |
2270 FieldAddress(V0, Array::type_arguments_offset()), | 2281 V0, FieldAddress(V0, Array::type_arguments_offset()), kElemTypeReg); |
2271 kElemTypeReg); | |
2272 | 2282 |
2273 // Set the length field. | 2283 // Set the length field. |
2274 __ StoreIntoObjectNoBarrier(V0, | 2284 __ StoreIntoObjectNoBarrier(V0, FieldAddress(V0, Array::length_offset()), |
2275 FieldAddress(V0, Array::length_offset()), | |
2276 kLengthReg); | 2285 kLengthReg); |
2277 | 2286 |
2278 // Initialize all array elements to raw_null. | 2287 // Initialize all array elements to raw_null. |
2279 // V0: new object start as a tagged pointer. | 2288 // V0: new object start as a tagged pointer. |
2280 // T1: new object end address. | 2289 // T1: new object end address. |
2281 // T2: iterator which initially points to the start of the variable | 2290 // T2: iterator which initially points to the start of the variable |
2282 // data area to be initialized. | 2291 // data area to be initialized. |
2283 // T7: null. | 2292 // T7: null. |
2284 if (num_elements > 0) { | 2293 if (num_elements > 0) { |
2285 const intptr_t array_size = instance_size - sizeof(RawArray); | 2294 const intptr_t array_size = instance_size - sizeof(RawArray); |
(...skipping 19 matching lines...) Expand all Loading... |
2305 | 2314 |
2306 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2315 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2307 __ Comment("CreateArrayInstr"); | 2316 __ Comment("CreateArrayInstr"); |
2308 const Register kLengthReg = A1; | 2317 const Register kLengthReg = A1; |
2309 const Register kElemTypeReg = A0; | 2318 const Register kElemTypeReg = A0; |
2310 const Register kResultReg = V0; | 2319 const Register kResultReg = V0; |
2311 ASSERT(locs()->in(0).reg() == kElemTypeReg); | 2320 ASSERT(locs()->in(0).reg() == kElemTypeReg); |
2312 ASSERT(locs()->in(1).reg() == kLengthReg); | 2321 ASSERT(locs()->in(1).reg() == kLengthReg); |
2313 | 2322 |
2314 Label slow_path, done; | 2323 Label slow_path, done; |
2315 if (compiler->is_optimizing() && | 2324 if (compiler->is_optimizing() && !FLAG_precompiled_mode && |
2316 !FLAG_precompiled_mode && | |
2317 num_elements()->BindsToConstant() && | 2325 num_elements()->BindsToConstant() && |
2318 num_elements()->BoundConstant().IsSmi()) { | 2326 num_elements()->BoundConstant().IsSmi()) { |
2319 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); | 2327 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); |
2320 if ((length >= 0) && (length <= Array::kMaxElements)) { | 2328 if ((length >= 0) && (length <= Array::kMaxElements)) { |
2321 Label slow_path, done; | 2329 Label slow_path, done; |
2322 InlineArrayAllocation(compiler, length, &slow_path, &done); | 2330 InlineArrayAllocation(compiler, length, &slow_path, &done); |
2323 __ Bind(&slow_path); | 2331 __ Bind(&slow_path); |
2324 __ PushObject(Object::null_object()); // Make room for the result. | 2332 __ PushObject(Object::null_object()); // Make room for the result. |
2325 __ Push(kLengthReg); // length. | 2333 __ Push(kLengthReg); // length. |
2326 __ Push(kElemTypeReg); | 2334 __ Push(kElemTypeReg); |
2327 compiler->GenerateRuntimeCall(token_pos(), | 2335 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2328 deopt_id(), | 2336 kAllocateArrayRuntimeEntry, 2, locs()); |
2329 kAllocateArrayRuntimeEntry, | |
2330 2, | |
2331 locs()); | |
2332 __ Drop(2); | 2337 __ Drop(2); |
2333 __ Pop(kResultReg); | 2338 __ Pop(kResultReg); |
2334 __ Bind(&done); | 2339 __ Bind(&done); |
2335 return; | 2340 return; |
2336 } | 2341 } |
2337 } | 2342 } |
2338 | 2343 |
2339 __ Bind(&slow_path); | 2344 __ Bind(&slow_path); |
2340 const Code& stub = Code::ZoneHandle(compiler->zone(), | 2345 const Code& stub = Code::ZoneHandle(compiler->zone(), |
2341 StubCode::AllocateArray_entry()->code()); | 2346 StubCode::AllocateArray_entry()->code()); |
2342 compiler->AddStubCallTarget(stub); | 2347 compiler->AddStubCallTarget(stub); |
2343 compiler->GenerateCall(token_pos(), | 2348 compiler->GenerateCall(token_pos(), *StubCode::AllocateArray_entry(), |
2344 *StubCode::AllocateArray_entry(), | 2349 RawPcDescriptors::kOther, locs()); |
2345 RawPcDescriptors::kOther, | |
2346 locs()); | |
2347 __ Bind(&done); | 2350 __ Bind(&done); |
2348 ASSERT(locs()->out(0).reg() == kResultReg); | 2351 ASSERT(locs()->out(0).reg() == kResultReg); |
2349 } | 2352 } |
2350 | 2353 |
2351 | 2354 |
2352 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 2355 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |
2353 bool opt) const { | 2356 bool opt) const { |
2354 const intptr_t kNumInputs = 1; | 2357 const intptr_t kNumInputs = 1; |
2355 const intptr_t kNumTemps = | 2358 const intptr_t kNumTemps = |
2356 (IsUnboxedLoad() && opt) ? 1 : | 2359 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0); |
2357 ((IsPotentialUnboxedLoad()) ? 2 : 0); | 2360 LocationSummary* locs = new (zone) LocationSummary( |
2358 LocationSummary* locs = new(zone) LocationSummary( | 2361 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) |
2359 zone, kNumInputs, kNumTemps, | 2362 ? LocationSummary::kNoCall |
2360 (opt && !IsPotentialUnboxedLoad()) | 2363 : LocationSummary::kCallOnSlowPath); |
2361 ? LocationSummary::kNoCall | |
2362 : LocationSummary::kCallOnSlowPath); | |
2363 | 2364 |
2364 locs->set_in(0, Location::RequiresRegister()); | 2365 locs->set_in(0, Location::RequiresRegister()); |
2365 | 2366 |
2366 if (IsUnboxedLoad() && opt) { | 2367 if (IsUnboxedLoad() && opt) { |
2367 locs->set_temp(0, Location::RequiresRegister()); | 2368 locs->set_temp(0, Location::RequiresRegister()); |
2368 } else if (IsPotentialUnboxedLoad()) { | 2369 } else if (IsPotentialUnboxedLoad()) { |
2369 locs->set_temp(0, opt ? Location::RequiresFpuRegister() | 2370 locs->set_temp(0, opt ? Location::RequiresFpuRegister() |
2370 : Location::FpuRegisterLocation(D1)); | 2371 : Location::FpuRegisterLocation(D1)); |
2371 locs->set_temp(1, Location::RequiresRegister()); | 2372 locs->set_temp(1, Location::RequiresRegister()); |
2372 } | 2373 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2418 | 2419 |
2419 // Fall through. | 2420 // Fall through. |
2420 __ b(&load_pointer); | 2421 __ b(&load_pointer); |
2421 | 2422 |
2422 if (!compiler->is_optimizing()) { | 2423 if (!compiler->is_optimizing()) { |
2423 locs()->live_registers()->Add(locs()->in(0)); | 2424 locs()->live_registers()->Add(locs()->in(0)); |
2424 } | 2425 } |
2425 | 2426 |
2426 { | 2427 { |
2427 __ Bind(&load_double); | 2428 __ Bind(&load_double); |
2428 BoxAllocationSlowPath::Allocate( | 2429 BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(), |
2429 compiler, this, compiler->double_class(), result_reg, temp); | 2430 result_reg, temp); |
2430 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2431 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes())); |
2431 __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag); | 2432 __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
2432 __ StoreDToOffset(value, | 2433 __ StoreDToOffset(value, result_reg, |
2433 result_reg, | |
2434 Double::value_offset() - kHeapObjectTag); | 2434 Double::value_offset() - kHeapObjectTag); |
2435 __ b(&done); | 2435 __ b(&done); |
2436 } | 2436 } |
2437 | 2437 |
2438 __ Bind(&load_pointer); | 2438 __ Bind(&load_pointer); |
2439 } | 2439 } |
2440 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); | 2440 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); |
2441 __ Bind(&done); | 2441 __ Bind(&done); |
2442 } | 2442 } |
2443 | 2443 |
2444 | 2444 |
2445 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2445 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
2446 bool opt) const { | 2446 bool opt) const { |
2447 const intptr_t kNumInputs = 1; | 2447 const intptr_t kNumInputs = 1; |
2448 const intptr_t kNumTemps = 0; | 2448 const intptr_t kNumTemps = 0; |
2449 LocationSummary* locs = new(zone) LocationSummary( | 2449 LocationSummary* locs = new (zone) |
2450 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2450 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2451 locs->set_in(0, Location::RegisterLocation(T0)); | 2451 locs->set_in(0, Location::RegisterLocation(T0)); |
2452 locs->set_out(0, Location::RegisterLocation(T0)); | 2452 locs->set_out(0, Location::RegisterLocation(T0)); |
2453 return locs; | 2453 return locs; |
2454 } | 2454 } |
2455 | 2455 |
2456 | 2456 |
2457 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2457 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2458 __ Comment("InstantiateTypeInstr"); | 2458 __ Comment("InstantiateTypeInstr"); |
2459 Register instantiator_reg = locs()->in(0).reg(); | 2459 Register instantiator_reg = locs()->in(0).reg(); |
2460 Register result_reg = locs()->out(0).reg(); | 2460 Register result_reg = locs()->out(0).reg(); |
2461 | 2461 |
2462 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2462 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
2463 // A runtime call to instantiate the type is required. | 2463 // A runtime call to instantiate the type is required. |
2464 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 2464 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
2465 __ LoadObject(TMP, Object::null_object()); | 2465 __ LoadObject(TMP, Object::null_object()); |
2466 __ sw(TMP, Address(SP, 2 * kWordSize)); // Make room for the result. | 2466 __ sw(TMP, Address(SP, 2 * kWordSize)); // Make room for the result. |
2467 __ LoadObject(TMP, type()); | 2467 __ LoadObject(TMP, type()); |
2468 __ sw(TMP, Address(SP, 1 * kWordSize)); | 2468 __ sw(TMP, Address(SP, 1 * kWordSize)); |
2469 // Push instantiator type arguments. | 2469 // Push instantiator type arguments. |
2470 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); | 2470 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); |
2471 | 2471 |
2472 compiler->GenerateRuntimeCall(token_pos(), | 2472 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2473 deopt_id(), | 2473 kInstantiateTypeRuntimeEntry, 2, locs()); |
2474 kInstantiateTypeRuntimeEntry, | |
2475 2, | |
2476 locs()); | |
2477 // Pop instantiated type. | 2474 // Pop instantiated type. |
2478 __ lw(result_reg, Address(SP, 2 * kWordSize)); | 2475 __ lw(result_reg, Address(SP, 2 * kWordSize)); |
2479 // Drop instantiator and uninstantiated type. | 2476 // Drop instantiator and uninstantiated type. |
2480 __ addiu(SP, SP, Immediate(3 * kWordSize)); | 2477 __ addiu(SP, SP, Immediate(3 * kWordSize)); |
2481 ASSERT(instantiator_reg == result_reg); | 2478 ASSERT(instantiator_reg == result_reg); |
2482 } | 2479 } |
2483 | 2480 |
2484 | 2481 |
2485 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2482 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
2486 Zone* zone, bool opt) const { | 2483 Zone* zone, |
| 2484 bool opt) const { |
2487 const intptr_t kNumInputs = 1; | 2485 const intptr_t kNumInputs = 1; |
2488 const intptr_t kNumTemps = 0; | 2486 const intptr_t kNumTemps = 0; |
2489 LocationSummary* locs = new(zone) LocationSummary( | 2487 LocationSummary* locs = new (zone) |
2490 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2488 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2491 locs->set_in(0, Location::RegisterLocation(T0)); | 2489 locs->set_in(0, Location::RegisterLocation(T0)); |
2492 locs->set_out(0, Location::RegisterLocation(T0)); | 2490 locs->set_out(0, Location::RegisterLocation(T0)); |
2493 return locs; | 2491 return locs; |
2494 } | 2492 } |
2495 | 2493 |
2496 | 2494 |
2497 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2495 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
2498 FlowGraphCompiler* compiler) { | 2496 FlowGraphCompiler* compiler) { |
2499 __ Comment("InstantiateTypeArgumentsInstr"); | 2497 __ Comment("InstantiateTypeArgumentsInstr"); |
2500 Register instantiator_reg = locs()->in(0).reg(); | 2498 Register instantiator_reg = locs()->in(0).reg(); |
(...skipping 17 matching lines...) Expand all Loading... |
2518 | 2516 |
2519 __ LoadObject(T2, type_arguments()); | 2517 __ LoadObject(T2, type_arguments()); |
2520 __ lw(T2, FieldAddress(T2, TypeArguments::instantiations_offset())); | 2518 __ lw(T2, FieldAddress(T2, TypeArguments::instantiations_offset())); |
2521 __ AddImmediate(T2, Array::data_offset() - kHeapObjectTag); | 2519 __ AddImmediate(T2, Array::data_offset() - kHeapObjectTag); |
2522 // The instantiations cache is initialized with Object::zero_array() and is | 2520 // The instantiations cache is initialized with Object::zero_array() and is |
2523 // therefore guaranteed to contain kNoInstantiator. No length check needed. | 2521 // therefore guaranteed to contain kNoInstantiator. No length check needed. |
2524 Label loop, found, slow_case; | 2522 Label loop, found, slow_case; |
2525 __ Bind(&loop); | 2523 __ Bind(&loop); |
2526 __ lw(T1, Address(T2, 0 * kWordSize)); // Cached instantiator. | 2524 __ lw(T1, Address(T2, 0 * kWordSize)); // Cached instantiator. |
2527 __ beq(T1, T0, &found); | 2525 __ beq(T1, T0, &found); |
2528 __ BranchNotEqual( | 2526 __ BranchNotEqual(T1, Immediate(Smi::RawValue(StubCode::kNoInstantiator)), |
2529 T1, Immediate(Smi::RawValue(StubCode::kNoInstantiator)), &loop); | 2527 &loop); |
2530 __ delay_slot()->addiu(T2, T2, Immediate(2 * kWordSize)); | 2528 __ delay_slot()->addiu(T2, T2, Immediate(2 * kWordSize)); |
2531 __ b(&slow_case); | 2529 __ b(&slow_case); |
2532 __ Bind(&found); | 2530 __ Bind(&found); |
2533 __ lw(T0, Address(T2, 1 * kWordSize)); // Cached instantiated args. | 2531 __ lw(T0, Address(T2, 1 * kWordSize)); // Cached instantiated args. |
2534 __ b(&type_arguments_instantiated); | 2532 __ b(&type_arguments_instantiated); |
2535 | 2533 |
2536 __ Bind(&slow_case); | 2534 __ Bind(&slow_case); |
2537 // Instantiate non-null type arguments. | 2535 // Instantiate non-null type arguments. |
2538 // A runtime call to instantiate the type arguments is required. | 2536 // A runtime call to instantiate the type arguments is required. |
2539 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 2537 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
2540 __ LoadObject(TMP, Object::null_object()); | 2538 __ LoadObject(TMP, Object::null_object()); |
2541 __ sw(TMP, Address(SP, 2 * kWordSize)); // Make room for the result. | 2539 __ sw(TMP, Address(SP, 2 * kWordSize)); // Make room for the result. |
2542 __ LoadObject(TMP, type_arguments()); | 2540 __ LoadObject(TMP, type_arguments()); |
2543 __ sw(TMP, Address(SP, 1 * kWordSize)); | 2541 __ sw(TMP, Address(SP, 1 * kWordSize)); |
2544 // Push instantiator type arguments. | 2542 // Push instantiator type arguments. |
2545 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); | 2543 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); |
2546 | 2544 |
2547 compiler->GenerateRuntimeCall(token_pos(), | 2545 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2548 deopt_id(), | 2546 kInstantiateTypeArgumentsRuntimeEntry, 2, |
2549 kInstantiateTypeArgumentsRuntimeEntry, | |
2550 2, | |
2551 locs()); | 2547 locs()); |
2552 // Pop instantiated type arguments. | 2548 // Pop instantiated type arguments. |
2553 __ lw(result_reg, Address(SP, 2 * kWordSize)); | 2549 __ lw(result_reg, Address(SP, 2 * kWordSize)); |
2554 // Drop instantiator and uninstantiated type arguments. | 2550 // Drop instantiator and uninstantiated type arguments. |
2555 __ addiu(SP, SP, Immediate(3 * kWordSize)); | 2551 __ addiu(SP, SP, Immediate(3 * kWordSize)); |
2556 __ Bind(&type_arguments_instantiated); | 2552 __ Bind(&type_arguments_instantiated); |
2557 } | 2553 } |
2558 | 2554 |
2559 | 2555 |
2560 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2556 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
2561 Zone* zone, | 2557 Zone* zone, |
2562 bool opt) const { | 2558 bool opt) const { |
2563 ASSERT(opt); | 2559 ASSERT(opt); |
2564 const intptr_t kNumInputs = 0; | 2560 const intptr_t kNumInputs = 0; |
2565 const intptr_t kNumTemps = 3; | 2561 const intptr_t kNumTemps = 3; |
2566 LocationSummary* locs = new(zone) LocationSummary( | 2562 LocationSummary* locs = new (zone) LocationSummary( |
2567 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2563 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2568 locs->set_temp(0, Location::RegisterLocation(T1)); | 2564 locs->set_temp(0, Location::RegisterLocation(T1)); |
2569 locs->set_temp(1, Location::RegisterLocation(T2)); | 2565 locs->set_temp(1, Location::RegisterLocation(T2)); |
2570 locs->set_temp(2, Location::RegisterLocation(T3)); | 2566 locs->set_temp(2, Location::RegisterLocation(T3)); |
2571 locs->set_out(0, Location::RegisterLocation(V0)); | 2567 locs->set_out(0, Location::RegisterLocation(V0)); |
2572 return locs; | 2568 return locs; |
2573 } | 2569 } |
2574 | 2570 |
2575 | 2571 |
2576 class AllocateContextSlowPath : public SlowPathCode { | 2572 class AllocateContextSlowPath : public SlowPathCode { |
2577 public: | 2573 public: |
2578 explicit AllocateContextSlowPath( | 2574 explicit AllocateContextSlowPath( |
2579 AllocateUninitializedContextInstr* instruction) | 2575 AllocateUninitializedContextInstr* instruction) |
2580 : instruction_(instruction) { } | 2576 : instruction_(instruction) {} |
2581 | 2577 |
2582 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2578 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2583 __ Comment("AllocateContextSlowPath"); | 2579 __ Comment("AllocateContextSlowPath"); |
2584 __ Bind(entry_label()); | 2580 __ Bind(entry_label()); |
2585 | 2581 |
2586 LocationSummary* locs = instruction_->locs(); | 2582 LocationSummary* locs = instruction_->locs(); |
2587 locs->live_registers()->Remove(locs->out(0)); | 2583 locs->live_registers()->Remove(locs->out(0)); |
2588 | 2584 |
2589 compiler->SaveLiveRegisters(locs); | 2585 compiler->SaveLiveRegisters(locs); |
2590 | 2586 |
2591 __ LoadImmediate(T1, instruction_->num_context_variables()); | 2587 __ LoadImmediate(T1, instruction_->num_context_variables()); |
2592 const Code& stub = Code::ZoneHandle( | 2588 const Code& stub = Code::ZoneHandle( |
2593 compiler->zone(), StubCode::AllocateContext_entry()->code()); | 2589 compiler->zone(), StubCode::AllocateContext_entry()->code()); |
2594 compiler->AddStubCallTarget(stub); | 2590 compiler->AddStubCallTarget(stub); |
2595 compiler->GenerateCall(instruction_->token_pos(), | 2591 compiler->GenerateCall(instruction_->token_pos(), |
2596 *StubCode::AllocateContext_entry(), | 2592 *StubCode::AllocateContext_entry(), |
2597 RawPcDescriptors::kOther, | 2593 RawPcDescriptors::kOther, locs); |
2598 locs); | |
2599 ASSERT(instruction_->locs()->out(0).reg() == V0); | 2594 ASSERT(instruction_->locs()->out(0).reg() == V0); |
2600 compiler->RestoreLiveRegisters(instruction_->locs()); | 2595 compiler->RestoreLiveRegisters(instruction_->locs()); |
2601 __ b(exit_label()); | 2596 __ b(exit_label()); |
2602 } | 2597 } |
2603 | 2598 |
2604 private: | 2599 private: |
2605 AllocateUninitializedContextInstr* instruction_; | 2600 AllocateUninitializedContextInstr* instruction_; |
2606 }; | 2601 }; |
2607 | 2602 |
2608 | 2603 |
2609 void AllocateUninitializedContextInstr::EmitNativeCode( | 2604 void AllocateUninitializedContextInstr::EmitNativeCode( |
2610 FlowGraphCompiler* compiler) { | 2605 FlowGraphCompiler* compiler) { |
2611 Register temp0 = locs()->temp(0).reg(); | 2606 Register temp0 = locs()->temp(0).reg(); |
2612 Register temp1 = locs()->temp(1).reg(); | 2607 Register temp1 = locs()->temp(1).reg(); |
2613 Register temp2 = locs()->temp(2).reg(); | 2608 Register temp2 = locs()->temp(2).reg(); |
2614 Register result = locs()->out(0).reg(); | 2609 Register result = locs()->out(0).reg(); |
2615 // Try allocate the object. | 2610 // Try allocate the object. |
2616 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2611 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
2617 compiler->AddSlowPathCode(slow_path); | 2612 compiler->AddSlowPathCode(slow_path); |
2618 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2613 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
2619 | 2614 |
2620 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 2615 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
2621 result, // instance | 2616 result, // instance |
2622 temp0, | 2617 temp0, temp1, temp2); |
2623 temp1, | |
2624 temp2); | |
2625 | 2618 |
2626 // Setup up number of context variables field. | 2619 // Setup up number of context variables field. |
2627 __ LoadImmediate(temp0, num_context_variables()); | 2620 __ LoadImmediate(temp0, num_context_variables()); |
2628 __ sw(temp0, FieldAddress(result, Context::num_variables_offset())); | 2621 __ sw(temp0, FieldAddress(result, Context::num_variables_offset())); |
2629 | 2622 |
2630 __ Bind(slow_path->exit_label()); | 2623 __ Bind(slow_path->exit_label()); |
2631 } | 2624 } |
2632 | 2625 |
2633 | 2626 |
2634 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 2627 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |
2635 bool opt) const { | 2628 bool opt) const { |
2636 const intptr_t kNumInputs = 0; | 2629 const intptr_t kNumInputs = 0; |
2637 const intptr_t kNumTemps = 1; | 2630 const intptr_t kNumTemps = 1; |
2638 LocationSummary* locs = new(zone) LocationSummary( | 2631 LocationSummary* locs = new (zone) |
2639 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2632 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2640 locs->set_temp(0, Location::RegisterLocation(T1)); | 2633 locs->set_temp(0, Location::RegisterLocation(T1)); |
2641 locs->set_out(0, Location::RegisterLocation(V0)); | 2634 locs->set_out(0, Location::RegisterLocation(V0)); |
2642 return locs; | 2635 return locs; |
2643 } | 2636 } |
2644 | 2637 |
2645 | 2638 |
2646 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2639 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2647 ASSERT(locs()->temp(0).reg() == T1); | 2640 ASSERT(locs()->temp(0).reg() == T1); |
2648 ASSERT(locs()->out(0).reg() == V0); | 2641 ASSERT(locs()->out(0).reg() == V0); |
2649 | 2642 |
2650 __ Comment("AllocateContextInstr"); | 2643 __ Comment("AllocateContextInstr"); |
2651 __ LoadImmediate(T1, num_context_variables()); | 2644 __ LoadImmediate(T1, num_context_variables()); |
2652 compiler->GenerateCall(token_pos(), | 2645 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), |
2653 *StubCode::AllocateContext_entry(), | 2646 RawPcDescriptors::kOther, locs()); |
2654 RawPcDescriptors::kOther, | |
2655 locs()); | |
2656 } | 2647 } |
2657 | 2648 |
2658 | 2649 |
2659 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2650 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
2660 bool opt) const { | 2651 bool opt) const { |
2661 const intptr_t kNumInputs = 1; | 2652 const intptr_t kNumInputs = 1; |
2662 const intptr_t kNumTemps = 1; | 2653 const intptr_t kNumTemps = 1; |
2663 LocationSummary* locs = new(zone) LocationSummary( | 2654 LocationSummary* locs = new (zone) |
2664 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2655 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2665 locs->set_in(0, Location::RegisterLocation(T0)); | 2656 locs->set_in(0, Location::RegisterLocation(T0)); |
2666 locs->set_temp(0, Location::RegisterLocation(T1)); | 2657 locs->set_temp(0, Location::RegisterLocation(T1)); |
2667 return locs; | 2658 return locs; |
2668 } | 2659 } |
2669 | 2660 |
2670 | 2661 |
2671 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2662 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2672 Register field = locs()->in(0).reg(); | 2663 Register field = locs()->in(0).reg(); |
2673 Register temp = locs()->temp(0).reg(); | 2664 Register temp = locs()->temp(0).reg(); |
2674 | 2665 |
2675 Label call_runtime, no_call; | 2666 Label call_runtime, no_call; |
2676 __ Comment("InitStaticFieldInstr"); | 2667 __ Comment("InitStaticFieldInstr"); |
2677 | 2668 |
2678 __ lw(temp, FieldAddress(field, Field::static_value_offset())); | 2669 __ lw(temp, FieldAddress(field, Field::static_value_offset())); |
2679 __ BranchEqual(temp, Object::sentinel(), &call_runtime); | 2670 __ BranchEqual(temp, Object::sentinel(), &call_runtime); |
2680 __ BranchNotEqual(temp, Object::transition_sentinel(), &no_call); | 2671 __ BranchNotEqual(temp, Object::transition_sentinel(), &no_call); |
2681 | 2672 |
2682 __ Bind(&call_runtime); | 2673 __ Bind(&call_runtime); |
2683 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 2674 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
2684 __ LoadObject(TMP, Object::null_object()); | 2675 __ LoadObject(TMP, Object::null_object()); |
2685 __ sw(TMP, Address(SP, 1 * kWordSize)); // Make room for (unused) result. | 2676 __ sw(TMP, Address(SP, 1 * kWordSize)); // Make room for (unused) result. |
2686 __ sw(field, Address(SP, 0 * kWordSize)); | 2677 __ sw(field, Address(SP, 0 * kWordSize)); |
2687 | 2678 |
2688 compiler->GenerateRuntimeCall(token_pos(), | 2679 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2689 deopt_id(), | 2680 kInitStaticFieldRuntimeEntry, 1, locs()); |
2690 kInitStaticFieldRuntimeEntry, | |
2691 1, | |
2692 locs()); | |
2693 | 2681 |
2694 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Purge argument and result. | 2682 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Purge argument and result. |
2695 | 2683 |
2696 __ Bind(&no_call); | 2684 __ Bind(&no_call); |
2697 } | 2685 } |
2698 | 2686 |
2699 | 2687 |
2700 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2688 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
2701 bool opt) const { | 2689 bool opt) const { |
2702 const intptr_t kNumInputs = 1; | 2690 const intptr_t kNumInputs = 1; |
2703 const intptr_t kNumTemps = 0; | 2691 const intptr_t kNumTemps = 0; |
2704 LocationSummary* locs = new(zone) LocationSummary( | 2692 LocationSummary* locs = new (zone) |
2705 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2693 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2706 locs->set_in(0, Location::RegisterLocation(T0)); | 2694 locs->set_in(0, Location::RegisterLocation(T0)); |
2707 locs->set_out(0, Location::RegisterLocation(T0)); | 2695 locs->set_out(0, Location::RegisterLocation(T0)); |
2708 return locs; | 2696 return locs; |
2709 } | 2697 } |
2710 | 2698 |
2711 | 2699 |
2712 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2700 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2713 Register context_value = locs()->in(0).reg(); | 2701 Register context_value = locs()->in(0).reg(); |
2714 Register result = locs()->out(0).reg(); | 2702 Register result = locs()->out(0).reg(); |
2715 | 2703 |
2716 __ Comment("CloneContextInstr"); | 2704 __ Comment("CloneContextInstr"); |
2717 | 2705 |
2718 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 2706 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
2719 __ LoadObject(TMP, Object::null_object()); // Make room for the result. | 2707 __ LoadObject(TMP, Object::null_object()); // Make room for the result. |
2720 __ sw(TMP, Address(SP, 1 * kWordSize)); | 2708 __ sw(TMP, Address(SP, 1 * kWordSize)); |
2721 __ sw(context_value, Address(SP, 0 * kWordSize)); | 2709 __ sw(context_value, Address(SP, 0 * kWordSize)); |
2722 | 2710 |
2723 compiler->GenerateRuntimeCall(token_pos(), | 2711 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2724 deopt_id(), | 2712 kCloneContextRuntimeEntry, 1, locs()); |
2725 kCloneContextRuntimeEntry, | |
2726 1, | |
2727 locs()); | |
2728 __ lw(result, Address(SP, 1 * kWordSize)); // Get result (cloned context). | 2713 __ lw(result, Address(SP, 1 * kWordSize)); // Get result (cloned context). |
2729 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 2714 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
2730 } | 2715 } |
2731 | 2716 |
2732 | 2717 |
2733 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2718 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
2734 bool opt) const { | 2719 bool opt) const { |
2735 UNREACHABLE(); | 2720 UNREACHABLE(); |
2736 return NULL; | 2721 return NULL; |
2737 } | 2722 } |
2738 | 2723 |
2739 | 2724 |
2740 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2725 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2741 __ Bind(compiler->GetJumpLabel(this)); | 2726 __ Bind(compiler->GetJumpLabel(this)); |
2742 compiler->AddExceptionHandler(catch_try_index(), | 2727 compiler->AddExceptionHandler(catch_try_index(), try_index(), |
2743 try_index(), | |
2744 compiler->assembler()->CodeSize(), | 2728 compiler->assembler()->CodeSize(), |
2745 catch_handler_types_, | 2729 catch_handler_types_, needs_stacktrace()); |
2746 needs_stacktrace()); | |
2747 // On lazy deoptimization we patch the optimized code here to enter the | 2730 // On lazy deoptimization we patch the optimized code here to enter the |
2748 // deoptimization stub. | 2731 // deoptimization stub. |
2749 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 2732 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |
2750 if (compiler->is_optimizing()) { | 2733 if (compiler->is_optimizing()) { |
2751 compiler->AddDeoptIndexAtCall(deopt_id); | 2734 compiler->AddDeoptIndexAtCall(deopt_id); |
2752 } else { | 2735 } else { |
2753 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 2736 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id, |
2754 deopt_id, | |
2755 TokenPosition::kNoSource); | 2737 TokenPosition::kNoSource); |
2756 } | 2738 } |
2757 if (HasParallelMove()) { | 2739 if (HasParallelMove()) { |
2758 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2740 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
2759 } | 2741 } |
2760 // Restore SP from FP as we are coming from a throw and the code for | 2742 // Restore SP from FP as we are coming from a throw and the code for |
2761 // popping arguments has not been run. | 2743 // popping arguments has not been run. |
2762 const intptr_t fp_sp_dist = | 2744 const intptr_t fp_sp_dist = |
2763 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 2745 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
2764 ASSERT(fp_sp_dist <= 0); | 2746 ASSERT(fp_sp_dist <= 0); |
2765 __ AddImmediate(SP, FP, fp_sp_dist); | 2747 __ AddImmediate(SP, FP, fp_sp_dist); |
2766 | 2748 |
2767 // Restore stack and initialize the two exception variables: | 2749 // Restore stack and initialize the two exception variables: |
2768 // exception and stack trace variables. | 2750 // exception and stack trace variables. |
2769 __ StoreToOffset(kExceptionObjectReg, | 2751 __ StoreToOffset(kExceptionObjectReg, FP, |
2770 FP, exception_var().index() * kWordSize); | 2752 exception_var().index() * kWordSize); |
2771 __ StoreToOffset(kStackTraceObjectReg, | 2753 __ StoreToOffset(kStackTraceObjectReg, FP, |
2772 FP, stacktrace_var().index() * kWordSize); | 2754 stacktrace_var().index() * kWordSize); |
2773 } | 2755 } |
2774 | 2756 |
2775 | 2757 |
2776 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 2758 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |
2777 bool opt) const { | 2759 bool opt) const { |
2778 const intptr_t kNumInputs = 0; | 2760 const intptr_t kNumInputs = 0; |
2779 const intptr_t kNumTemps = 1; | 2761 const intptr_t kNumTemps = 1; |
2780 LocationSummary* summary = new(zone) LocationSummary( | 2762 LocationSummary* summary = new (zone) LocationSummary( |
2781 zone, kNumInputs, | 2763 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2782 kNumTemps, | |
2783 LocationSummary::kCallOnSlowPath); | |
2784 summary->set_temp(0, Location::RequiresRegister()); | 2764 summary->set_temp(0, Location::RequiresRegister()); |
2785 return summary; | 2765 return summary; |
2786 } | 2766 } |
2787 | 2767 |
2788 | 2768 |
2789 class CheckStackOverflowSlowPath : public SlowPathCode { | 2769 class CheckStackOverflowSlowPath : public SlowPathCode { |
2790 public: | 2770 public: |
2791 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2771 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
2792 : instruction_(instruction) { } | 2772 : instruction_(instruction) {} |
2793 | 2773 |
2794 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2774 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2795 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { | 2775 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { |
2796 Register value = instruction_->locs()->temp(0).reg(); | 2776 Register value = instruction_->locs()->temp(0).reg(); |
2797 __ Comment("CheckStackOverflowSlowPathOsr"); | 2777 __ Comment("CheckStackOverflowSlowPathOsr"); |
2798 __ Bind(osr_entry_label()); | 2778 __ Bind(osr_entry_label()); |
2799 __ LoadImmediate(value, Thread::kOsrRequest); | 2779 __ LoadImmediate(value, Thread::kOsrRequest); |
2800 __ sw(value, Address(THR, Thread::stack_overflow_flags_offset())); | 2780 __ sw(value, Address(THR, Thread::stack_overflow_flags_offset())); |
2801 } | 2781 } |
2802 __ Comment("CheckStackOverflowSlowPath"); | 2782 __ Comment("CheckStackOverflowSlowPath"); |
2803 __ Bind(entry_label()); | 2783 __ Bind(entry_label()); |
2804 compiler->SaveLiveRegisters(instruction_->locs()); | 2784 compiler->SaveLiveRegisters(instruction_->locs()); |
2805 // pending_deoptimization_env_ is needed to generate a runtime call that | 2785 // pending_deoptimization_env_ is needed to generate a runtime call that |
2806 // may throw an exception. | 2786 // may throw an exception. |
2807 ASSERT(compiler->pending_deoptimization_env_ == NULL); | 2787 ASSERT(compiler->pending_deoptimization_env_ == NULL); |
2808 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); | 2788 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |
2809 compiler->pending_deoptimization_env_ = env; | 2789 compiler->pending_deoptimization_env_ = env; |
2810 compiler->GenerateRuntimeCall(instruction_->token_pos(), | 2790 compiler->GenerateRuntimeCall( |
2811 instruction_->deopt_id(), | 2791 instruction_->token_pos(), instruction_->deopt_id(), |
2812 kStackOverflowRuntimeEntry, | 2792 kStackOverflowRuntimeEntry, 0, instruction_->locs()); |
2813 0, | |
2814 instruction_->locs()); | |
2815 | 2793 |
2816 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { | 2794 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { |
2817 // In unoptimized code, record loop stack checks as possible OSR entries. | 2795 // In unoptimized code, record loop stack checks as possible OSR entries. |
2818 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, | 2796 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, |
2819 instruction_->deopt_id(), | 2797 instruction_->deopt_id(), |
2820 TokenPosition::kNoSource); | 2798 TokenPosition::kNoSource); |
2821 } | 2799 } |
2822 compiler->pending_deoptimization_env_ = NULL; | 2800 compiler->pending_deoptimization_env_ = NULL; |
2823 compiler->RestoreLiveRegisters(instruction_->locs()); | 2801 compiler->RestoreLiveRegisters(instruction_->locs()); |
2824 __ b(exit_label()); | 2802 __ b(exit_label()); |
(...skipping 19 matching lines...) Expand all Loading... |
2844 __ BranchUnsignedLessEqual(SP, CMPRES1, slow_path->entry_label()); | 2822 __ BranchUnsignedLessEqual(SP, CMPRES1, slow_path->entry_label()); |
2845 if (compiler->CanOSRFunction() && in_loop()) { | 2823 if (compiler->CanOSRFunction() && in_loop()) { |
2846 Register temp = locs()->temp(0).reg(); | 2824 Register temp = locs()->temp(0).reg(); |
2847 // In unoptimized code check the usage counter to trigger OSR at loop | 2825 // In unoptimized code check the usage counter to trigger OSR at loop |
2848 // stack checks. Use progressively higher thresholds for more deeply | 2826 // stack checks. Use progressively higher thresholds for more deeply |
2849 // nested loops to attempt to hit outer loops with OSR when possible. | 2827 // nested loops to attempt to hit outer loops with OSR when possible. |
2850 __ LoadObject(temp, compiler->parsed_function().function()); | 2828 __ LoadObject(temp, compiler->parsed_function().function()); |
2851 intptr_t threshold = | 2829 intptr_t threshold = |
2852 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2830 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
2853 __ lw(temp, FieldAddress(temp, Function::usage_counter_offset())); | 2831 __ lw(temp, FieldAddress(temp, Function::usage_counter_offset())); |
2854 __ BranchSignedGreaterEqual( | 2832 __ BranchSignedGreaterEqual(temp, Immediate(threshold), |
2855 temp, Immediate(threshold), slow_path->osr_entry_label()); | 2833 slow_path->osr_entry_label()); |
2856 } | 2834 } |
2857 if (compiler->ForceSlowPathForStackOverflow()) { | 2835 if (compiler->ForceSlowPathForStackOverflow()) { |
2858 __ b(slow_path->entry_label()); | 2836 __ b(slow_path->entry_label()); |
2859 } | 2837 } |
2860 __ Bind(slow_path->exit_label()); | 2838 __ Bind(slow_path->exit_label()); |
2861 } | 2839 } |
2862 | 2840 |
2863 | 2841 |
2864 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2842 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
2865 BinarySmiOpInstr* shift_left) { | 2843 BinarySmiOpInstr* shift_left) { |
2866 const LocationSummary& locs = *shift_left->locs(); | 2844 const LocationSummary& locs = *shift_left->locs(); |
2867 Register left = locs.in(0).reg(); | 2845 Register left = locs.in(0).reg(); |
2868 Register result = locs.out(0).reg(); | 2846 Register result = locs.out(0).reg(); |
2869 Label* deopt = shift_left->CanDeoptimize() ? | 2847 Label* deopt = shift_left->CanDeoptimize() |
2870 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | 2848 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
2871 : NULL; | 2849 ICData::kDeoptBinarySmiOp) |
| 2850 : NULL; |
2872 | 2851 |
2873 __ Comment("EmitSmiShiftLeft"); | 2852 __ Comment("EmitSmiShiftLeft"); |
2874 | 2853 |
2875 if (locs.in(1).IsConstant()) { | 2854 if (locs.in(1).IsConstant()) { |
2876 const Object& constant = locs.in(1).constant(); | 2855 const Object& constant = locs.in(1).constant(); |
2877 ASSERT(constant.IsSmi()); | 2856 ASSERT(constant.IsSmi()); |
2878 // Immediate shift operation takes 5 bits for the count. | 2857 // Immediate shift operation takes 5 bits for the count. |
2879 const intptr_t kCountLimit = 0x1F; | 2858 const intptr_t kCountLimit = 0x1F; |
2880 const intptr_t value = Smi::Cast(constant).Value(); | 2859 const intptr_t value = Smi::Cast(constant).Value(); |
2881 ASSERT((0 < value) && (value < kCountLimit)); | 2860 ASSERT((0 < value) && (value < kCountLimit)); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2923 if (!shift_left->can_overflow()) { | 2902 if (!shift_left->can_overflow()) { |
2924 if (right_needs_check) { | 2903 if (right_needs_check) { |
2925 const bool right_may_be_negative = | 2904 const bool right_may_be_negative = |
2926 (right_range == NULL) || !right_range->IsPositive(); | 2905 (right_range == NULL) || !right_range->IsPositive(); |
2927 if (right_may_be_negative) { | 2906 if (right_may_be_negative) { |
2928 ASSERT(shift_left->CanDeoptimize()); | 2907 ASSERT(shift_left->CanDeoptimize()); |
2929 __ bltz(right, deopt); | 2908 __ bltz(right, deopt); |
2930 } | 2909 } |
2931 Label done, is_not_zero; | 2910 Label done, is_not_zero; |
2932 | 2911 |
2933 __ sltiu(CMPRES1, | 2912 __ sltiu(CMPRES1, right, |
2934 right, Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); | 2913 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); |
2935 __ movz(result, ZR, CMPRES1); // result = right >= kBits ? 0 : result. | 2914 __ movz(result, ZR, CMPRES1); // result = right >= kBits ? 0 : result. |
2936 __ sra(TMP, right, kSmiTagSize); | 2915 __ sra(TMP, right, kSmiTagSize); |
2937 __ sllv(TMP, left, TMP); | 2916 __ sllv(TMP, left, TMP); |
2938 // result = right < kBits ? left << right : result. | 2917 // result = right < kBits ? left << right : result. |
2939 __ movn(result, TMP, CMPRES1); | 2918 __ movn(result, TMP, CMPRES1); |
2940 } else { | 2919 } else { |
2941 __ sra(TMP, right, kSmiTagSize); | 2920 __ sra(TMP, right, kSmiTagSize); |
2942 __ sllv(result, left, TMP); | 2921 __ sllv(result, left, TMP); |
2943 } | 2922 } |
2944 } else { | 2923 } else { |
(...skipping 13 matching lines...) Expand all Loading... |
2958 __ bne(CMPRES1, left, deopt); // Overflow. | 2937 __ bne(CMPRES1, left, deopt); // Overflow. |
2959 // Shift for result now we know there is no overflow. | 2938 // Shift for result now we know there is no overflow. |
2960 __ sllv(result, left, temp); | 2939 __ sllv(result, left, temp); |
2961 } | 2940 } |
2962 } | 2941 } |
2963 | 2942 |
2964 | 2943 |
2965 class CheckedSmiSlowPath : public SlowPathCode { | 2944 class CheckedSmiSlowPath : public SlowPathCode { |
2966 public: | 2945 public: |
2967 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) | 2946 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) |
2968 : instruction_(instruction), try_index_(try_index) { } | 2947 : instruction_(instruction), try_index_(try_index) {} |
2969 | 2948 |
2970 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2949 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2971 if (Assembler::EmittingComments()) { | 2950 if (Assembler::EmittingComments()) { |
2972 __ Comment("slow path smi operation"); | 2951 __ Comment("slow path smi operation"); |
2973 } | 2952 } |
2974 __ Bind(entry_label()); | 2953 __ Bind(entry_label()); |
2975 LocationSummary* locs = instruction_->locs(); | 2954 LocationSummary* locs = instruction_->locs(); |
2976 Register result = locs->out(0).reg(); | 2955 Register result = locs->out(0).reg(); |
2977 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 2956 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
2978 | 2957 |
2979 compiler->SaveLiveRegisters(locs); | 2958 compiler->SaveLiveRegisters(locs); |
2980 __ Push(locs->in(0).reg()); | 2959 __ Push(locs->in(0).reg()); |
2981 __ Push(locs->in(1).reg()); | 2960 __ Push(locs->in(1).reg()); |
2982 compiler->EmitMegamorphicInstanceCall( | 2961 compiler->EmitMegamorphicInstanceCall( |
2983 *instruction_->call()->ic_data(), | 2962 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
2984 instruction_->call()->ArgumentCount(), | 2963 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
2985 instruction_->call()->deopt_id(), | 2964 locs, try_index_, |
2986 instruction_->call()->token_pos(), | |
2987 locs, | |
2988 try_index_, | |
2989 /* slow_path_argument_count = */ 2); | 2965 /* slow_path_argument_count = */ 2); |
2990 __ mov(result, V0); | 2966 __ mov(result, V0); |
2991 compiler->RestoreLiveRegisters(locs); | 2967 compiler->RestoreLiveRegisters(locs); |
2992 __ b(exit_label()); | 2968 __ b(exit_label()); |
2993 } | 2969 } |
2994 | 2970 |
2995 private: | 2971 private: |
2996 CheckedSmiOpInstr* instruction_; | 2972 CheckedSmiOpInstr* instruction_; |
2997 intptr_t try_index_; | 2973 intptr_t try_index_; |
2998 }; | 2974 }; |
2999 | 2975 |
3000 | 2976 |
3001 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 2977 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
3002 bool opt) const { | 2978 bool opt) const { |
3003 const intptr_t kNumInputs = 2; | 2979 const intptr_t kNumInputs = 2; |
3004 const intptr_t kNumTemps = 0; | 2980 const intptr_t kNumTemps = 0; |
3005 LocationSummary* summary = new(zone) LocationSummary( | 2981 LocationSummary* summary = new (zone) LocationSummary( |
3006 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2982 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
3007 summary->set_in(0, Location::RequiresRegister()); | 2983 summary->set_in(0, Location::RequiresRegister()); |
3008 summary->set_in(1, Location::RequiresRegister()); | 2984 summary->set_in(1, Location::RequiresRegister()); |
3009 summary->set_out(0, Location::RequiresRegister()); | 2985 summary->set_out(0, Location::RequiresRegister()); |
3010 return summary; | 2986 return summary; |
3011 } | 2987 } |
3012 | 2988 |
3013 | 2989 |
3014 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2990 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3015 CheckedSmiSlowPath* slow_path = | 2991 CheckedSmiSlowPath* slow_path = |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3072 | 3048 |
3073 class CheckedSmiComparisonSlowPath : public SlowPathCode { | 3049 class CheckedSmiComparisonSlowPath : public SlowPathCode { |
3074 public: | 3050 public: |
3075 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, | 3051 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, |
3076 intptr_t try_index, | 3052 intptr_t try_index, |
3077 BranchLabels labels, | 3053 BranchLabels labels, |
3078 bool merged) | 3054 bool merged) |
3079 : instruction_(instruction), | 3055 : instruction_(instruction), |
3080 try_index_(try_index), | 3056 try_index_(try_index), |
3081 labels_(labels), | 3057 labels_(labels), |
3082 merged_(merged) { } | 3058 merged_(merged) {} |
3083 | 3059 |
3084 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 3060 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
3085 if (Assembler::EmittingComments()) { | 3061 if (Assembler::EmittingComments()) { |
3086 __ Comment("slow path smi operation"); | 3062 __ Comment("slow path smi operation"); |
3087 } | 3063 } |
3088 __ Bind(entry_label()); | 3064 __ Bind(entry_label()); |
3089 LocationSummary* locs = instruction_->locs(); | 3065 LocationSummary* locs = instruction_->locs(); |
3090 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); | 3066 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); |
3091 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 3067 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
3092 | 3068 |
3093 compiler->SaveLiveRegisters(locs); | 3069 compiler->SaveLiveRegisters(locs); |
3094 __ Push(locs->in(0).reg()); | 3070 __ Push(locs->in(0).reg()); |
3095 __ Push(locs->in(1).reg()); | 3071 __ Push(locs->in(1).reg()); |
3096 compiler->EmitMegamorphicInstanceCall( | 3072 compiler->EmitMegamorphicInstanceCall( |
3097 *instruction_->call()->ic_data(), | 3073 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
3098 instruction_->call()->ArgumentCount(), | 3074 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
3099 instruction_->call()->deopt_id(), | 3075 locs, try_index_, |
3100 instruction_->call()->token_pos(), | |
3101 locs, | |
3102 try_index_, | |
3103 /* slow_path_argument_count = */ 2); | 3076 /* slow_path_argument_count = */ 2); |
3104 __ mov(result, V0); | 3077 __ mov(result, V0); |
3105 compiler->RestoreLiveRegisters(locs); | 3078 compiler->RestoreLiveRegisters(locs); |
3106 if (merged_) { | 3079 if (merged_) { |
3107 __ BranchEqual(result, Bool::True(), | 3080 __ BranchEqual(result, Bool::True(), instruction_->is_negated() |
3108 instruction_->is_negated() ? labels_.false_label : labels_.true_label); | 3081 ? labels_.false_label |
3109 __ b(instruction_->is_negated() | 3082 : labels_.true_label); |
3110 ? labels_.true_label : labels_.false_label); | 3083 __ b(instruction_->is_negated() ? labels_.true_label |
| 3084 : labels_.false_label); |
3111 } else { | 3085 } else { |
3112 __ b(exit_label()); | 3086 __ b(exit_label()); |
3113 } | 3087 } |
3114 } | 3088 } |
3115 | 3089 |
3116 private: | 3090 private: |
3117 CheckedSmiComparisonInstr* instruction_; | 3091 CheckedSmiComparisonInstr* instruction_; |
3118 intptr_t try_index_; | 3092 intptr_t try_index_; |
3119 BranchLabels labels_; | 3093 BranchLabels labels_; |
3120 bool merged_; | 3094 bool merged_; |
3121 }; | 3095 }; |
3122 | 3096 |
3123 | 3097 |
3124 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 3098 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
3125 Zone* zone, bool opt) const { | 3099 Zone* zone, |
| 3100 bool opt) const { |
3126 const intptr_t kNumInputs = 2; | 3101 const intptr_t kNumInputs = 2; |
3127 const intptr_t kNumTemps = 1; | 3102 const intptr_t kNumTemps = 1; |
3128 LocationSummary* summary = new(zone) LocationSummary( | 3103 LocationSummary* summary = new (zone) LocationSummary( |
3129 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3104 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
3130 summary->set_in(0, Location::RequiresRegister()); | 3105 summary->set_in(0, Location::RequiresRegister()); |
3131 summary->set_in(1, Location::RequiresRegister()); | 3106 summary->set_in(1, Location::RequiresRegister()); |
3132 summary->set_temp(0, Location::RequiresRegister()); | 3107 summary->set_temp(0, Location::RequiresRegister()); |
3133 summary->set_out(0, Location::RequiresRegister()); | 3108 summary->set_out(0, Location::RequiresRegister()); |
3134 return summary; | 3109 return summary; |
3135 } | 3110 } |
3136 | 3111 |
3137 | 3112 |
3138 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 3113 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
3139 FlowGraphCompiler* compiler, BranchLabels labels) { | 3114 FlowGraphCompiler* compiler, |
| 3115 BranchLabels labels) { |
3140 return EmitSmiComparisonOp(compiler, *locs(), kind()); | 3116 return EmitSmiComparisonOp(compiler, *locs(), kind()); |
3141 } | 3117 } |
3142 | 3118 |
3143 | 3119 |
3144 #define EMIT_SMI_CHECK \ | 3120 #define EMIT_SMI_CHECK \ |
3145 Register left = locs()->in(0).reg(); \ | 3121 Register left = locs()->in(0).reg(); \ |
3146 Register right = locs()->in(1).reg(); \ | 3122 Register right = locs()->in(1).reg(); \ |
3147 Register temp = locs()->temp(0).reg(); \ | 3123 Register temp = locs()->temp(0).reg(); \ |
3148 intptr_t left_cid = this->left()->Type()->ToCid(); \ | 3124 intptr_t left_cid = this->left()->Type()->ToCid(); \ |
3149 intptr_t right_cid = this->right()->Type()->ToCid(); \ | 3125 intptr_t right_cid = this->right()->Type()->ToCid(); \ |
3150 if (this->left()->definition() == this->right()->definition()) { \ | 3126 if (this->left()->definition() == this->right()->definition()) { \ |
3151 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); \ | 3127 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); \ |
3152 } else if (left_cid == kSmiCid) { \ | 3128 } else if (left_cid == kSmiCid) { \ |
3153 __ andi(CMPRES1, right, Immediate(kSmiTagMask)); \ | 3129 __ andi(CMPRES1, right, Immediate(kSmiTagMask)); \ |
3154 } else if (right_cid == kSmiCid) { \ | 3130 } else if (right_cid == kSmiCid) { \ |
3155 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); \ | 3131 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); \ |
3156 } else { \ | 3132 } else { \ |
3157 __ or_(temp, left, right); \ | 3133 __ or_(temp, left, right); \ |
3158 __ andi(CMPRES1, temp, Immediate(kSmiTagMask)); \ | 3134 __ andi(CMPRES1, temp, Immediate(kSmiTagMask)); \ |
3159 } \ | 3135 } \ |
3160 __ bne(CMPRES1, ZR, slow_path->entry_label()); \ | 3136 __ bne(CMPRES1, ZR, slow_path->entry_label()); |
3161 | 3137 |
3162 | 3138 |
3163 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3139 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
3164 BranchInstr* branch) { | 3140 BranchInstr* branch) { |
3165 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3141 BranchLabels labels = compiler->CreateBranchLabels(branch); |
3166 CheckedSmiComparisonSlowPath* slow_path = | 3142 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3167 new CheckedSmiComparisonSlowPath(this, | 3143 this, compiler->CurrentTryIndex(), labels, |
3168 compiler->CurrentTryIndex(), | 3144 /* merged = */ true); |
3169 labels, | |
3170 /* merged = */ true); | |
3171 compiler->AddSlowPathCode(slow_path); | 3145 compiler->AddSlowPathCode(slow_path); |
3172 EMIT_SMI_CHECK; | 3146 EMIT_SMI_CHECK; |
3173 Condition true_condition = EmitComparisonCode(compiler, labels); | 3147 Condition true_condition = EmitComparisonCode(compiler, labels); |
3174 EmitBranchOnCondition(compiler, true_condition, labels); | 3148 EmitBranchOnCondition(compiler, true_condition, labels); |
3175 __ Bind(slow_path->exit_label()); | 3149 __ Bind(slow_path->exit_label()); |
3176 } | 3150 } |
3177 | 3151 |
3178 | 3152 |
3179 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3153 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3180 Label true_label, false_label, done; | 3154 Label true_label, false_label, done; |
3181 BranchLabels labels = { &true_label, &false_label, &false_label }; | 3155 BranchLabels labels = {&true_label, &false_label, &false_label}; |
3182 CheckedSmiComparisonSlowPath* slow_path = | 3156 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3183 new CheckedSmiComparisonSlowPath(this, | 3157 this, compiler->CurrentTryIndex(), labels, |
3184 compiler->CurrentTryIndex(), | 3158 /* merged = */ false); |
3185 labels, | |
3186 /* merged = */ false); | |
3187 compiler->AddSlowPathCode(slow_path); | 3159 compiler->AddSlowPathCode(slow_path); |
3188 EMIT_SMI_CHECK; | 3160 EMIT_SMI_CHECK; |
3189 Condition true_condition = EmitComparisonCode(compiler, labels); | 3161 Condition true_condition = EmitComparisonCode(compiler, labels); |
3190 EmitBranchOnCondition(compiler, true_condition, labels); | 3162 EmitBranchOnCondition(compiler, true_condition, labels); |
3191 Register result = locs()->out(0).reg(); | 3163 Register result = locs()->out(0).reg(); |
3192 __ Bind(&false_label); | 3164 __ Bind(&false_label); |
3193 __ LoadObject(result, Bool::False()); | 3165 __ LoadObject(result, Bool::False()); |
3194 __ b(&done); | 3166 __ b(&done); |
3195 __ Bind(&true_label); | 3167 __ Bind(&true_label); |
3196 __ LoadObject(result, Bool::True()); | 3168 __ LoadObject(result, Bool::True()); |
3197 __ Bind(&done); | 3169 __ Bind(&done); |
3198 __ Bind(slow_path->exit_label()); | 3170 __ Bind(slow_path->exit_label()); |
3199 } | 3171 } |
3200 | 3172 |
3201 | 3173 |
3202 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 3174 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
3203 bool opt) const { | 3175 bool opt) const { |
3204 const intptr_t kNumInputs = 2; | 3176 const intptr_t kNumInputs = 2; |
3205 const intptr_t kNumTemps = | 3177 const intptr_t kNumTemps = |
3206 ((op_kind() == Token::kADD) || | 3178 ((op_kind() == Token::kADD) || (op_kind() == Token::kMOD) || |
3207 (op_kind() == Token::kMOD) || | |
3208 (op_kind() == Token::kTRUNCDIV) || | 3179 (op_kind() == Token::kTRUNCDIV) || |
3209 (((op_kind() == Token::kSHL) && can_overflow()) || | 3180 (((op_kind() == Token::kSHL) && can_overflow()) || |
3210 (op_kind() == Token::kSHR))) ? 1 : 0; | 3181 (op_kind() == Token::kSHR))) |
3211 LocationSummary* summary = new(zone) LocationSummary( | 3182 ? 1 |
3212 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3183 : 0; |
| 3184 LocationSummary* summary = new (zone) |
| 3185 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3213 if (op_kind() == Token::kTRUNCDIV) { | 3186 if (op_kind() == Token::kTRUNCDIV) { |
3214 summary->set_in(0, Location::RequiresRegister()); | 3187 summary->set_in(0, Location::RequiresRegister()); |
3215 if (RightIsPowerOfTwoConstant()) { | 3188 if (RightIsPowerOfTwoConstant()) { |
3216 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 3189 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
3217 summary->set_in(1, Location::Constant(right_constant)); | 3190 summary->set_in(1, Location::Constant(right_constant)); |
3218 } else { | 3191 } else { |
3219 summary->set_in(1, Location::RequiresRegister()); | 3192 summary->set_in(1, Location::RequiresRegister()); |
3220 } | 3193 } |
3221 summary->set_temp(0, Location::RequiresRegister()); | 3194 summary->set_temp(0, Location::RequiresRegister()); |
3222 summary->set_out(0, Location::RequiresRegister()); | 3195 summary->set_out(0, Location::RequiresRegister()); |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3493 } | 3466 } |
3494 | 3467 |
3495 | 3468 |
3496 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3469 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
3497 bool opt) const { | 3470 bool opt) const { |
3498 intptr_t left_cid = left()->Type()->ToCid(); | 3471 intptr_t left_cid = left()->Type()->ToCid(); |
3499 intptr_t right_cid = right()->Type()->ToCid(); | 3472 intptr_t right_cid = right()->Type()->ToCid(); |
3500 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3473 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
3501 const intptr_t kNumInputs = 2; | 3474 const intptr_t kNumInputs = 2; |
3502 const intptr_t kNumTemps = 0; | 3475 const intptr_t kNumTemps = 0; |
3503 LocationSummary* summary = new(zone) LocationSummary( | 3476 LocationSummary* summary = new (zone) |
3504 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3477 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3505 summary->set_in(0, Location::RequiresRegister()); | 3478 summary->set_in(0, Location::RequiresRegister()); |
3506 summary->set_in(1, Location::RequiresRegister()); | 3479 summary->set_in(1, Location::RequiresRegister()); |
3507 return summary; | 3480 return summary; |
3508 } | 3481 } |
3509 | 3482 |
3510 | 3483 |
3511 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3484 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3512 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3485 Label* deopt = |
3513 ICData::kDeoptBinaryDoubleOp, | 3486 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
3514 licm_hoisted_ ? ICData::kHoisted : 0); | 3487 licm_hoisted_ ? ICData::kHoisted : 0); |
3515 intptr_t left_cid = left()->Type()->ToCid(); | 3488 intptr_t left_cid = left()->Type()->ToCid(); |
3516 intptr_t right_cid = right()->Type()->ToCid(); | 3489 intptr_t right_cid = right()->Type()->ToCid(); |
3517 Register left = locs()->in(0).reg(); | 3490 Register left = locs()->in(0).reg(); |
3518 Register right = locs()->in(1).reg(); | 3491 Register right = locs()->in(1).reg(); |
3519 if (this->left()->definition() == this->right()->definition()) { | 3492 if (this->left()->definition() == this->right()->definition()) { |
3520 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); | 3493 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); |
3521 } else if (left_cid == kSmiCid) { | 3494 } else if (left_cid == kSmiCid) { |
3522 __ andi(CMPRES1, right, Immediate(kSmiTagMask)); | 3495 __ andi(CMPRES1, right, Immediate(kSmiTagMask)); |
3523 } else if (right_cid == kSmiCid) { | 3496 } else if (right_cid == kSmiCid) { |
3524 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); | 3497 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); |
3525 } else { | 3498 } else { |
3526 __ or_(TMP, left, right); | 3499 __ or_(TMP, left, right); |
3527 __ andi(CMPRES1, TMP, Immediate(kSmiTagMask)); | 3500 __ andi(CMPRES1, TMP, Immediate(kSmiTagMask)); |
3528 } | 3501 } |
3529 __ beq(CMPRES1, ZR, deopt); | 3502 __ beq(CMPRES1, ZR, deopt); |
3530 } | 3503 } |
3531 | 3504 |
3532 | 3505 |
3533 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, | 3506 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
3534 bool opt) const { | |
3535 const intptr_t kNumInputs = 1; | 3507 const intptr_t kNumInputs = 1; |
3536 const intptr_t kNumTemps = 1; | 3508 const intptr_t kNumTemps = 1; |
3537 LocationSummary* summary = new(zone) LocationSummary( | 3509 LocationSummary* summary = new (zone) LocationSummary( |
3538 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3510 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
3539 summary->set_in(0, Location::RequiresFpuRegister()); | 3511 summary->set_in(0, Location::RequiresFpuRegister()); |
3540 summary->set_temp(0, Location::RequiresRegister()); | 3512 summary->set_temp(0, Location::RequiresRegister()); |
3541 summary->set_out(0, Location::RequiresRegister()); | 3513 summary->set_out(0, Location::RequiresRegister()); |
3542 return summary; | 3514 return summary; |
3543 } | 3515 } |
3544 | 3516 |
3545 | 3517 |
3546 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3518 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3547 ASSERT(from_representation() == kUnboxedDouble); | 3519 ASSERT(from_representation() == kUnboxedDouble); |
3548 | 3520 |
3549 Register out_reg = locs()->out(0).reg(); | 3521 Register out_reg = locs()->out(0).reg(); |
3550 DRegister value = locs()->in(0).fpu_reg(); | 3522 DRegister value = locs()->in(0).fpu_reg(); |
3551 | 3523 |
3552 BoxAllocationSlowPath::Allocate( | 3524 BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(), |
3553 compiler, this, compiler->double_class(), out_reg, locs()->temp(0).reg()); | 3525 out_reg, locs()->temp(0).reg()); |
3554 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag); | 3526 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag); |
3555 } | 3527 } |
3556 | 3528 |
3557 | 3529 |
3558 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, | 3530 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
3559 bool opt) const { | |
3560 const intptr_t kNumInputs = 1; | 3531 const intptr_t kNumInputs = 1; |
3561 const intptr_t kNumTemps = 0; | 3532 const intptr_t kNumTemps = 0; |
3562 LocationSummary* summary = new(zone) LocationSummary( | 3533 LocationSummary* summary = new (zone) |
3563 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3534 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3564 summary->set_in(0, Location::RequiresRegister()); | 3535 summary->set_in(0, Location::RequiresRegister()); |
3565 if (representation() == kUnboxedMint) { | 3536 if (representation() == kUnboxedMint) { |
3566 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 3537 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
3567 Location::RequiresRegister())); | 3538 Location::RequiresRegister())); |
3568 } else { | 3539 } else { |
3569 summary->set_out(0, Location::RequiresFpuRegister()); | 3540 summary->set_out(0, Location::RequiresFpuRegister()); |
3570 } | 3541 } |
3571 return summary; | 3542 return summary; |
3572 } | 3543 } |
3573 | 3544 |
3574 | 3545 |
3575 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { | 3546 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |
3576 const Register box = locs()->in(0).reg(); | 3547 const Register box = locs()->in(0).reg(); |
3577 | 3548 |
3578 switch (representation()) { | 3549 switch (representation()) { |
3579 case kUnboxedMint: { | 3550 case kUnboxedMint: { |
3580 PairLocation* result = locs()->out(0).AsPairLocation(); | 3551 PairLocation* result = locs()->out(0).AsPairLocation(); |
3581 __ LoadFromOffset(result->At(0).reg(), | 3552 __ LoadFromOffset(result->At(0).reg(), box, |
3582 box, | |
3583 ValueOffset() - kHeapObjectTag); | 3553 ValueOffset() - kHeapObjectTag); |
3584 __ LoadFromOffset(result->At(1).reg(), | 3554 __ LoadFromOffset(result->At(1).reg(), box, |
3585 box, | |
3586 ValueOffset() - kHeapObjectTag + kWordSize); | 3555 ValueOffset() - kHeapObjectTag + kWordSize); |
3587 break; | 3556 break; |
3588 } | 3557 } |
3589 | 3558 |
3590 case kUnboxedDouble: { | 3559 case kUnboxedDouble: { |
3591 const DRegister result = locs()->out(0).fpu_reg(); | 3560 const DRegister result = locs()->out(0).fpu_reg(); |
3592 __ LoadDFromOffset(result, box, Double::value_offset() - kHeapObjectTag); | 3561 __ LoadDFromOffset(result, box, Double::value_offset() - kHeapObjectTag); |
3593 break; | 3562 break; |
3594 } | 3563 } |
3595 | 3564 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3636 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3605 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3637 const intptr_t value_cid = value()->Type()->ToCid(); | 3606 const intptr_t value_cid = value()->Type()->ToCid(); |
3638 const intptr_t box_cid = BoxCid(); | 3607 const intptr_t box_cid = BoxCid(); |
3639 | 3608 |
3640 if (value_cid == box_cid) { | 3609 if (value_cid == box_cid) { |
3641 EmitLoadFromBox(compiler); | 3610 EmitLoadFromBox(compiler); |
3642 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 3611 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
3643 EmitSmiConversion(compiler); | 3612 EmitSmiConversion(compiler); |
3644 } else { | 3613 } else { |
3645 const Register box = locs()->in(0).reg(); | 3614 const Register box = locs()->in(0).reg(); |
3646 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), | 3615 Label* deopt = |
3647 ICData::kDeoptCheckClass); | 3616 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass); |
3648 Label is_smi; | 3617 Label is_smi; |
3649 | 3618 |
3650 if ((value()->Type()->ToNullableCid() == box_cid) && | 3619 if ((value()->Type()->ToNullableCid() == box_cid) && |
3651 value()->Type()->is_nullable()) { | 3620 value()->Type()->is_nullable()) { |
3652 __ BranchEqual(box, Object::null_object(), deopt); | 3621 __ BranchEqual(box, Object::null_object(), deopt); |
3653 } else { | 3622 } else { |
3654 __ andi(CMPRES1, box, Immediate(kSmiTagMask)); | 3623 __ andi(CMPRES1, box, Immediate(kSmiTagMask)); |
3655 __ beq(CMPRES1, ZR, CanConvertSmi() ? &is_smi : deopt); | 3624 __ beq(CMPRES1, ZR, CanConvertSmi() ? &is_smi : deopt); |
3656 __ LoadClassId(CMPRES1, box); | 3625 __ LoadClassId(CMPRES1, box); |
3657 __ BranchNotEqual(CMPRES1, Immediate(box_cid), deopt); | 3626 __ BranchNotEqual(CMPRES1, Immediate(box_cid), deopt); |
(...skipping 11 matching lines...) Expand all Loading... |
3669 } | 3638 } |
3670 } | 3639 } |
3671 | 3640 |
3672 | 3641 |
3673 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 3642 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |
3674 bool opt) const { | 3643 bool opt) const { |
3675 ASSERT((from_representation() == kUnboxedInt32) || | 3644 ASSERT((from_representation() == kUnboxedInt32) || |
3676 (from_representation() == kUnboxedUint32)); | 3645 (from_representation() == kUnboxedUint32)); |
3677 const intptr_t kNumInputs = 1; | 3646 const intptr_t kNumInputs = 1; |
3678 const intptr_t kNumTemps = 1; | 3647 const intptr_t kNumTemps = 1; |
3679 LocationSummary* summary = new(zone) LocationSummary( | 3648 LocationSummary* summary = new (zone) LocationSummary( |
3680 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3649 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
3681 summary->set_in(0, Location::RequiresRegister()); | 3650 summary->set_in(0, Location::RequiresRegister()); |
3682 summary->set_temp(0, Location::RequiresRegister()); | 3651 summary->set_temp(0, Location::RequiresRegister()); |
3683 summary->set_out(0, Location::RequiresRegister()); | 3652 summary->set_out(0, Location::RequiresRegister()); |
3684 return summary; | 3653 return summary; |
3685 } | 3654 } |
3686 | 3655 |
3687 | 3656 |
3688 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3657 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3689 Register value = locs()->in(0).reg(); | 3658 Register value = locs()->in(0).reg(); |
3690 Register out = locs()->out(0).reg(); | 3659 Register out = locs()->out(0).reg(); |
3691 ASSERT(value != out); | 3660 ASSERT(value != out); |
3692 | 3661 |
3693 __ SmiTag(out, value); | 3662 __ SmiTag(out, value); |
3694 if (!ValueFitsSmi()) { | 3663 if (!ValueFitsSmi()) { |
3695 Register temp = locs()->temp(0).reg(); | 3664 Register temp = locs()->temp(0).reg(); |
3696 Label done; | 3665 Label done; |
3697 if (from_representation() == kUnboxedInt32) { | 3666 if (from_representation() == kUnboxedInt32) { |
3698 __ SmiUntag(CMPRES1, out); | 3667 __ SmiUntag(CMPRES1, out); |
3699 __ BranchEqual(CMPRES1, value, &done); | 3668 __ BranchEqual(CMPRES1, value, &done); |
3700 } else { | 3669 } else { |
3701 ASSERT(from_representation() == kUnboxedUint32); | 3670 ASSERT(from_representation() == kUnboxedUint32); |
3702 __ AndImmediate(CMPRES1, value, 0xC0000000); | 3671 __ AndImmediate(CMPRES1, value, 0xC0000000); |
3703 __ BranchEqual(CMPRES1, ZR, &done); | 3672 __ BranchEqual(CMPRES1, ZR, &done); |
3704 } | 3673 } |
3705 BoxAllocationSlowPath::Allocate( | 3674 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out, |
3706 compiler, | 3675 temp); |
3707 this, | |
3708 compiler->mint_class(), | |
3709 out, | |
3710 temp); | |
3711 Register hi; | 3676 Register hi; |
3712 if (from_representation() == kUnboxedInt32) { | 3677 if (from_representation() == kUnboxedInt32) { |
3713 hi = temp; | 3678 hi = temp; |
3714 __ sra(hi, value, kBitsPerWord - 1); | 3679 __ sra(hi, value, kBitsPerWord - 1); |
3715 } else { | 3680 } else { |
3716 ASSERT(from_representation() == kUnboxedUint32); | 3681 ASSERT(from_representation() == kUnboxedUint32); |
3717 hi = ZR; | 3682 hi = ZR; |
3718 } | 3683 } |
3719 __ StoreToOffset(value, | 3684 __ StoreToOffset(value, out, Mint::value_offset() - kHeapObjectTag); |
3720 out, | 3685 __ StoreToOffset(hi, out, |
3721 Mint::value_offset() - kHeapObjectTag); | |
3722 __ StoreToOffset(hi, | |
3723 out, | |
3724 Mint::value_offset() - kHeapObjectTag + kWordSize); | 3686 Mint::value_offset() - kHeapObjectTag + kWordSize); |
3725 __ Bind(&done); | 3687 __ Bind(&done); |
3726 } | 3688 } |
3727 } | 3689 } |
3728 | 3690 |
3729 | 3691 |
3730 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, | 3692 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, |
3731 bool opt) const { | 3693 bool opt) const { |
3732 const intptr_t kNumInputs = 1; | 3694 const intptr_t kNumInputs = 1; |
3733 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 3695 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
3734 LocationSummary* summary = new(zone) LocationSummary( | 3696 LocationSummary* summary = new (zone) |
3735 zone, | 3697 LocationSummary(zone, kNumInputs, kNumTemps, |
3736 kNumInputs, | 3698 ValueFitsSmi() ? LocationSummary::kNoCall |
3737 kNumTemps, | 3699 : LocationSummary::kCallOnSlowPath); |
3738 ValueFitsSmi() ? LocationSummary::kNoCall | |
3739 : LocationSummary::kCallOnSlowPath); | |
3740 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 3700 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
3741 Location::RequiresRegister())); | 3701 Location::RequiresRegister())); |
3742 if (!ValueFitsSmi()) { | 3702 if (!ValueFitsSmi()) { |
3743 summary->set_temp(0, Location::RequiresRegister()); | 3703 summary->set_temp(0, Location::RequiresRegister()); |
3744 } | 3704 } |
3745 summary->set_out(0, Location::RequiresRegister()); | 3705 summary->set_out(0, Location::RequiresRegister()); |
3746 return summary; | 3706 return summary; |
3747 } | 3707 } |
3748 | 3708 |
3749 | 3709 |
(...skipping 13 matching lines...) Expand all Loading... |
3763 Register out_reg = locs()->out(0).reg(); | 3723 Register out_reg = locs()->out(0).reg(); |
3764 | 3724 |
3765 Label not_smi, done; | 3725 Label not_smi, done; |
3766 __ SmiTag(out_reg, value_lo); | 3726 __ SmiTag(out_reg, value_lo); |
3767 __ SmiUntag(tmp, out_reg); | 3727 __ SmiUntag(tmp, out_reg); |
3768 __ bne(tmp, value_lo, ¬_smi); | 3728 __ bne(tmp, value_lo, ¬_smi); |
3769 __ delay_slot()->sra(tmp, out_reg, 31); | 3729 __ delay_slot()->sra(tmp, out_reg, 31); |
3770 __ beq(tmp, value_hi, &done); | 3730 __ beq(tmp, value_hi, &done); |
3771 | 3731 |
3772 __ Bind(¬_smi); | 3732 __ Bind(¬_smi); |
3773 BoxAllocationSlowPath::Allocate( | 3733 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), |
3774 compiler, | 3734 out_reg, tmp); |
3775 this, | |
3776 compiler->mint_class(), | |
3777 out_reg, | |
3778 tmp); | |
3779 __ StoreToOffset(value_lo, out_reg, Mint::value_offset() - kHeapObjectTag); | 3735 __ StoreToOffset(value_lo, out_reg, Mint::value_offset() - kHeapObjectTag); |
3780 __ StoreToOffset(value_hi, | 3736 __ StoreToOffset(value_hi, out_reg, |
3781 out_reg, | |
3782 Mint::value_offset() - kHeapObjectTag + kWordSize); | 3737 Mint::value_offset() - kHeapObjectTag + kWordSize); |
3783 __ Bind(&done); | 3738 __ Bind(&done); |
3784 } | 3739 } |
3785 | 3740 |
3786 | 3741 |
3787 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 3742 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |
3788 bool opt) const { | 3743 bool opt) const { |
3789 ASSERT((representation() == kUnboxedInt32) || | 3744 ASSERT((representation() == kUnboxedInt32) || |
3790 (representation() == kUnboxedUint32)); | 3745 (representation() == kUnboxedUint32)); |
3791 const intptr_t kNumInputs = 1; | 3746 const intptr_t kNumInputs = 1; |
3792 const intptr_t kNumTemps = 0; | 3747 const intptr_t kNumTemps = 0; |
3793 LocationSummary* summary = new(zone) LocationSummary( | 3748 LocationSummary* summary = new (zone) |
3794 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3749 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3795 summary->set_in(0, Location::RequiresRegister()); | 3750 summary->set_in(0, Location::RequiresRegister()); |
3796 summary->set_out(0, Location::RequiresRegister()); | 3751 summary->set_out(0, Location::RequiresRegister()); |
3797 return summary; | 3752 return summary; |
3798 } | 3753 } |
3799 | 3754 |
3800 | 3755 |
3801 static void LoadInt32FromMint(FlowGraphCompiler* compiler, | 3756 static void LoadInt32FromMint(FlowGraphCompiler* compiler, |
3802 Register mint, | 3757 Register mint, |
3803 Register result, | 3758 Register result, |
3804 Label* deopt) { | 3759 Label* deopt) { |
3805 __ LoadFieldFromOffset(result, mint, Mint::value_offset()); | 3760 __ LoadFieldFromOffset(result, mint, Mint::value_offset()); |
3806 if (deopt != NULL) { | 3761 if (deopt != NULL) { |
3807 __ LoadFieldFromOffset(CMPRES1, | 3762 __ LoadFieldFromOffset(CMPRES1, mint, Mint::value_offset() + kWordSize); |
3808 mint, | |
3809 Mint::value_offset() + kWordSize); | |
3810 __ sra(CMPRES2, result, kBitsPerWord - 1); | 3763 __ sra(CMPRES2, result, kBitsPerWord - 1); |
3811 __ BranchNotEqual(CMPRES1, CMPRES2, deopt); | 3764 __ BranchNotEqual(CMPRES1, CMPRES2, deopt); |
3812 } | 3765 } |
3813 } | 3766 } |
3814 | 3767 |
3815 | 3768 |
3816 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3769 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3817 const intptr_t value_cid = value()->Type()->ToCid(); | 3770 const intptr_t value_cid = value()->Type()->ToCid(); |
3818 const Register value = locs()->in(0).reg(); | 3771 const Register value = locs()->in(0).reg(); |
3819 const Register out = locs()->out(0).reg(); | 3772 const Register out = locs()->out(0).reg(); |
3820 Label* deopt = CanDeoptimize() ? | 3773 Label* deopt = |
3821 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL; | 3774 CanDeoptimize() |
| 3775 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) |
| 3776 : NULL; |
3822 Label* out_of_range = !is_truncating() ? deopt : NULL; | 3777 Label* out_of_range = !is_truncating() ? deopt : NULL; |
3823 ASSERT(value != out); | 3778 ASSERT(value != out); |
3824 | 3779 |
3825 if (value_cid == kSmiCid) { | 3780 if (value_cid == kSmiCid) { |
3826 __ SmiUntag(out, value); | 3781 __ SmiUntag(out, value); |
3827 } else if (value_cid == kMintCid) { | 3782 } else if (value_cid == kMintCid) { |
3828 LoadInt32FromMint(compiler, value, out, out_of_range); | 3783 LoadInt32FromMint(compiler, value, out, out_of_range); |
3829 } else if (!CanDeoptimize()) { | 3784 } else if (!CanDeoptimize()) { |
3830 Label done; | 3785 Label done; |
3831 __ SmiUntag(out, value); | 3786 __ SmiUntag(out, value); |
(...skipping 11 matching lines...) Expand all Loading... |
3843 LoadInt32FromMint(compiler, value, out, out_of_range); | 3798 LoadInt32FromMint(compiler, value, out, out_of_range); |
3844 __ Bind(&done); | 3799 __ Bind(&done); |
3845 } | 3800 } |
3846 } | 3801 } |
3847 | 3802 |
3848 | 3803 |
3849 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 3804 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
3850 bool opt) const { | 3805 bool opt) const { |
3851 const intptr_t kNumInputs = 2; | 3806 const intptr_t kNumInputs = 2; |
3852 const intptr_t kNumTemps = 0; | 3807 const intptr_t kNumTemps = 0; |
3853 LocationSummary* summary = new(zone) LocationSummary( | 3808 LocationSummary* summary = new (zone) |
3854 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3809 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3855 summary->set_in(0, Location::RequiresFpuRegister()); | 3810 summary->set_in(0, Location::RequiresFpuRegister()); |
3856 summary->set_in(1, Location::RequiresFpuRegister()); | 3811 summary->set_in(1, Location::RequiresFpuRegister()); |
3857 summary->set_out(0, Location::RequiresFpuRegister()); | 3812 summary->set_out(0, Location::RequiresFpuRegister()); |
3858 return summary; | 3813 return summary; |
3859 } | 3814 } |
3860 | 3815 |
3861 | 3816 |
3862 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3817 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3863 DRegister left = locs()->in(0).fpu_reg(); | 3818 DRegister left = locs()->in(0).fpu_reg(); |
3864 DRegister right = locs()->in(1).fpu_reg(); | 3819 DRegister right = locs()->in(1).fpu_reg(); |
3865 DRegister result = locs()->out(0).fpu_reg(); | 3820 DRegister result = locs()->out(0).fpu_reg(); |
3866 switch (op_kind()) { | 3821 switch (op_kind()) { |
3867 case Token::kADD: __ addd(result, left, right); break; | 3822 case Token::kADD: |
3868 case Token::kSUB: __ subd(result, left, right); break; | 3823 __ addd(result, left, right); |
3869 case Token::kMUL: __ muld(result, left, right); break; | 3824 break; |
3870 case Token::kDIV: __ divd(result, left, right); break; | 3825 case Token::kSUB: |
3871 default: UNREACHABLE(); | 3826 __ subd(result, left, right); |
| 3827 break; |
| 3828 case Token::kMUL: |
| 3829 __ muld(result, left, right); |
| 3830 break; |
| 3831 case Token::kDIV: |
| 3832 __ divd(result, left, right); |
| 3833 break; |
| 3834 default: |
| 3835 UNREACHABLE(); |
3872 } | 3836 } |
3873 } | 3837 } |
3874 | 3838 |
3875 | 3839 |
3876 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 3840 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |
3877 bool opt) const { | 3841 bool opt) const { |
3878 const intptr_t kNumInputs = 1; | 3842 const intptr_t kNumInputs = 1; |
3879 const intptr_t kNumTemps = 0; | 3843 const intptr_t kNumTemps = 0; |
3880 LocationSummary* summary = new(zone) LocationSummary( | 3844 LocationSummary* summary = new (zone) |
3881 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3845 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3882 summary->set_in(0, Location::RequiresFpuRegister()); | 3846 summary->set_in(0, Location::RequiresFpuRegister()); |
3883 summary->set_out(0, Location::RequiresRegister()); | 3847 summary->set_out(0, Location::RequiresRegister()); |
3884 return summary; | 3848 return summary; |
3885 } | 3849 } |
3886 | 3850 |
3887 | 3851 |
3888 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 3852 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
3889 BranchLabels labels) { | 3853 BranchLabels labels) { |
3890 const DRegister value = locs()->in(0).fpu_reg(); | 3854 const DRegister value = locs()->in(0).fpu_reg(); |
3891 const bool is_negated = kind() != Token::kEQ; | 3855 const bool is_negated = kind() != Token::kEQ; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3933 Condition true_condition = EmitComparisonCode(compiler, labels); | 3897 Condition true_condition = EmitComparisonCode(compiler, labels); |
3934 // Branches for isNaN are emitted in EmitComparisonCode already. | 3898 // Branches for isNaN are emitted in EmitComparisonCode already. |
3935 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 3899 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
3936 EmitBranchOnCondition(compiler, true_condition, labels); | 3900 EmitBranchOnCondition(compiler, true_condition, labels); |
3937 } | 3901 } |
3938 } | 3902 } |
3939 | 3903 |
3940 | 3904 |
3941 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3905 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3942 Label is_true, is_false; | 3906 Label is_true, is_false; |
3943 BranchLabels labels = { &is_true, &is_false, &is_false }; | 3907 BranchLabels labels = {&is_true, &is_false, &is_false}; |
3944 Condition true_condition = EmitComparisonCode(compiler, labels); | 3908 Condition true_condition = EmitComparisonCode(compiler, labels); |
3945 // Branches for isNaN are emitted in EmitComparisonCode already. | 3909 // Branches for isNaN are emitted in EmitComparisonCode already. |
3946 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 3910 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
3947 EmitBranchOnCondition(compiler, true_condition, labels); | 3911 EmitBranchOnCondition(compiler, true_condition, labels); |
3948 } | 3912 } |
3949 const Register result = locs()->out(0).reg(); | 3913 const Register result = locs()->out(0).reg(); |
3950 Label done; | 3914 Label done; |
3951 __ Comment("return bool"); | 3915 __ Comment("return bool"); |
3952 __ Bind(&is_false); | 3916 __ Bind(&is_false); |
3953 __ LoadObject(result, Bool::False()); | 3917 __ LoadObject(result, Bool::False()); |
3954 __ b(&done); | 3918 __ b(&done); |
3955 __ Bind(&is_true); | 3919 __ Bind(&is_true); |
3956 __ LoadObject(result, Bool::True()); | 3920 __ LoadObject(result, Bool::True()); |
3957 __ Bind(&done); | 3921 __ Bind(&done); |
(...skipping 29 matching lines...) Expand all Loading... |
3987 UNIMPLEMENTED(); | 3951 UNIMPLEMENTED(); |
3988 return NULL; | 3952 return NULL; |
3989 } | 3953 } |
3990 | 3954 |
3991 | 3955 |
3992 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3956 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3993 UNIMPLEMENTED(); | 3957 UNIMPLEMENTED(); |
3994 } | 3958 } |
3995 | 3959 |
3996 | 3960 |
3997 | |
3998 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 3961 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |
3999 bool opt) const { | 3962 bool opt) const { |
4000 UNIMPLEMENTED(); | 3963 UNIMPLEMENTED(); |
4001 return NULL; | 3964 return NULL; |
4002 } | 3965 } |
4003 | 3966 |
4004 | 3967 |
4005 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3968 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4006 UNIMPLEMENTED(); | 3969 UNIMPLEMENTED(); |
4007 } | 3970 } |
4008 | 3971 |
4009 | 3972 |
4010 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 3973 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
4011 Zone* zone, bool opt) const { | 3974 Zone* zone, |
| 3975 bool opt) const { |
4012 UNIMPLEMENTED(); | 3976 UNIMPLEMENTED(); |
4013 return NULL; | 3977 return NULL; |
4014 } | 3978 } |
4015 | 3979 |
4016 | 3980 |
4017 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3981 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4018 UNIMPLEMENTED(); | 3982 UNIMPLEMENTED(); |
4019 } | 3983 } |
4020 | 3984 |
4021 | 3985 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4140 | 4104 |
4141 | 4105 |
4142 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 4106 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |
4143 bool opt) const { | 4107 bool opt) const { |
4144 UNIMPLEMENTED(); | 4108 UNIMPLEMENTED(); |
4145 return NULL; | 4109 return NULL; |
4146 } | 4110 } |
4147 | 4111 |
4148 | 4112 |
4149 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4113 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4150 UNIMPLEMENTED(); | 4114 UNIMPLEMENTED(); |
4151 } | 4115 } |
4152 | 4116 |
4153 | 4117 |
4154 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 4118 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |
4155 bool opt) const { | 4119 bool opt) const { |
4156 UNIMPLEMENTED(); | 4120 UNIMPLEMENTED(); |
4157 return NULL; | 4121 return NULL; |
4158 } | 4122 } |
4159 | 4123 |
4160 | 4124 |
4161 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4125 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4162 UNIMPLEMENTED(); | 4126 UNIMPLEMENTED(); |
4163 } | 4127 } |
4164 | 4128 |
4165 | 4129 |
4166 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 4130 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |
4167 bool opt) const { | 4131 bool opt) const { |
4168 UNIMPLEMENTED(); | 4132 UNIMPLEMENTED(); |
4169 return NULL; | 4133 return NULL; |
4170 } | 4134 } |
4171 | 4135 |
4172 | 4136 |
4173 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4137 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4174 UNIMPLEMENTED(); | 4138 UNIMPLEMENTED(); |
4175 } | 4139 } |
4176 | 4140 |
4177 | 4141 |
4178 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 4142 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
4179 Zone* zone, bool opt) const { | 4143 Zone* zone, |
| 4144 bool opt) const { |
4180 UNIMPLEMENTED(); | 4145 UNIMPLEMENTED(); |
4181 return NULL; | 4146 return NULL; |
4182 } | 4147 } |
4183 | 4148 |
4184 | 4149 |
4185 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4150 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4186 UNIMPLEMENTED(); | 4151 UNIMPLEMENTED(); |
4187 } | 4152 } |
4188 | 4153 |
4189 | 4154 |
4190 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 4155 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
4191 Zone* zone, bool opt) const { | 4156 Zone* zone, |
| 4157 bool opt) const { |
4192 UNIMPLEMENTED(); | 4158 UNIMPLEMENTED(); |
4193 return NULL; | 4159 return NULL; |
4194 } | 4160 } |
4195 | 4161 |
4196 | 4162 |
4197 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4163 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4198 UNIMPLEMENTED(); | 4164 UNIMPLEMENTED(); |
4199 } | 4165 } |
4200 | 4166 |
4201 | 4167 |
4202 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 4168 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
4203 Zone* zone, bool opt) const { | 4169 Zone* zone, |
| 4170 bool opt) const { |
4204 UNIMPLEMENTED(); | 4171 UNIMPLEMENTED(); |
4205 return NULL; | 4172 return NULL; |
4206 } | 4173 } |
4207 | 4174 |
4208 | 4175 |
4209 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4176 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4210 UNIMPLEMENTED(); | 4177 UNIMPLEMENTED(); |
4211 } | 4178 } |
4212 | 4179 |
4213 | 4180 |
(...skipping 14 matching lines...) Expand all Loading... |
4228 UNIMPLEMENTED(); | 4195 UNIMPLEMENTED(); |
4229 return NULL; | 4196 return NULL; |
4230 } | 4197 } |
4231 | 4198 |
4232 | 4199 |
4233 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4200 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4234 UNIMPLEMENTED(); | 4201 UNIMPLEMENTED(); |
4235 } | 4202 } |
4236 | 4203 |
4237 | 4204 |
4238 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary( | 4205 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, |
4239 Zone* zone, bool opt) const { | 4206 bool opt) const { |
4240 UNIMPLEMENTED(); | 4207 UNIMPLEMENTED(); |
4241 return NULL; | 4208 return NULL; |
4242 } | 4209 } |
4243 | 4210 |
4244 | 4211 |
4245 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4212 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4246 UNIMPLEMENTED(); | 4213 UNIMPLEMENTED(); |
4247 } | 4214 } |
4248 | 4215 |
4249 | 4216 |
4250 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 4217 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
4251 Zone* zone, bool opt) const { | 4218 Zone* zone, |
| 4219 bool opt) const { |
4252 UNIMPLEMENTED(); | 4220 UNIMPLEMENTED(); |
4253 return NULL; | 4221 return NULL; |
4254 } | 4222 } |
4255 | 4223 |
4256 | 4224 |
4257 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4225 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4258 UNIMPLEMENTED(); | 4226 UNIMPLEMENTED(); |
4259 } | 4227 } |
4260 | 4228 |
4261 | 4229 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4330 UNIMPLEMENTED(); | 4298 UNIMPLEMENTED(); |
4331 } | 4299 } |
4332 | 4300 |
4333 | 4301 |
4334 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 4302 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |
4335 bool opt) const { | 4303 bool opt) const { |
4336 ASSERT((kind() == MathUnaryInstr::kSqrt) || | 4304 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
4337 (kind() == MathUnaryInstr::kDoubleSquare)); | 4305 (kind() == MathUnaryInstr::kDoubleSquare)); |
4338 const intptr_t kNumInputs = 1; | 4306 const intptr_t kNumInputs = 1; |
4339 const intptr_t kNumTemps = 0; | 4307 const intptr_t kNumTemps = 0; |
4340 LocationSummary* summary = new(zone) LocationSummary( | 4308 LocationSummary* summary = new (zone) |
4341 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4309 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4342 summary->set_in(0, Location::RequiresFpuRegister()); | 4310 summary->set_in(0, Location::RequiresFpuRegister()); |
4343 summary->set_out(0, Location::RequiresFpuRegister()); | 4311 summary->set_out(0, Location::RequiresFpuRegister()); |
4344 return summary; | 4312 return summary; |
4345 } | 4313 } |
4346 | 4314 |
4347 | 4315 |
4348 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4316 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4349 if (kind() == MathUnaryInstr::kSqrt) { | 4317 if (kind() == MathUnaryInstr::kSqrt) { |
4350 __ sqrtd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 4318 __ sqrtd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
4351 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 4319 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
4352 DRegister val = locs()->in(0).fpu_reg(); | 4320 DRegister val = locs()->in(0).fpu_reg(); |
4353 DRegister result = locs()->out(0).fpu_reg(); | 4321 DRegister result = locs()->out(0).fpu_reg(); |
4354 __ muld(result, val, val); | 4322 __ muld(result, val, val); |
4355 } else { | 4323 } else { |
4356 UNREACHABLE(); | 4324 UNREACHABLE(); |
4357 } | 4325 } |
4358 } | 4326 } |
4359 | 4327 |
4360 | 4328 |
4361 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 4329 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |
4362 Zone* zone, bool opt) const { | 4330 Zone* zone, |
| 4331 bool opt) const { |
4363 const intptr_t kNumTemps = 0; | 4332 const intptr_t kNumTemps = 0; |
4364 LocationSummary* summary = new(zone) LocationSummary( | 4333 LocationSummary* summary = new (zone) |
4365 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 4334 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
4366 summary->set_in(0, Location::RegisterLocation(A0)); | 4335 summary->set_in(0, Location::RegisterLocation(A0)); |
4367 summary->set_in(1, Location::RegisterLocation(A1)); | 4336 summary->set_in(1, Location::RegisterLocation(A1)); |
4368 summary->set_in(2, Location::RegisterLocation(A2)); | 4337 summary->set_in(2, Location::RegisterLocation(A2)); |
4369 summary->set_in(3, Location::RegisterLocation(A3)); | 4338 summary->set_in(3, Location::RegisterLocation(A3)); |
4370 summary->set_out(0, Location::RegisterLocation(V0)); | 4339 summary->set_out(0, Location::RegisterLocation(V0)); |
4371 return summary; | 4340 return summary; |
4372 } | 4341 } |
4373 | 4342 |
4374 | 4343 |
4375 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 4344 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |
4376 FlowGraphCompiler* compiler) { | 4345 FlowGraphCompiler* compiler) { |
4377 | |
4378 // Call the function. | 4346 // Call the function. |
4379 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 4347 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |
4380 } | 4348 } |
4381 | 4349 |
4382 | 4350 |
4383 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 4351 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |
4384 bool opt) const { | 4352 bool opt) const { |
4385 if (result_cid() == kDoubleCid) { | 4353 if (result_cid() == kDoubleCid) { |
4386 const intptr_t kNumInputs = 2; | 4354 const intptr_t kNumInputs = 2; |
4387 const intptr_t kNumTemps = 1; | 4355 const intptr_t kNumTemps = 1; |
4388 LocationSummary* summary = new(zone) LocationSummary( | 4356 LocationSummary* summary = new (zone) |
4389 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4357 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4390 summary->set_in(0, Location::RequiresFpuRegister()); | 4358 summary->set_in(0, Location::RequiresFpuRegister()); |
4391 summary->set_in(1, Location::RequiresFpuRegister()); | 4359 summary->set_in(1, Location::RequiresFpuRegister()); |
4392 // Reuse the left register so that code can be made shorter. | 4360 // Reuse the left register so that code can be made shorter. |
4393 summary->set_out(0, Location::SameAsFirstInput()); | 4361 summary->set_out(0, Location::SameAsFirstInput()); |
4394 summary->set_temp(0, Location::RequiresRegister()); | 4362 summary->set_temp(0, Location::RequiresRegister()); |
4395 return summary; | 4363 return summary; |
4396 } | 4364 } |
4397 ASSERT(result_cid() == kSmiCid); | 4365 ASSERT(result_cid() == kSmiCid); |
4398 const intptr_t kNumInputs = 2; | 4366 const intptr_t kNumInputs = 2; |
4399 const intptr_t kNumTemps = 0; | 4367 const intptr_t kNumTemps = 0; |
4400 LocationSummary* summary = new(zone) LocationSummary( | 4368 LocationSummary* summary = new (zone) |
4401 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4369 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4402 summary->set_in(0, Location::RequiresRegister()); | 4370 summary->set_in(0, Location::RequiresRegister()); |
4403 summary->set_in(1, Location::RequiresRegister()); | 4371 summary->set_in(1, Location::RequiresRegister()); |
4404 // Reuse the left register so that code can be made shorter. | 4372 // Reuse the left register so that code can be made shorter. |
4405 summary->set_out(0, Location::SameAsFirstInput()); | 4373 summary->set_out(0, Location::SameAsFirstInput()); |
4406 return summary; | 4374 return summary; |
4407 } | 4375 } |
4408 | 4376 |
4409 | 4377 |
4410 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4378 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4411 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 4379 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4469 } | 4437 } |
4470 __ mov(result, right); | 4438 __ mov(result, right); |
4471 __ Bind(&done); | 4439 __ Bind(&done); |
4472 } | 4440 } |
4473 | 4441 |
4474 | 4442 |
4475 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 4443 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |
4476 bool opt) const { | 4444 bool opt) const { |
4477 const intptr_t kNumInputs = 1; | 4445 const intptr_t kNumInputs = 1; |
4478 const intptr_t kNumTemps = 0; | 4446 const intptr_t kNumTemps = 0; |
4479 LocationSummary* summary = new(zone) LocationSummary( | 4447 LocationSummary* summary = new (zone) |
4480 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4448 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4481 summary->set_in(0, Location::RequiresRegister()); | 4449 summary->set_in(0, Location::RequiresRegister()); |
4482 // We make use of 3-operand instructions by not requiring result register | 4450 // We make use of 3-operand instructions by not requiring result register |
4483 // to be identical to first input register as on Intel. | 4451 // to be identical to first input register as on Intel. |
4484 summary->set_out(0, Location::RequiresRegister()); | 4452 summary->set_out(0, Location::RequiresRegister()); |
4485 return summary; | 4453 return summary; |
4486 } | 4454 } |
4487 | 4455 |
4488 | 4456 |
4489 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4457 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4490 Register value = locs()->in(0).reg(); | 4458 Register value = locs()->in(0).reg(); |
(...skipping 12 matching lines...) Expand all Loading... |
4503 default: | 4471 default: |
4504 UNREACHABLE(); | 4472 UNREACHABLE(); |
4505 } | 4473 } |
4506 } | 4474 } |
4507 | 4475 |
4508 | 4476 |
4509 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 4477 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
4510 bool opt) const { | 4478 bool opt) const { |
4511 const intptr_t kNumInputs = 1; | 4479 const intptr_t kNumInputs = 1; |
4512 const intptr_t kNumTemps = 0; | 4480 const intptr_t kNumTemps = 0; |
4513 LocationSummary* summary = new(zone) LocationSummary( | 4481 LocationSummary* summary = new (zone) |
4514 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4482 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4515 summary->set_in(0, Location::RequiresFpuRegister()); | 4483 summary->set_in(0, Location::RequiresFpuRegister()); |
4516 summary->set_out(0, Location::RequiresFpuRegister()); | 4484 summary->set_out(0, Location::RequiresFpuRegister()); |
4517 return summary; | 4485 return summary; |
4518 } | 4486 } |
4519 | 4487 |
4520 | 4488 |
4521 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4489 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4522 FpuRegister result = locs()->out(0).fpu_reg(); | 4490 FpuRegister result = locs()->out(0).fpu_reg(); |
4523 FpuRegister value = locs()->in(0).fpu_reg(); | 4491 FpuRegister value = locs()->in(0).fpu_reg(); |
4524 __ negd(result, value); | 4492 __ negd(result, value); |
4525 } | 4493 } |
4526 | 4494 |
4527 | 4495 |
4528 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 4496 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |
4529 bool opt) const { | 4497 bool opt) const { |
4530 const intptr_t kNumInputs = 1; | 4498 const intptr_t kNumInputs = 1; |
4531 const intptr_t kNumTemps = 0; | 4499 const intptr_t kNumTemps = 0; |
4532 LocationSummary* result = new(zone) LocationSummary( | 4500 LocationSummary* result = new (zone) |
4533 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4501 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4534 result->set_in(0, Location::RequiresRegister()); | 4502 result->set_in(0, Location::RequiresRegister()); |
4535 result->set_out(0, Location::RequiresFpuRegister()); | 4503 result->set_out(0, Location::RequiresFpuRegister()); |
4536 return result; | 4504 return result; |
4537 } | 4505 } |
4538 | 4506 |
4539 | 4507 |
4540 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4508 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4541 Register value = locs()->in(0).reg(); | 4509 Register value = locs()->in(0).reg(); |
4542 FpuRegister result = locs()->out(0).fpu_reg(); | 4510 FpuRegister result = locs()->out(0).fpu_reg(); |
4543 __ mtc1(value, STMP1); | 4511 __ mtc1(value, STMP1); |
4544 __ cvtdw(result, STMP1); | 4512 __ cvtdw(result, STMP1); |
4545 } | 4513 } |
4546 | 4514 |
4547 | 4515 |
4548 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 4516 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |
4549 bool opt) const { | 4517 bool opt) const { |
4550 const intptr_t kNumInputs = 1; | 4518 const intptr_t kNumInputs = 1; |
4551 const intptr_t kNumTemps = 0; | 4519 const intptr_t kNumTemps = 0; |
4552 LocationSummary* result = new(zone) LocationSummary( | 4520 LocationSummary* result = new (zone) |
4553 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4521 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4554 result->set_in(0, Location::RequiresRegister()); | 4522 result->set_in(0, Location::RequiresRegister()); |
4555 result->set_out(0, Location::RequiresFpuRegister()); | 4523 result->set_out(0, Location::RequiresFpuRegister()); |
4556 return result; | 4524 return result; |
4557 } | 4525 } |
4558 | 4526 |
4559 | 4527 |
4560 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4528 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4561 Register value = locs()->in(0).reg(); | 4529 Register value = locs()->in(0).reg(); |
4562 FpuRegister result = locs()->out(0).fpu_reg(); | 4530 FpuRegister result = locs()->out(0).fpu_reg(); |
4563 __ SmiUntag(TMP, value); | 4531 __ SmiUntag(TMP, value); |
(...skipping 11 matching lines...) Expand all Loading... |
4575 | 4543 |
4576 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4544 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4577 UNIMPLEMENTED(); | 4545 UNIMPLEMENTED(); |
4578 } | 4546 } |
4579 | 4547 |
4580 | 4548 |
4581 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 4549 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |
4582 bool opt) const { | 4550 bool opt) const { |
4583 const intptr_t kNumInputs = 1; | 4551 const intptr_t kNumInputs = 1; |
4584 const intptr_t kNumTemps = 0; | 4552 const intptr_t kNumTemps = 0; |
4585 LocationSummary* result = new(zone) LocationSummary( | 4553 LocationSummary* result = new (zone) |
4586 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 4554 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
4587 result->set_in(0, Location::RegisterLocation(T1)); | 4555 result->set_in(0, Location::RegisterLocation(T1)); |
4588 result->set_out(0, Location::RegisterLocation(V0)); | 4556 result->set_out(0, Location::RegisterLocation(V0)); |
4589 return result; | 4557 return result; |
4590 } | 4558 } |
4591 | 4559 |
4592 | 4560 |
4593 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4561 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4594 Register result = locs()->out(0).reg(); | 4562 Register result = locs()->out(0).reg(); |
4595 Register value_obj = locs()->in(0).reg(); | 4563 Register value_obj = locs()->in(0).reg(); |
4596 ASSERT(result == V0); | 4564 ASSERT(result == V0); |
(...skipping 11 matching lines...) Expand all Loading... |
4608 __ SmiTag(result); | 4576 __ SmiTag(result); |
4609 __ b(&done); | 4577 __ b(&done); |
4610 __ Bind(&do_call); | 4578 __ Bind(&do_call); |
4611 __ Push(value_obj); | 4579 __ Push(value_obj); |
4612 ASSERT(instance_call()->HasICData()); | 4580 ASSERT(instance_call()->HasICData()); |
4613 const ICData& ic_data = *instance_call()->ic_data(); | 4581 const ICData& ic_data = *instance_call()->ic_data(); |
4614 ASSERT((ic_data.NumberOfChecks() == 1)); | 4582 ASSERT((ic_data.NumberOfChecks() == 1)); |
4615 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 4583 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
4616 | 4584 |
4617 const intptr_t kNumberOfArguments = 1; | 4585 const intptr_t kNumberOfArguments = 1; |
4618 compiler->GenerateStaticCall(deopt_id(), | 4586 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, |
4619 instance_call()->token_pos(), | |
4620 target, | |
4621 kNumberOfArguments, | 4587 kNumberOfArguments, |
4622 Object::null_array(), // No argument names. | 4588 Object::null_array(), // No argument names. |
4623 locs(), | 4589 locs(), ICData::Handle()); |
4624 ICData::Handle()); | |
4625 __ Bind(&done); | 4590 __ Bind(&done); |
4626 } | 4591 } |
4627 | 4592 |
4628 | 4593 |
4629 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 4594 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |
4630 bool opt) const { | 4595 bool opt) const { |
4631 const intptr_t kNumInputs = 1; | 4596 const intptr_t kNumInputs = 1; |
4632 const intptr_t kNumTemps = 0; | 4597 const intptr_t kNumTemps = 0; |
4633 LocationSummary* result = new(zone) LocationSummary( | 4598 LocationSummary* result = new (zone) |
4634 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4599 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4635 result->set_in(0, Location::RequiresFpuRegister()); | 4600 result->set_in(0, Location::RequiresFpuRegister()); |
4636 result->set_out(0, Location::RequiresRegister()); | 4601 result->set_out(0, Location::RequiresRegister()); |
4637 return result; | 4602 return result; |
4638 } | 4603 } |
4639 | 4604 |
4640 | 4605 |
4641 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4606 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4642 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 4607 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
4643 Register result = locs()->out(0).reg(); | 4608 Register result = locs()->out(0).reg(); |
4644 DRegister value = locs()->in(0).fpu_reg(); | 4609 DRegister value = locs()->in(0).fpu_reg(); |
(...skipping 17 matching lines...) Expand all Loading... |
4662 | 4627 |
4663 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4628 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4664 UNIMPLEMENTED(); | 4629 UNIMPLEMENTED(); |
4665 } | 4630 } |
4666 | 4631 |
4667 | 4632 |
4668 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 4633 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |
4669 bool opt) const { | 4634 bool opt) const { |
4670 const intptr_t kNumInputs = 1; | 4635 const intptr_t kNumInputs = 1; |
4671 const intptr_t kNumTemps = 0; | 4636 const intptr_t kNumTemps = 0; |
4672 LocationSummary* result = new(zone) LocationSummary( | 4637 LocationSummary* result = new (zone) |
4673 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4638 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4674 result->set_in(0, Location::RequiresFpuRegister()); | 4639 result->set_in(0, Location::RequiresFpuRegister()); |
4675 result->set_out(0, Location::SameAsFirstInput()); | 4640 result->set_out(0, Location::SameAsFirstInput()); |
4676 return result; | 4641 return result; |
4677 } | 4642 } |
4678 | 4643 |
4679 | 4644 |
4680 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4645 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4681 DRegister value = locs()->in(0).fpu_reg(); | 4646 DRegister value = locs()->in(0).fpu_reg(); |
4682 FRegister result = EvenFRegisterOf(locs()->out(0).fpu_reg()); | 4647 FRegister result = EvenFRegisterOf(locs()->out(0).fpu_reg()); |
4683 __ cvtsd(result, value); | 4648 __ cvtsd(result, value); |
4684 } | 4649 } |
4685 | 4650 |
4686 | 4651 |
4687 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 4652 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |
4688 bool opt) const { | 4653 bool opt) const { |
4689 const intptr_t kNumInputs = 1; | 4654 const intptr_t kNumInputs = 1; |
4690 const intptr_t kNumTemps = 0; | 4655 const intptr_t kNumTemps = 0; |
4691 LocationSummary* result = new(zone) LocationSummary( | 4656 LocationSummary* result = new (zone) |
4692 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4657 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4693 result->set_in(0, Location::RequiresFpuRegister()); | 4658 result->set_in(0, Location::RequiresFpuRegister()); |
4694 result->set_out(0, Location::SameAsFirstInput()); | 4659 result->set_out(0, Location::SameAsFirstInput()); |
4695 return result; | 4660 return result; |
4696 } | 4661 } |
4697 | 4662 |
4698 | 4663 |
4699 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4664 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4700 FRegister value = EvenFRegisterOf(locs()->in(0).fpu_reg()); | 4665 FRegister value = EvenFRegisterOf(locs()->in(0).fpu_reg()); |
4701 DRegister result = locs()->out(0).fpu_reg(); | 4666 DRegister result = locs()->out(0).fpu_reg(); |
4702 __ cvtds(result, value); | 4667 __ cvtds(result, value); |
4703 } | 4668 } |
4704 | 4669 |
4705 | 4670 |
4706 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 4671 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |
4707 bool opt) const { | 4672 bool opt) const { |
4708 // Calling convention on MIPS uses D6 and D7 to pass the first two | 4673 // Calling convention on MIPS uses D6 and D7 to pass the first two |
4709 // double arguments. | 4674 // double arguments. |
4710 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 4675 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
4711 const intptr_t kNumTemps = 0; | 4676 const intptr_t kNumTemps = 0; |
4712 LocationSummary* result = new(zone) LocationSummary( | 4677 LocationSummary* result = new (zone) |
4713 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 4678 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
4714 result->set_in(0, Location::FpuRegisterLocation(D6)); | 4679 result->set_in(0, Location::FpuRegisterLocation(D6)); |
4715 if (InputCount() == 2) { | 4680 if (InputCount() == 2) { |
4716 result->set_in(1, Location::FpuRegisterLocation(D7)); | 4681 result->set_in(1, Location::FpuRegisterLocation(D7)); |
4717 } | 4682 } |
4718 result->set_out(0, Location::FpuRegisterLocation(D0)); | 4683 result->set_out(0, Location::FpuRegisterLocation(D0)); |
4719 return result; | 4684 return result; |
4720 } | 4685 } |
4721 | 4686 |
4722 | 4687 |
4723 // Pseudo code: | 4688 // Pseudo code: |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4842 // double values are passed and returned in vfp registers. | 4807 // double values are passed and returned in vfp registers. |
4843 __ CallRuntime(TargetFunction(), InputCount()); | 4808 __ CallRuntime(TargetFunction(), InputCount()); |
4844 } | 4809 } |
4845 | 4810 |
4846 | 4811 |
4847 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 4812 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |
4848 bool opt) const { | 4813 bool opt) const { |
4849 // Only use this instruction in optimized code. | 4814 // Only use this instruction in optimized code. |
4850 ASSERT(opt); | 4815 ASSERT(opt); |
4851 const intptr_t kNumInputs = 1; | 4816 const intptr_t kNumInputs = 1; |
4852 LocationSummary* summary = new(zone) LocationSummary( | 4817 LocationSummary* summary = |
4853 zone, kNumInputs, 0, LocationSummary::kNoCall); | 4818 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
4854 if (representation() == kUnboxedDouble) { | 4819 if (representation() == kUnboxedDouble) { |
4855 if (index() == 0) { | 4820 if (index() == 0) { |
4856 summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), | 4821 summary->set_in( |
4857 Location::Any())); | 4822 0, Location::Pair(Location::RequiresFpuRegister(), Location::Any())); |
4858 } else { | 4823 } else { |
4859 ASSERT(index() == 1); | 4824 ASSERT(index() == 1); |
4860 summary->set_in(0, Location::Pair(Location::Any(), | 4825 summary->set_in( |
4861 Location::RequiresFpuRegister())); | 4826 0, Location::Pair(Location::Any(), Location::RequiresFpuRegister())); |
4862 } | 4827 } |
4863 summary->set_out(0, Location::RequiresFpuRegister()); | 4828 summary->set_out(0, Location::RequiresFpuRegister()); |
4864 } else { | 4829 } else { |
4865 ASSERT(representation() == kTagged); | 4830 ASSERT(representation() == kTagged); |
4866 if (index() == 0) { | 4831 if (index() == 0) { |
4867 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 4832 summary->set_in( |
4868 Location::Any())); | 4833 0, Location::Pair(Location::RequiresRegister(), Location::Any())); |
4869 } else { | 4834 } else { |
4870 ASSERT(index() == 1); | 4835 ASSERT(index() == 1); |
4871 summary->set_in(0, Location::Pair(Location::Any(), | 4836 summary->set_in( |
4872 Location::RequiresRegister())); | 4837 0, Location::Pair(Location::Any(), Location::RequiresRegister())); |
4873 } | 4838 } |
4874 summary->set_out(0, Location::RequiresRegister()); | 4839 summary->set_out(0, Location::RequiresRegister()); |
4875 } | 4840 } |
4876 return summary; | 4841 return summary; |
4877 } | 4842 } |
4878 | 4843 |
4879 | 4844 |
4880 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4845 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4881 ASSERT(locs()->in(0).IsPairLocation()); | 4846 ASSERT(locs()->in(0).IsPairLocation()); |
4882 PairLocation* pair = locs()->in(0).AsPairLocation(); | 4847 PairLocation* pair = locs()->in(0).AsPairLocation(); |
4883 Location in_loc = pair->At(index()); | 4848 Location in_loc = pair->At(index()); |
4884 if (representation() == kUnboxedDouble) { | 4849 if (representation() == kUnboxedDouble) { |
4885 DRegister out = locs()->out(0).fpu_reg(); | 4850 DRegister out = locs()->out(0).fpu_reg(); |
4886 DRegister in = in_loc.fpu_reg(); | 4851 DRegister in = in_loc.fpu_reg(); |
4887 __ movd(out, in); | 4852 __ movd(out, in); |
4888 } else { | 4853 } else { |
4889 ASSERT(representation() == kTagged); | 4854 ASSERT(representation() == kTagged); |
4890 Register out = locs()->out(0).reg(); | 4855 Register out = locs()->out(0).reg(); |
4891 Register in = in_loc.reg(); | 4856 Register in = in_loc.reg(); |
4892 __ mov(out, in); | 4857 __ mov(out, in); |
4893 } | 4858 } |
4894 } | 4859 } |
4895 | 4860 |
4896 | 4861 |
4897 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, | 4862 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, |
4898 bool opt) const { | 4863 bool opt) const { |
4899 if (kind() == MergedMathInstr::kTruncDivMod) { | 4864 if (kind() == MergedMathInstr::kTruncDivMod) { |
4900 const intptr_t kNumInputs = 2; | 4865 const intptr_t kNumInputs = 2; |
4901 const intptr_t kNumTemps = 1; | 4866 const intptr_t kNumTemps = 1; |
4902 LocationSummary* summary = new(zone) LocationSummary( | 4867 LocationSummary* summary = new (zone) |
4903 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4868 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4904 summary->set_in(0, Location::RequiresRegister()); | 4869 summary->set_in(0, Location::RequiresRegister()); |
4905 summary->set_in(1, Location::RequiresRegister()); | 4870 summary->set_in(1, Location::RequiresRegister()); |
4906 summary->set_temp(0, Location::RequiresRegister()); | 4871 summary->set_temp(0, Location::RequiresRegister()); |
4907 // Output is a pair of registers. | 4872 // Output is a pair of registers. |
4908 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 4873 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
4909 Location::RequiresRegister())); | 4874 Location::RequiresRegister())); |
4910 return summary; | 4875 return summary; |
4911 } | 4876 } |
4912 UNIMPLEMENTED(); | 4877 UNIMPLEMENTED(); |
4913 return NULL; | 4878 return NULL; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4968 | 4933 |
4969 __ SmiTag(result_div); | 4934 __ SmiTag(result_div); |
4970 __ SmiTag(result_mod); | 4935 __ SmiTag(result_mod); |
4971 return; | 4936 return; |
4972 } | 4937 } |
4973 UNIMPLEMENTED(); | 4938 UNIMPLEMENTED(); |
4974 } | 4939 } |
4975 | 4940 |
4976 | 4941 |
4977 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 4942 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
4978 Zone* zone, bool opt) const { | 4943 Zone* zone, |
| 4944 bool opt) const { |
4979 return MakeCallSummary(zone); | 4945 return MakeCallSummary(zone); |
4980 } | 4946 } |
4981 | 4947 |
4982 | 4948 |
4983 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, | 4949 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
4984 bool opt) const { | |
4985 comparison()->InitializeLocationSummary(zone, opt); | 4950 comparison()->InitializeLocationSummary(zone, opt); |
4986 // Branches don't produce a result. | 4951 // Branches don't produce a result. |
4987 comparison()->locs()->set_out(0, Location::NoLocation()); | 4952 comparison()->locs()->set_out(0, Location::NoLocation()); |
4988 return comparison()->locs(); | 4953 return comparison()->locs(); |
4989 } | 4954 } |
4990 | 4955 |
4991 | 4956 |
4992 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4957 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4993 __ Comment("BranchInstr"); | 4958 __ Comment("BranchInstr"); |
4994 comparison()->EmitBranchCode(compiler, this); | 4959 comparison()->EmitBranchCode(compiler, this); |
4995 } | 4960 } |
4996 | 4961 |
4997 | 4962 |
4998 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 4963 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
4999 bool opt) const { | 4964 bool opt) const { |
5000 const intptr_t kNumInputs = 1; | 4965 const intptr_t kNumInputs = 1; |
5001 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); | 4966 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); |
5002 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 4967 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
5003 LocationSummary* summary = new(zone) LocationSummary( | 4968 LocationSummary* summary = new (zone) |
5004 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4969 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5005 summary->set_in(0, Location::RequiresRegister()); | 4970 summary->set_in(0, Location::RequiresRegister()); |
5006 if (!IsNullCheck()) { | 4971 if (!IsNullCheck()) { |
5007 summary->set_temp(0, Location::RequiresRegister()); | 4972 summary->set_temp(0, Location::RequiresRegister()); |
5008 if (need_mask_temp) { | 4973 if (need_mask_temp) { |
5009 summary->set_temp(1, Location::RequiresRegister()); | 4974 summary->set_temp(1, Location::RequiresRegister()); |
5010 } | 4975 } |
5011 } | 4976 } |
5012 return summary; | 4977 return summary; |
5013 } | 4978 } |
5014 | 4979 |
5015 | 4980 |
5016 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4981 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5017 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 4982 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass, |
5018 ICData::kDeoptCheckClass, | |
5019 licm_hoisted_ ? ICData::kHoisted : 0); | 4983 licm_hoisted_ ? ICData::kHoisted : 0); |
5020 if (IsNullCheck()) { | 4984 if (IsNullCheck()) { |
5021 if (DeoptIfNull()) { | 4985 if (DeoptIfNull()) { |
5022 __ BranchEqual(locs()->in(0).reg(), Object::null_object(), deopt); | 4986 __ BranchEqual(locs()->in(0).reg(), Object::null_object(), deopt); |
5023 } else { | 4987 } else { |
5024 ASSERT(DeoptIfNotNull()); | 4988 ASSERT(DeoptIfNotNull()); |
5025 __ BranchNotEqual(locs()->in(0).reg(), Object::null_object(), deopt); | 4989 __ BranchNotEqual(locs()->in(0).reg(), Object::null_object(), deopt); |
5026 } | 4990 } |
5027 return; | 4991 return; |
5028 } | 4992 } |
(...skipping 24 matching lines...) Expand all Loading... |
5053 // Only need mask if there are missing numbers in the range. | 5017 // Only need mask if there are missing numbers in the range. |
5054 ASSERT(cids_.length() > 2); | 5018 ASSERT(cids_.length() > 2); |
5055 Register mask_reg = locs()->temp(1).reg(); | 5019 Register mask_reg = locs()->temp(1).reg(); |
5056 __ LoadImmediate(mask_reg, 1); | 5020 __ LoadImmediate(mask_reg, 1); |
5057 __ sllv(mask_reg, mask_reg, temp); | 5021 __ sllv(mask_reg, mask_reg, temp); |
5058 __ AndImmediate(mask_reg, mask_reg, mask); | 5022 __ AndImmediate(mask_reg, mask_reg, mask); |
5059 __ beq(mask_reg, ZR, deopt); | 5023 __ beq(mask_reg, ZR, deopt); |
5060 } | 5024 } |
5061 } else { | 5025 } else { |
5062 GrowableArray<CidTarget> sorted_ic_data; | 5026 GrowableArray<CidTarget> sorted_ic_data; |
5063 FlowGraphCompiler::SortICDataByCount(unary_checks(), | 5027 FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data, |
5064 &sorted_ic_data, | |
5065 /* drop_smi = */ true); | 5028 /* drop_smi = */ true); |
5066 const intptr_t num_checks = sorted_ic_data.length(); | 5029 const intptr_t num_checks = sorted_ic_data.length(); |
5067 for (intptr_t i = 0; i < num_checks; i++) { | 5030 for (intptr_t i = 0; i < num_checks; i++) { |
5068 const intptr_t cid = sorted_ic_data[i].cid; | 5031 const intptr_t cid = sorted_ic_data[i].cid; |
5069 ASSERT(cid != kSmiCid); | 5032 ASSERT(cid != kSmiCid); |
5070 __ LoadImmediate(TMP, cid); | 5033 __ LoadImmediate(TMP, cid); |
5071 __ subu(CMPRES1, temp, TMP); | 5034 __ subu(CMPRES1, temp, TMP); |
5072 if (i == (num_checks - 1)) { | 5035 if (i == (num_checks - 1)) { |
5073 __ bne(CMPRES1, ZR, deopt); | 5036 __ bne(CMPRES1, ZR, deopt); |
5074 } else { | 5037 } else { |
5075 __ beq(CMPRES1, ZR, &is_ok); | 5038 __ beq(CMPRES1, ZR, &is_ok); |
5076 } | 5039 } |
5077 } | 5040 } |
5078 } | 5041 } |
5079 __ Bind(&is_ok); | 5042 __ Bind(&is_ok); |
5080 } | 5043 } |
5081 | 5044 |
5082 | 5045 |
5083 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 5046 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
5084 bool opt) const { | 5047 bool opt) const { |
5085 const intptr_t kNumInputs = 1; | 5048 const intptr_t kNumInputs = 1; |
5086 const intptr_t kNumTemps = 0; | 5049 const intptr_t kNumTemps = 0; |
5087 LocationSummary* summary = new(zone) LocationSummary( | 5050 LocationSummary* summary = new (zone) |
5088 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5051 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5089 summary->set_in(0, Location::RequiresRegister()); | 5052 summary->set_in(0, Location::RequiresRegister()); |
5090 return summary; | 5053 return summary; |
5091 } | 5054 } |
5092 | 5055 |
5093 | 5056 |
5094 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5057 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5095 __ Comment("CheckSmiInstr"); | 5058 __ Comment("CheckSmiInstr"); |
5096 Register value = locs()->in(0).reg(); | 5059 Register value = locs()->in(0).reg(); |
5097 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5060 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, |
5098 ICData::kDeoptCheckSmi, | |
5099 licm_hoisted_ ? ICData::kHoisted : 0); | 5061 licm_hoisted_ ? ICData::kHoisted : 0); |
5100 __ BranchIfNotSmi(value, deopt); | 5062 __ BranchIfNotSmi(value, deopt); |
5101 } | 5063 } |
5102 | 5064 |
5103 | 5065 |
5104 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 5066 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
5105 bool opt) const { | 5067 bool opt) const { |
5106 const intptr_t kNumInputs = 1; | 5068 const intptr_t kNumInputs = 1; |
5107 const intptr_t kNumTemps = 0; | 5069 const intptr_t kNumTemps = 0; |
5108 LocationSummary* summary = new(zone) LocationSummary( | 5070 LocationSummary* summary = new (zone) |
5109 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5071 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5110 summary->set_in(0, Location::RequiresRegister()); | 5072 summary->set_in(0, Location::RequiresRegister()); |
5111 return summary; | 5073 return summary; |
5112 } | 5074 } |
5113 | 5075 |
5114 | 5076 |
5115 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5077 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5116 Register value = locs()->in(0).reg(); | 5078 Register value = locs()->in(0).reg(); |
5117 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 5079 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
5118 __ BranchNotEqual(value, Immediate(Smi::RawValue(cid_)), deopt); | 5080 __ BranchNotEqual(value, Immediate(Smi::RawValue(cid_)), deopt); |
5119 } | 5081 } |
5120 | 5082 |
5121 | 5083 |
5122 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, | 5084 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, |
5123 bool opt) const { | 5085 bool opt) const { |
5124 const intptr_t kNumInputs = 2; | 5086 const intptr_t kNumInputs = 2; |
5125 const intptr_t kNumTemps = 0; | 5087 const intptr_t kNumTemps = 0; |
5126 LocationSummary* locs = new(zone) LocationSummary( | 5088 LocationSummary* locs = new (zone) LocationSummary( |
5127 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 5089 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
5128 locs->set_in(kLengthPos, Location::RequiresRegister()); | 5090 locs->set_in(kLengthPos, Location::RequiresRegister()); |
5129 locs->set_in(kIndexPos, Location::RequiresRegister()); | 5091 locs->set_in(kIndexPos, Location::RequiresRegister()); |
5130 return locs; | 5092 return locs; |
5131 } | 5093 } |
5132 | 5094 |
5133 | 5095 |
5134 class RangeErrorSlowPath : public SlowPathCode { | 5096 class RangeErrorSlowPath : public SlowPathCode { |
5135 public: | 5097 public: |
5136 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) | 5098 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) |
5137 : instruction_(instruction), try_index_(try_index) { } | 5099 : instruction_(instruction), try_index_(try_index) {} |
5138 | 5100 |
5139 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 5101 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
5140 if (Assembler::EmittingComments()) { | 5102 if (Assembler::EmittingComments()) { |
5141 __ Comment("slow path check bound operation"); | 5103 __ Comment("slow path check bound operation"); |
5142 } | 5104 } |
5143 __ Bind(entry_label()); | 5105 __ Bind(entry_label()); |
5144 LocationSummary* locs = instruction_->locs(); | 5106 LocationSummary* locs = instruction_->locs(); |
5145 __ Push(locs->in(0).reg()); | 5107 __ Push(locs->in(0).reg()); |
5146 __ Push(locs->in(1).reg()); | 5108 __ Push(locs->in(1).reg()); |
5147 __ CallRuntime(kRangeErrorRuntimeEntry, 2); | 5109 __ CallRuntime(kRangeErrorRuntimeEntry, 2); |
5148 compiler->pc_descriptors_list()->AddDescriptor( | 5110 compiler->pc_descriptors_list()->AddDescriptor( |
5149 RawPcDescriptors::kOther, | 5111 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), |
5150 compiler->assembler()->CodeSize(), | 5112 instruction_->deopt_id(), instruction_->token_pos(), try_index_); |
5151 instruction_->deopt_id(), | |
5152 instruction_->token_pos(), | |
5153 try_index_); | |
5154 __ break_(0); | 5113 __ break_(0); |
5155 } | 5114 } |
5156 | 5115 |
5157 private: | 5116 private: |
5158 GenericCheckBoundInstr* instruction_; | 5117 GenericCheckBoundInstr* instruction_; |
5159 intptr_t try_index_; | 5118 intptr_t try_index_; |
5160 }; | 5119 }; |
5161 | 5120 |
5162 | 5121 |
5163 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5122 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(...skipping 10 matching lines...) Expand all Loading... |
5174 __ BranchIfNotSmi(index, slow_path->entry_label()); | 5133 __ BranchIfNotSmi(index, slow_path->entry_label()); |
5175 } | 5134 } |
5176 __ BranchUnsignedGreaterEqual(index, length, slow_path->entry_label()); | 5135 __ BranchUnsignedGreaterEqual(index, length, slow_path->entry_label()); |
5177 } | 5136 } |
5178 | 5137 |
5179 | 5138 |
5180 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 5139 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
5181 bool opt) const { | 5140 bool opt) const { |
5182 const intptr_t kNumInputs = 2; | 5141 const intptr_t kNumInputs = 2; |
5183 const intptr_t kNumTemps = 0; | 5142 const intptr_t kNumTemps = 0; |
5184 LocationSummary* locs = new(zone) LocationSummary( | 5143 LocationSummary* locs = new (zone) |
5185 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5144 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5186 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 5145 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
5187 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 5146 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
5188 return locs; | 5147 return locs; |
5189 } | 5148 } |
5190 | 5149 |
5191 | 5150 |
5192 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5151 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5193 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 5152 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |
5194 flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 5153 flags |= licm_hoisted_ ? ICData::kHoisted : 0; |
5195 Label* deopt = compiler->AddDeoptStub( | 5154 Label* deopt = |
5196 deopt_id(), | 5155 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); |
5197 ICData::kDeoptCheckArrayBound, | |
5198 flags); | |
5199 | 5156 |
5200 Location length_loc = locs()->in(kLengthPos); | 5157 Location length_loc = locs()->in(kLengthPos); |
5201 Location index_loc = locs()->in(kIndexPos); | 5158 Location index_loc = locs()->in(kIndexPos); |
5202 | 5159 |
5203 if (length_loc.IsConstant() && index_loc.IsConstant()) { | 5160 if (length_loc.IsConstant() && index_loc.IsConstant()) { |
5204 ASSERT((Smi::Cast(length_loc.constant()).Value() <= | 5161 ASSERT((Smi::Cast(length_loc.constant()).Value() <= |
5205 Smi::Cast(index_loc.constant()).Value()) || | 5162 Smi::Cast(index_loc.constant()).Value()) || |
5206 (Smi::Cast(index_loc.constant()).Value() < 0)); | 5163 (Smi::Cast(index_loc.constant()).Value() < 0)); |
5207 // Unconditionally deoptimize for constant bounds checks because they | 5164 // Unconditionally deoptimize for constant bounds checks because they |
5208 // only occur only when index is out-of-bounds. | 5165 // only occur only when index is out-of-bounds. |
(...skipping 26 matching lines...) Expand all Loading... |
5235 __ BranchIfNotSmi(index, deopt); | 5192 __ BranchIfNotSmi(index, deopt); |
5236 } | 5193 } |
5237 __ BranchUnsignedGreaterEqual(index, length, deopt); | 5194 __ BranchUnsignedGreaterEqual(index, length, deopt); |
5238 } | 5195 } |
5239 } | 5196 } |
5240 | 5197 |
5241 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5198 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, |
5242 bool opt) const { | 5199 bool opt) const { |
5243 const intptr_t kNumInputs = 2; | 5200 const intptr_t kNumInputs = 2; |
5244 const intptr_t kNumTemps = 0; | 5201 const intptr_t kNumTemps = 0; |
5245 LocationSummary* summary = new(zone) LocationSummary( | 5202 LocationSummary* summary = new (zone) |
5246 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5203 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5247 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5204 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5248 Location::RequiresRegister())); | 5205 Location::RequiresRegister())); |
5249 summary->set_in(1, Location::Pair(Location::RequiresRegister(), | 5206 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
5250 Location::RequiresRegister())); | 5207 Location::RequiresRegister())); |
5251 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 5208 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
5252 Location::RequiresRegister())); | 5209 Location::RequiresRegister())); |
5253 return summary; | 5210 return summary; |
5254 } | 5211 } |
5255 | 5212 |
5256 | 5213 |
(...skipping 17 matching lines...) Expand all Loading... |
5274 __ and_(out_lo, left_lo, right_lo); | 5231 __ and_(out_lo, left_lo, right_lo); |
5275 __ and_(out_hi, left_hi, right_hi); | 5232 __ and_(out_hi, left_hi, right_hi); |
5276 break; | 5233 break; |
5277 } | 5234 } |
5278 case Token::kBIT_OR: { | 5235 case Token::kBIT_OR: { |
5279 __ or_(out_lo, left_lo, right_lo); | 5236 __ or_(out_lo, left_lo, right_lo); |
5280 __ or_(out_hi, left_hi, right_hi); | 5237 __ or_(out_hi, left_hi, right_hi); |
5281 break; | 5238 break; |
5282 } | 5239 } |
5283 case Token::kBIT_XOR: { | 5240 case Token::kBIT_XOR: { |
5284 __ xor_(out_lo, left_lo, right_lo); | 5241 __ xor_(out_lo, left_lo, right_lo); |
5285 __ xor_(out_hi, left_hi, right_hi); | 5242 __ xor_(out_hi, left_hi, right_hi); |
5286 break; | 5243 break; |
5287 } | 5244 } |
5288 case Token::kADD: | 5245 case Token::kADD: |
5289 case Token::kSUB: { | 5246 case Token::kSUB: { |
5290 if (op_kind() == Token::kADD) { | 5247 if (op_kind() == Token::kADD) { |
5291 __ addu(out_lo, left_lo, right_lo); | 5248 __ addu(out_lo, left_lo, right_lo); |
5292 __ sltu(TMP, out_lo, left_lo); // TMP = carry of left_lo + right_lo. | 5249 __ sltu(TMP, out_lo, left_lo); // TMP = carry of left_lo + right_lo. |
5293 __ addu(out_hi, left_hi, right_hi); | 5250 __ addu(out_hi, left_hi, right_hi); |
5294 __ addu(out_hi, out_hi, TMP); | 5251 __ addu(out_hi, out_hi, TMP); |
5295 if (can_overflow()) { | 5252 if (can_overflow()) { |
5296 __ xor_(CMPRES1, out_hi, left_hi); | 5253 __ xor_(CMPRES1, out_hi, left_hi); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5329 default: | 5286 default: |
5330 UNREACHABLE(); | 5287 UNREACHABLE(); |
5331 } | 5288 } |
5332 } | 5289 } |
5333 | 5290 |
5334 | 5291 |
5335 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, | 5292 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, |
5336 bool opt) const { | 5293 bool opt) const { |
5337 const intptr_t kNumInputs = 2; | 5294 const intptr_t kNumInputs = 2; |
5338 const intptr_t kNumTemps = 0; | 5295 const intptr_t kNumTemps = 0; |
5339 LocationSummary* summary = new(zone) LocationSummary( | 5296 LocationSummary* summary = new (zone) |
5340 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5297 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5341 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5298 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5342 Location::RequiresRegister())); | 5299 Location::RequiresRegister())); |
5343 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); | 5300 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); |
5344 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 5301 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
5345 Location::RequiresRegister())); | 5302 Location::RequiresRegister())); |
5346 return summary; | 5303 return summary; |
5347 } | 5304 } |
5348 | 5305 |
5349 | 5306 |
5350 static const intptr_t kMintShiftCountLimit = 63; | 5307 static const intptr_t kMintShiftCountLimit = 63; |
5351 | 5308 |
5352 bool ShiftMintOpInstr::has_shift_count_check() const { | 5309 bool ShiftMintOpInstr::has_shift_count_check() const { |
5353 return !RangeUtils::IsWithin( | 5310 return !RangeUtils::IsWithin(right()->definition()->range(), 0, |
5354 right()->definition()->range(), 0, kMintShiftCountLimit); | 5311 kMintShiftCountLimit); |
5355 } | 5312 } |
5356 | 5313 |
5357 | 5314 |
5358 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5315 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5359 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 5316 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
5360 Register left_lo = left_pair->At(0).reg(); | 5317 Register left_lo = left_pair->At(0).reg(); |
5361 Register left_hi = left_pair->At(1).reg(); | 5318 Register left_hi = left_pair->At(1).reg(); |
5362 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 5319 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
5363 Register out_lo = out_pair->At(0).reg(); | 5320 Register out_lo = out_pair->At(0).reg(); |
5364 Register out_hi = out_pair->At(1).reg(); | 5321 Register out_hi = out_pair->At(1).reg(); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5431 // Code below assumes shift amount is not 0 (cannot shift by 32 - 0). | 5388 // Code below assumes shift amount is not 0 (cannot shift by 32 - 0). |
5432 Label non_zero_shift, done; | 5389 Label non_zero_shift, done; |
5433 __ bne(shift, ZR, &non_zero_shift); | 5390 __ bne(shift, ZR, &non_zero_shift); |
5434 __ delay_slot()->mov(out_lo, left_lo); | 5391 __ delay_slot()->mov(out_lo, left_lo); |
5435 __ b(&done); | 5392 __ b(&done); |
5436 __ delay_slot()->mov(out_hi, left_hi); | 5393 __ delay_slot()->mov(out_hi, left_hi); |
5437 __ Bind(&non_zero_shift); | 5394 __ Bind(&non_zero_shift); |
5438 | 5395 |
5439 // Deopt if shift is larger than 63 or less than 0. | 5396 // Deopt if shift is larger than 63 or less than 0. |
5440 if (has_shift_count_check()) { | 5397 if (has_shift_count_check()) { |
5441 __ sltiu(CMPRES1, shift, Immediate(2*(kMintShiftCountLimit + 1))); | 5398 __ sltiu(CMPRES1, shift, Immediate(2 * (kMintShiftCountLimit + 1))); |
5442 __ beq(CMPRES1, ZR, deopt); | 5399 __ beq(CMPRES1, ZR, deopt); |
5443 // Untag shift count. | 5400 // Untag shift count. |
5444 __ delay_slot()->SmiUntag(shift); | 5401 __ delay_slot()->SmiUntag(shift); |
5445 } else { | 5402 } else { |
5446 // Untag shift count. | 5403 // Untag shift count. |
5447 __ SmiUntag(shift); | 5404 __ SmiUntag(shift); |
5448 } | 5405 } |
5449 | 5406 |
5450 switch (op_kind()) { | 5407 switch (op_kind()) { |
5451 case Token::kSHR: { | 5408 case Token::kSHR: { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5515 } | 5472 } |
5516 __ Bind(&done); | 5473 __ Bind(&done); |
5517 } | 5474 } |
5518 } | 5475 } |
5519 | 5476 |
5520 | 5477 |
5521 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5478 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, |
5522 bool opt) const { | 5479 bool opt) const { |
5523 const intptr_t kNumInputs = 1; | 5480 const intptr_t kNumInputs = 1; |
5524 const intptr_t kNumTemps = 0; | 5481 const intptr_t kNumTemps = 0; |
5525 LocationSummary* summary = new(zone) LocationSummary( | 5482 LocationSummary* summary = new (zone) |
5526 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5483 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5527 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5484 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5528 Location::RequiresRegister())); | 5485 Location::RequiresRegister())); |
5529 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 5486 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
5530 Location::RequiresRegister())); | 5487 Location::RequiresRegister())); |
5531 return summary; | 5488 return summary; |
5532 } | 5489 } |
5533 | 5490 |
5534 | 5491 |
5535 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5492 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5536 ASSERT(op_kind() == Token::kBIT_NOT); | 5493 ASSERT(op_kind() == Token::kBIT_NOT); |
(...skipping 22 matching lines...) Expand all Loading... |
5559 | 5516 |
5560 CompileType UnaryUint32OpInstr::ComputeType() const { | 5517 CompileType UnaryUint32OpInstr::ComputeType() const { |
5561 return CompileType::Int(); | 5518 return CompileType::Int(); |
5562 } | 5519 } |
5563 | 5520 |
5564 | 5521 |
5565 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 5522 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
5566 bool opt) const { | 5523 bool opt) const { |
5567 const intptr_t kNumInputs = 2; | 5524 const intptr_t kNumInputs = 2; |
5568 const intptr_t kNumTemps = 0; | 5525 const intptr_t kNumTemps = 0; |
5569 LocationSummary* summary = new(zone) LocationSummary( | 5526 LocationSummary* summary = new (zone) |
5570 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5527 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5571 summary->set_in(0, Location::RequiresRegister()); | 5528 summary->set_in(0, Location::RequiresRegister()); |
5572 summary->set_in(1, Location::RequiresRegister()); | 5529 summary->set_in(1, Location::RequiresRegister()); |
5573 summary->set_out(0, Location::RequiresRegister()); | 5530 summary->set_out(0, Location::RequiresRegister()); |
5574 return summary; | 5531 return summary; |
5575 } | 5532 } |
5576 | 5533 |
5577 | 5534 |
5578 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5535 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5579 Register left = locs()->in(0).reg(); | 5536 Register left = locs()->in(0).reg(); |
5580 Register right = locs()->in(1).reg(); | 5537 Register right = locs()->in(1).reg(); |
(...skipping 22 matching lines...) Expand all Loading... |
5603 default: | 5560 default: |
5604 UNREACHABLE(); | 5561 UNREACHABLE(); |
5605 } | 5562 } |
5606 } | 5563 } |
5607 | 5564 |
5608 | 5565 |
5609 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, | 5566 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, |
5610 bool opt) const { | 5567 bool opt) const { |
5611 const intptr_t kNumInputs = 2; | 5568 const intptr_t kNumInputs = 2; |
5612 const intptr_t kNumTemps = 1; | 5569 const intptr_t kNumTemps = 1; |
5613 LocationSummary* summary = new(zone) LocationSummary( | 5570 LocationSummary* summary = new (zone) |
5614 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5571 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5615 summary->set_in(0, Location::RequiresRegister()); | 5572 summary->set_in(0, Location::RequiresRegister()); |
5616 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 5573 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
5617 summary->set_temp(0, Location::RequiresRegister()); | 5574 summary->set_temp(0, Location::RequiresRegister()); |
5618 summary->set_out(0, Location::RequiresRegister()); | 5575 summary->set_out(0, Location::RequiresRegister()); |
5619 return summary; | 5576 return summary; |
5620 } | 5577 } |
5621 | 5578 |
5622 | 5579 |
5623 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5580 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5624 const intptr_t kShifterLimit = 31; | 5581 const intptr_t kShifterLimit = 31; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5672 default: | 5629 default: |
5673 UNREACHABLE(); | 5630 UNREACHABLE(); |
5674 } | 5631 } |
5675 } | 5632 } |
5676 | 5633 |
5677 | 5634 |
5678 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 5635 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
5679 bool opt) const { | 5636 bool opt) const { |
5680 const intptr_t kNumInputs = 1; | 5637 const intptr_t kNumInputs = 1; |
5681 const intptr_t kNumTemps = 0; | 5638 const intptr_t kNumTemps = 0; |
5682 LocationSummary* summary = new(zone) LocationSummary( | 5639 LocationSummary* summary = new (zone) |
5683 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5640 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5684 summary->set_in(0, Location::RequiresRegister()); | 5641 summary->set_in(0, Location::RequiresRegister()); |
5685 summary->set_out(0, Location::RequiresRegister()); | 5642 summary->set_out(0, Location::RequiresRegister()); |
5686 return summary; | 5643 return summary; |
5687 } | 5644 } |
5688 | 5645 |
5689 | 5646 |
5690 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5647 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5691 Register left = locs()->in(0).reg(); | 5648 Register left = locs()->in(0).reg(); |
5692 Register out = locs()->out(0).reg(); | 5649 Register out = locs()->out(0).reg(); |
5693 ASSERT(left != out); | 5650 ASSERT(left != out); |
5694 | 5651 |
5695 ASSERT(op_kind() == Token::kBIT_NOT); | 5652 ASSERT(op_kind() == Token::kBIT_NOT); |
5696 | 5653 |
5697 __ nor(out, ZR, left); | 5654 __ nor(out, ZR, left); |
5698 } | 5655 } |
5699 | 5656 |
5700 | 5657 |
5701 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 5658 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
5702 | 5659 |
5703 | 5660 |
5704 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 5661 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |
5705 bool opt) const { | 5662 bool opt) const { |
5706 const intptr_t kNumInputs = 1; | 5663 const intptr_t kNumInputs = 1; |
5707 const intptr_t kNumTemps = 0; | 5664 const intptr_t kNumTemps = 0; |
5708 LocationSummary* summary = new(zone) LocationSummary( | 5665 LocationSummary* summary = new (zone) |
5709 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5710 if (from() == kUnboxedMint) { | 5667 if (from() == kUnboxedMint) { |
5711 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 5668 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
5712 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5669 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5713 Location::RequiresRegister())); | 5670 Location::RequiresRegister())); |
5714 summary->set_out(0, Location::RequiresRegister()); | 5671 summary->set_out(0, Location::RequiresRegister()); |
5715 } else if (to() == kUnboxedMint) { | 5672 } else if (to() == kUnboxedMint) { |
5716 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 5673 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
5717 summary->set_in(0, Location::RequiresRegister()); | 5674 summary->set_in(0, Location::RequiresRegister()); |
5718 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 5675 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
5719 Location::RequiresRegister())); | 5676 Location::RequiresRegister())); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5769 } else { | 5726 } else { |
5770 ASSERT(from() == kUnboxedInt32); | 5727 ASSERT(from() == kUnboxedInt32); |
5771 __ sra(out_hi, in, 31); | 5728 __ sra(out_hi, in, 31); |
5772 } | 5729 } |
5773 } else { | 5730 } else { |
5774 UNREACHABLE(); | 5731 UNREACHABLE(); |
5775 } | 5732 } |
5776 } | 5733 } |
5777 | 5734 |
5778 | 5735 |
5779 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, | 5736 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
5780 bool opt) const { | 5737 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
5781 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
5782 } | 5738 } |
5783 | 5739 |
5784 | 5740 |
5785 | |
5786 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5741 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5787 compiler->GenerateRuntimeCall(token_pos(), | 5742 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, |
5788 deopt_id(), | |
5789 kThrowRuntimeEntry, | |
5790 1, | |
5791 locs()); | 5743 locs()); |
5792 __ break_(0); | 5744 __ break_(0); |
5793 } | 5745 } |
5794 | 5746 |
5795 | 5747 |
5796 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, | 5748 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
5797 bool opt) const { | 5749 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
5798 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
5799 } | 5750 } |
5800 | 5751 |
5801 | 5752 |
5802 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5753 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5803 compiler->SetNeedsStacktrace(catch_try_index()); | 5754 compiler->SetNeedsStacktrace(catch_try_index()); |
5804 compiler->GenerateRuntimeCall(token_pos(), | 5755 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, |
5805 deopt_id(), | 5756 2, locs()); |
5806 kReThrowRuntimeEntry, | |
5807 2, | |
5808 locs()); | |
5809 __ break_(0); | 5757 __ break_(0); |
5810 } | 5758 } |
5811 | 5759 |
5812 | 5760 |
5813 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, | 5761 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
5814 bool opt) const { | 5762 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
5815 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
5816 } | 5763 } |
5817 | 5764 |
5818 | 5765 |
5819 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5766 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5820 __ Stop(message()); | 5767 __ Stop(message()); |
5821 } | 5768 } |
5822 | 5769 |
5823 | 5770 |
5824 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5771 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5825 if (!compiler->CanFallThroughTo(normal_entry())) { | 5772 if (!compiler->CanFallThroughTo(normal_entry())) { |
5826 __ b(compiler->GetJumpLabel(normal_entry())); | 5773 __ b(compiler->GetJumpLabel(normal_entry())); |
5827 } | 5774 } |
5828 } | 5775 } |
5829 | 5776 |
5830 | 5777 |
5831 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, | 5778 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
5832 bool opt) const { | 5779 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
5833 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
5834 } | 5780 } |
5835 | 5781 |
5836 | 5782 |
5837 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5783 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5838 __ Comment("GotoInstr"); | 5784 __ Comment("GotoInstr"); |
5839 if (!compiler->is_optimizing()) { | 5785 if (!compiler->is_optimizing()) { |
5840 if (FLAG_reorder_basic_blocks) { | 5786 if (FLAG_reorder_basic_blocks) { |
5841 compiler->EmitEdgeCounter(block()->preorder_number()); | 5787 compiler->EmitEdgeCounter(block()->preorder_number()); |
5842 } | 5788 } |
5843 // Add a deoptimization descriptor for deoptimizing instructions that | 5789 // Add a deoptimization descriptor for deoptimizing instructions that |
5844 // may be inserted before this instruction. | 5790 // may be inserted before this instruction. |
5845 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 5791 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), |
5846 GetDeoptId(), | |
5847 TokenPosition::kNoSource); | 5792 TokenPosition::kNoSource); |
5848 } | 5793 } |
5849 if (HasParallelMove()) { | 5794 if (HasParallelMove()) { |
5850 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 5795 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
5851 } | 5796 } |
5852 | 5797 |
5853 // We can fall through if the successor is the next block in the list. | 5798 // We can fall through if the successor is the next block in the list. |
5854 // Otherwise, we need a jump. | 5799 // Otherwise, we need a jump. |
5855 if (!compiler->CanFallThroughTo(successor())) { | 5800 if (!compiler->CanFallThroughTo(successor())) { |
5856 __ b(compiler->GetJumpLabel(successor())); | 5801 __ b(compiler->GetJumpLabel(successor())); |
5857 } | 5802 } |
5858 } | 5803 } |
5859 | 5804 |
5860 | 5805 |
5861 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 5806 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |
5862 bool opt) const { | 5807 bool opt) const { |
5863 const intptr_t kNumInputs = 1; | 5808 const intptr_t kNumInputs = 1; |
5864 const intptr_t kNumTemps = 1; | 5809 const intptr_t kNumTemps = 1; |
5865 | 5810 |
5866 LocationSummary* summary = new(zone) LocationSummary( | 5811 LocationSummary* summary = new (zone) |
5867 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5812 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5868 | 5813 |
5869 summary->set_in(0, Location::RequiresRegister()); | 5814 summary->set_in(0, Location::RequiresRegister()); |
5870 summary->set_temp(0, Location::RequiresRegister()); | 5815 summary->set_temp(0, Location::RequiresRegister()); |
5871 | 5816 |
5872 return summary; | 5817 return summary; |
5873 } | 5818 } |
5874 | 5819 |
5875 | 5820 |
5876 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5821 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5877 Register target_reg = locs()->temp_slot(0)->reg(); | 5822 Register target_reg = locs()->temp_slot(0)->reg(); |
5878 | 5823 |
5879 __ GetNextPC(target_reg, TMP); | 5824 __ GetNextPC(target_reg, TMP); |
5880 const intptr_t entry_offset = | 5825 const intptr_t entry_offset = __ CodeSize() - 1 * Instr::kInstrSize; |
5881 __ CodeSize() - 1 * Instr::kInstrSize; | |
5882 __ AddImmediate(target_reg, target_reg, -entry_offset); | 5826 __ AddImmediate(target_reg, target_reg, -entry_offset); |
5883 | 5827 |
5884 // Add the offset. | 5828 // Add the offset. |
5885 Register offset_reg = locs()->in(0).reg(); | 5829 Register offset_reg = locs()->in(0).reg(); |
5886 if (offset()->definition()->representation() == kTagged) { | 5830 if (offset()->definition()->representation() == kTagged) { |
5887 __ SmiUntag(offset_reg); | 5831 __ SmiUntag(offset_reg); |
5888 } | 5832 } |
5889 __ addu(target_reg, target_reg, offset_reg); | 5833 __ addu(target_reg, target_reg, offset_reg); |
5890 | 5834 |
5891 // Jump to the absolute address. | 5835 // Jump to the absolute address. |
5892 __ jr(target_reg); | 5836 __ jr(target_reg); |
5893 } | 5837 } |
5894 | 5838 |
5895 | 5839 |
5896 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, | 5840 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, |
5897 bool opt) const { | 5841 bool opt) const { |
5898 const intptr_t kNumInputs = 2; | 5842 const intptr_t kNumInputs = 2; |
5899 const intptr_t kNumTemps = 0; | 5843 const intptr_t kNumTemps = 0; |
5900 if (needs_number_check()) { | 5844 if (needs_number_check()) { |
5901 LocationSummary* locs = new(zone) LocationSummary( | 5845 LocationSummary* locs = new (zone) |
5902 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5846 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
5903 locs->set_in(0, Location::RegisterLocation(A0)); | 5847 locs->set_in(0, Location::RegisterLocation(A0)); |
5904 locs->set_in(1, Location::RegisterLocation(A1)); | 5848 locs->set_in(1, Location::RegisterLocation(A1)); |
5905 locs->set_out(0, Location::RegisterLocation(A0)); | 5849 locs->set_out(0, Location::RegisterLocation(A0)); |
5906 return locs; | 5850 return locs; |
5907 } | 5851 } |
5908 LocationSummary* locs = new(zone) LocationSummary( | 5852 LocationSummary* locs = new (zone) |
5909 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5853 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5910 locs->set_in(0, Location::RegisterOrConstant(left())); | 5854 locs->set_in(0, Location::RegisterOrConstant(left())); |
5911 // Only one of the inputs can be a constant. Choose register if the first one | 5855 // Only one of the inputs can be a constant. Choose register if the first one |
5912 // is a constant. | 5856 // is a constant. |
5913 locs->set_in(1, locs->in(0).IsConstant() | 5857 locs->set_in(1, locs->in(0).IsConstant() |
5914 ? Location::RequiresRegister() | 5858 ? Location::RequiresRegister() |
5915 : Location::RegisterOrConstant(right())); | 5859 : Location::RegisterOrConstant(right())); |
5916 locs->set_out(0, Location::RequiresRegister()); | 5860 locs->set_out(0, Location::RequiresRegister()); |
5917 return locs; | 5861 return locs; |
5918 } | 5862 } |
5919 | 5863 |
5920 | 5864 |
5921 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 5865 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
5922 BranchLabels labels) { | 5866 BranchLabels labels) { |
5923 Location left = locs()->in(0); | 5867 Location left = locs()->in(0); |
5924 Location right = locs()->in(1); | 5868 Location right = locs()->in(1); |
5925 ASSERT(!left.IsConstant() || !right.IsConstant()); | 5869 ASSERT(!left.IsConstant() || !right.IsConstant()); |
5926 Condition true_condition; | 5870 Condition true_condition; |
5927 if (left.IsConstant()) { | 5871 if (left.IsConstant()) { |
5928 true_condition = compiler->EmitEqualityRegConstCompare(right.reg(), | 5872 true_condition = compiler->EmitEqualityRegConstCompare( |
5929 left.constant(), | 5873 right.reg(), left.constant(), needs_number_check(), token_pos()); |
5930 needs_number_check(), | |
5931 token_pos()); | |
5932 } else if (right.IsConstant()) { | 5874 } else if (right.IsConstant()) { |
5933 true_condition = compiler->EmitEqualityRegConstCompare(left.reg(), | 5875 true_condition = compiler->EmitEqualityRegConstCompare( |
5934 right.constant(), | 5876 left.reg(), right.constant(), needs_number_check(), token_pos()); |
5935 needs_number_check(), | |
5936 token_pos()); | |
5937 } else { | 5877 } else { |
5938 true_condition = compiler->EmitEqualityRegRegCompare(left.reg(), | 5878 true_condition = compiler->EmitEqualityRegRegCompare( |
5939 right.reg(), | 5879 left.reg(), right.reg(), needs_number_check(), token_pos()); |
5940 needs_number_check(), | |
5941 token_pos()); | |
5942 } | 5880 } |
5943 if (kind() != Token::kEQ_STRICT) { | 5881 if (kind() != Token::kEQ_STRICT) { |
5944 ASSERT(kind() == Token::kNE_STRICT); | 5882 ASSERT(kind() == Token::kNE_STRICT); |
5945 true_condition = NegateCondition(true_condition); | 5883 true_condition = NegateCondition(true_condition); |
5946 } | 5884 } |
5947 return true_condition; | 5885 return true_condition; |
5948 } | 5886 } |
5949 | 5887 |
5950 | 5888 |
5951 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5889 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5952 __ Comment("StrictCompareInstr"); | 5890 __ Comment("StrictCompareInstr"); |
5953 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 5891 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
5954 | 5892 |
5955 Label is_true, is_false; | 5893 Label is_true, is_false; |
5956 BranchLabels labels = { &is_true, &is_false, &is_false }; | 5894 BranchLabels labels = {&is_true, &is_false, &is_false}; |
5957 Condition true_condition = EmitComparisonCode(compiler, labels); | 5895 Condition true_condition = EmitComparisonCode(compiler, labels); |
5958 EmitBranchOnCondition(compiler, true_condition, labels); | 5896 EmitBranchOnCondition(compiler, true_condition, labels); |
5959 | 5897 |
5960 Register result = locs()->out(0).reg(); | 5898 Register result = locs()->out(0).reg(); |
5961 Label done; | 5899 Label done; |
5962 __ Bind(&is_false); | 5900 __ Bind(&is_false); |
5963 __ LoadObject(result, Bool::False()); | 5901 __ LoadObject(result, Bool::False()); |
5964 __ b(&done); | 5902 __ b(&done); |
5965 __ Bind(&is_true); | 5903 __ Bind(&is_true); |
5966 __ LoadObject(result, Bool::True()); | 5904 __ LoadObject(result, Bool::True()); |
5967 __ Bind(&done); | 5905 __ Bind(&done); |
5968 } | 5906 } |
5969 | 5907 |
5970 | 5908 |
5971 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 5909 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
5972 BranchInstr* branch) { | 5910 BranchInstr* branch) { |
5973 __ Comment("StrictCompareInstr::EmitBranchCode"); | 5911 __ Comment("StrictCompareInstr::EmitBranchCode"); |
5974 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 5912 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
5975 | 5913 |
5976 BranchLabels labels = compiler->CreateBranchLabels(branch); | 5914 BranchLabels labels = compiler->CreateBranchLabels(branch); |
5977 Condition true_condition = EmitComparisonCode(compiler, labels); | 5915 Condition true_condition = EmitComparisonCode(compiler, labels); |
5978 EmitBranchOnCondition(compiler, true_condition, labels); | 5916 EmitBranchOnCondition(compiler, true_condition, labels); |
5979 } | 5917 } |
5980 | 5918 |
5981 | 5919 |
5982 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 5920 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
5983 bool opt) const { | 5921 bool opt) const { |
5984 return LocationSummary::Make(zone, | 5922 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
5985 1, | |
5986 Location::RequiresRegister(), | |
5987 LocationSummary::kNoCall); | 5923 LocationSummary::kNoCall); |
5988 } | 5924 } |
5989 | 5925 |
5990 | 5926 |
5991 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5927 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5992 Register value = locs()->in(0).reg(); | 5928 Register value = locs()->in(0).reg(); |
5993 Register result = locs()->out(0).reg(); | 5929 Register result = locs()->out(0).reg(); |
5994 | 5930 |
5995 __ LoadObject(result, Bool::True()); | 5931 __ LoadObject(result, Bool::True()); |
5996 __ LoadObject(TMP, Bool::False()); | 5932 __ LoadObject(TMP, Bool::False()); |
5997 __ subu(CMPRES1, value, result); | 5933 __ subu(CMPRES1, value, result); |
5998 __ movz(result, TMP, CMPRES1); // If value is True, move False into result. | 5934 __ movz(result, TMP, CMPRES1); // If value is True, move False into result. |
5999 } | 5935 } |
6000 | 5936 |
6001 | 5937 |
6002 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 5938 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
6003 bool opt) const { | 5939 bool opt) const { |
6004 return MakeCallSummary(zone); | 5940 return MakeCallSummary(zone); |
6005 } | 5941 } |
6006 | 5942 |
6007 | 5943 |
6008 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5944 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6009 __ Comment("AllocateObjectInstr"); | 5945 __ Comment("AllocateObjectInstr"); |
6010 const Code& stub = Code::ZoneHandle( | 5946 const Code& stub = Code::ZoneHandle( |
6011 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 5947 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |
6012 const StubEntry stub_entry(stub); | 5948 const StubEntry stub_entry(stub); |
6013 compiler->GenerateCall(token_pos(), | 5949 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, |
6014 stub_entry, | |
6015 RawPcDescriptors::kOther, | |
6016 locs()); | 5950 locs()); |
6017 compiler->AddStubCallTarget(stub); | 5951 compiler->AddStubCallTarget(stub); |
6018 __ Drop(ArgumentCount()); // Discard arguments. | 5952 __ Drop(ArgumentCount()); // Discard arguments. |
6019 } | 5953 } |
6020 | 5954 |
6021 | 5955 |
6022 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5956 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6023 ASSERT(!compiler->is_optimizing()); | 5957 ASSERT(!compiler->is_optimizing()); |
6024 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); | 5958 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); |
6025 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); | 5959 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); |
6026 compiler->RecordSafepoint(locs()); | 5960 compiler->RecordSafepoint(locs()); |
6027 } | 5961 } |
6028 | 5962 |
6029 | 5963 |
6030 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary( | 5964 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary(Zone* zone, |
6031 Zone* zone, bool opt) const { | 5965 bool opt) const { |
6032 const intptr_t kNumInputs = 1; | 5966 const intptr_t kNumInputs = 1; |
6033 const intptr_t kNumTemps = 0; | 5967 const intptr_t kNumTemps = 0; |
6034 LocationSummary* locs = new(zone) LocationSummary( | 5968 LocationSummary* locs = new (zone) |
6035 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5969 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
6036 locs->set_in(0, Location::RegisterLocation(T0)); | 5970 locs->set_in(0, Location::RegisterLocation(T0)); |
6037 locs->set_out(0, Location::RegisterLocation(T0)); | 5971 locs->set_out(0, Location::RegisterLocation(T0)); |
6038 return locs; | 5972 return locs; |
6039 } | 5973 } |
6040 | 5974 |
6041 | 5975 |
6042 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5976 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6043 const Register typed_data = locs()->in(0).reg(); | 5977 const Register typed_data = locs()->in(0).reg(); |
6044 const Register result = locs()->out(0).reg(); | 5978 const Register result = locs()->out(0).reg(); |
6045 __ Comment("GrowRegExpStackInstr"); | 5979 __ Comment("GrowRegExpStackInstr"); |
6046 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 5980 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
6047 __ LoadObject(TMP, Object::null_object()); | 5981 __ LoadObject(TMP, Object::null_object()); |
6048 __ sw(TMP, Address(SP, 1 * kWordSize)); | 5982 __ sw(TMP, Address(SP, 1 * kWordSize)); |
6049 __ sw(typed_data, Address(SP, 0 * kWordSize)); | 5983 __ sw(typed_data, Address(SP, 0 * kWordSize)); |
6050 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, | 5984 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
6051 deopt_id(), | 5985 kGrowRegExpStackRuntimeEntry, 1, locs()); |
6052 kGrowRegExpStackRuntimeEntry, | |
6053 1, | |
6054 locs()); | |
6055 __ lw(result, Address(SP, 1 * kWordSize)); | 5986 __ lw(result, Address(SP, 1 * kWordSize)); |
6056 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 5987 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
6057 } | 5988 } |
6058 | 5989 |
6059 | 5990 |
6060 } // namespace dart | 5991 } // namespace dart |
6061 | 5992 |
6062 #endif // defined TARGET_ARCH_MIPS | 5993 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |