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/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); | 42 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); |
43 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress"); | 43 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress"); |
44 DEFINE_FLAG(bool, truncating_left_shift, true, | 44 DEFINE_FLAG(bool, truncating_left_shift, true, |
45 "Optimize left shift to truncate if possible"); | 45 "Optimize left shift to truncate if possible"); |
46 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); | 46 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); |
47 DECLARE_FLAG(bool, enable_type_checks); | 47 DECLARE_FLAG(bool, enable_type_checks); |
48 DECLARE_FLAG(bool, source_lines); | 48 DECLARE_FLAG(bool, source_lines); |
49 DECLARE_FLAG(bool, trace_type_check_elimination); | 49 DECLARE_FLAG(bool, trace_type_check_elimination); |
50 DECLARE_FLAG(bool, warn_on_javascript_compatibility); | 50 DECLARE_FLAG(bool, warn_on_javascript_compatibility); |
51 | 51 |
| 52 // Quick access to the locally defined isolate() method. |
| 53 #define I (isolate()) |
52 | 54 |
53 static bool ShouldInlineSimd() { | 55 static bool ShouldInlineSimd() { |
54 return FlowGraphCompiler::SupportsUnboxedSimd128(); | 56 return FlowGraphCompiler::SupportsUnboxedSimd128(); |
55 } | 57 } |
56 | 58 |
57 | 59 |
58 static bool CanUnboxDouble() { | 60 static bool CanUnboxDouble() { |
59 return FlowGraphCompiler::SupportsUnboxedDoubles(); | 61 return FlowGraphCompiler::SupportsUnboxedDoubles(); |
60 } | 62 } |
61 | 63 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 } | 152 } |
151 } | 153 } |
152 | 154 |
153 for (intptr_t i = 0; i < class_ids.length(); i++) { | 155 for (intptr_t i = 0; i < class_ids.length(); i++) { |
154 if (class_ids[i] == kDynamicCid) { | 156 if (class_ids[i] == kDynamicCid) { |
155 // Not all cid-s known. | 157 // Not all cid-s known. |
156 return false; | 158 return false; |
157 } | 159 } |
158 } | 160 } |
159 | 161 |
160 const Array& args_desc_array = Array::Handle(isolate(), | 162 const Array& args_desc_array = Array::Handle(I, |
161 ArgumentsDescriptor::New(call->ArgumentCount(), call->argument_names())); | 163 ArgumentsDescriptor::New(call->ArgumentCount(), call->argument_names())); |
162 ArgumentsDescriptor args_desc(args_desc_array); | 164 ArgumentsDescriptor args_desc(args_desc_array); |
163 const Class& receiver_class = Class::Handle(isolate(), | 165 const Class& receiver_class = Class::Handle(I, |
164 isolate()->class_table()->At(class_ids[0])); | 166 isolate()->class_table()->At(class_ids[0])); |
165 const Function& function = Function::Handle(isolate(), | 167 const Function& function = Function::Handle(I, |
166 Resolver::ResolveDynamicForReceiverClass( | 168 Resolver::ResolveDynamicForReceiverClass( |
167 receiver_class, | 169 receiver_class, |
168 call->function_name(), | 170 call->function_name(), |
169 args_desc)); | 171 args_desc)); |
170 if (function.IsNull()) { | 172 if (function.IsNull()) { |
171 return false; | 173 return false; |
172 } | 174 } |
173 // Create new ICData, do not modify the one attached to the instruction | 175 // Create new ICData, do not modify the one attached to the instruction |
174 // since it is attached to the assembly instruction itself. | 176 // since it is attached to the assembly instruction itself. |
175 // TODO(srdjan): Prevent modification of ICData object that is | 177 // TODO(srdjan): Prevent modification of ICData object that is |
176 // referenced in assembly code. | 178 // referenced in assembly code. |
177 ICData& ic_data = ICData::ZoneHandle(isolate(), ICData::New( | 179 ICData& ic_data = ICData::ZoneHandle(I, ICData::New( |
178 flow_graph_->parsed_function().function(), | 180 flow_graph_->parsed_function().function(), |
179 call->function_name(), | 181 call->function_name(), |
180 args_desc_array, | 182 args_desc_array, |
181 call->deopt_id(), | 183 call->deopt_id(), |
182 class_ids.length())); | 184 class_ids.length())); |
183 if (class_ids.length() > 1) { | 185 if (class_ids.length() > 1) { |
184 ic_data.AddCheck(class_ids, function); | 186 ic_data.AddCheck(class_ids, function); |
185 } else { | 187 } else { |
186 ASSERT(class_ids.length() == 1); | 188 ASSERT(class_ids.length() == 1); |
187 ic_data.AddReceiverCheck(class_ids[0], function); | 189 ic_data.AddReceiverCheck(class_ids[0], function); |
188 } | 190 } |
189 call->set_ic_data(&ic_data); | 191 call->set_ic_data(&ic_data); |
190 return true; | 192 return true; |
191 } | 193 } |
192 | 194 |
193 | 195 |
194 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data, | 196 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data, |
195 intptr_t cid) { | 197 intptr_t cid) { |
196 ASSERT(ic_data.NumArgsTested() == 1); | 198 ASSERT(ic_data.NumArgsTested() == 1); |
197 | 199 |
198 if ((ic_data.NumberOfChecks() == 1) && | 200 if ((ic_data.NumberOfChecks() == 1) && |
199 (ic_data.GetReceiverClassIdAt(0) == cid)) { | 201 (ic_data.GetReceiverClassIdAt(0) == cid)) { |
200 return ic_data; // Nothing to do | 202 return ic_data; // Nothing to do |
201 } | 203 } |
202 | 204 |
203 const Function& function = | 205 const Function& function = |
204 Function::Handle(isolate(), ic_data.GetTargetForReceiverClassId(cid)); | 206 Function::Handle(I, ic_data.GetTargetForReceiverClassId(cid)); |
205 // TODO(fschneider): Try looking up the function on the class if it is | 207 // TODO(fschneider): Try looking up the function on the class if it is |
206 // not found in the ICData. | 208 // not found in the ICData. |
207 if (!function.IsNull()) { | 209 if (!function.IsNull()) { |
208 const ICData& new_ic_data = ICData::ZoneHandle(isolate(), ICData::New( | 210 const ICData& new_ic_data = ICData::ZoneHandle(I, ICData::New( |
209 Function::Handle(isolate(), ic_data.owner()), | 211 Function::Handle(I, ic_data.owner()), |
210 String::Handle(isolate(), ic_data.target_name()), | 212 String::Handle(I, ic_data.target_name()), |
211 Object::empty_array(), // Dummy argument descriptor. | 213 Object::empty_array(), // Dummy argument descriptor. |
212 ic_data.deopt_id(), | 214 ic_data.deopt_id(), |
213 ic_data.NumArgsTested())); | 215 ic_data.NumArgsTested())); |
214 new_ic_data.SetDeoptReasons(ic_data.DeoptReasons()); | 216 new_ic_data.SetDeoptReasons(ic_data.DeoptReasons()); |
215 new_ic_data.AddReceiverCheck(cid, function); | 217 new_ic_data.AddReceiverCheck(cid, function); |
216 return new_ic_data; | 218 return new_ic_data; |
217 } | 219 } |
218 | 220 |
219 return ic_data; | 221 return ic_data; |
220 } | 222 } |
(...skipping 12 matching lines...) Expand all Loading... |
233 } | 235 } |
234 | 236 |
235 const ICData& ic_data = TrySpecializeICData(call->ic_data(), receiver_cid); | 237 const ICData& ic_data = TrySpecializeICData(call->ic_data(), receiver_cid); |
236 if (ic_data.raw() == call->ic_data().raw()) { | 238 if (ic_data.raw() == call->ic_data().raw()) { |
237 // No specialization. | 239 // No specialization. |
238 return; | 240 return; |
239 } | 241 } |
240 | 242 |
241 const bool with_checks = false; | 243 const bool with_checks = false; |
242 PolymorphicInstanceCallInstr* specialized = | 244 PolymorphicInstanceCallInstr* specialized = |
243 new(isolate()) PolymorphicInstanceCallInstr(call->instance_call(), | 245 new(I) PolymorphicInstanceCallInstr(call->instance_call(), |
244 ic_data, | 246 ic_data, |
245 with_checks); | 247 with_checks); |
246 call->ReplaceWith(specialized, current_iterator()); | 248 call->ReplaceWith(specialized, current_iterator()); |
247 } | 249 } |
248 | 250 |
249 | 251 |
250 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) { | 252 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) { |
251 BinarySmiOpInstr* instr = d->AsBinarySmiOp(); | 253 BinarySmiOpInstr* instr = d->AsBinarySmiOp(); |
252 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) { | 254 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) { |
253 return instr; | 255 return instr; |
254 } | 256 } |
255 return NULL; | 257 return NULL; |
(...skipping 30 matching lines...) Expand all Loading... |
286 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) { | 288 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) { |
287 smi_shift_left = AsSmiShiftLeftInstruction(right_instr); | 289 smi_shift_left = AsSmiShiftLeftInstruction(right_instr); |
288 } | 290 } |
289 if (smi_shift_left == NULL) return; | 291 if (smi_shift_left == NULL) return; |
290 | 292 |
291 // Pattern recognized. | 293 // Pattern recognized. |
292 smi_shift_left->set_is_truncating(true); | 294 smi_shift_left->set_is_truncating(true); |
293 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); | 295 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); |
294 if (bit_and_instr->IsBinaryMintOp()) { | 296 if (bit_and_instr->IsBinaryMintOp()) { |
295 // Replace Mint op with Smi op. | 297 // Replace Mint op with Smi op. |
296 BinarySmiOpInstr* smi_op = new(isolate()) BinarySmiOpInstr( | 298 BinarySmiOpInstr* smi_op = new(I) BinarySmiOpInstr( |
297 Token::kBIT_AND, | 299 Token::kBIT_AND, |
298 new(isolate()) Value(left_instr), | 300 new(I) Value(left_instr), |
299 new(isolate()) Value(right_instr), | 301 new(I) Value(right_instr), |
300 Isolate::kNoDeoptId, // BIT_AND cannot deoptimize. | 302 Isolate::kNoDeoptId, // BIT_AND cannot deoptimize. |
301 Scanner::kNoSourcePos); | 303 Scanner::kNoSourcePos); |
302 bit_and_instr->ReplaceWith(smi_op, current_iterator()); | 304 bit_and_instr->ReplaceWith(smi_op, current_iterator()); |
303 } | 305 } |
304 } | 306 } |
305 | 307 |
306 | 308 |
307 | 309 |
308 // Used by TryMergeDivMod. | 310 // Used by TryMergeDivMod. |
309 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction, | 311 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction, |
310 // and the using instruction. This is an intermediate step before merging. | 312 // and the using instruction. This is an intermediate step before merging. |
311 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr, | 313 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr, |
312 intptr_t ix, | 314 intptr_t ix, |
313 intptr_t cid) { | 315 intptr_t cid) { |
314 const intptr_t index_scale = Instance::ElementSizeFor(cid); | 316 const intptr_t index_scale = Instance::ElementSizeFor(cid); |
315 ConstantInstr* index_instr = | 317 ConstantInstr* index_instr = |
316 flow_graph()->GetConstant(Smi::Handle(isolate(), Smi::New(ix))); | 318 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(ix))); |
317 LoadIndexedInstr* load = | 319 LoadIndexedInstr* load = |
318 new(isolate()) LoadIndexedInstr(new(isolate()) Value(instr), | 320 new(I) LoadIndexedInstr(new(I) Value(instr), |
319 new(isolate()) Value(index_instr), | 321 new(I) Value(index_instr), |
320 index_scale, | 322 index_scale, |
321 cid, | 323 cid, |
322 Isolate::kNoDeoptId, | 324 Isolate::kNoDeoptId, |
323 instr->token_pos()); | 325 instr->token_pos()); |
324 instr->ReplaceUsesWith(load); | 326 instr->ReplaceUsesWith(load); |
325 flow_graph()->InsertAfter(instr, load, NULL, FlowGraph::kValue); | 327 flow_graph()->InsertAfter(instr, load, NULL, FlowGraph::kValue); |
326 } | 328 } |
327 | 329 |
328 | 330 |
329 void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr, | 331 void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr, |
330 intptr_t index, | 332 intptr_t index, |
331 Representation rep, | 333 Representation rep, |
332 intptr_t cid) { | 334 intptr_t cid) { |
333 ExtractNthOutputInstr* extract = | 335 ExtractNthOutputInstr* extract = |
334 new(isolate()) ExtractNthOutputInstr(new(isolate()) Value(instr), | 336 new(I) ExtractNthOutputInstr(new(I) Value(instr), index, rep, cid); |
335 index, | |
336 rep, | |
337 cid); | |
338 instr->ReplaceUsesWith(extract); | 337 instr->ReplaceUsesWith(extract); |
339 flow_graph()->InsertAfter(instr, extract, NULL, FlowGraph::kValue); | 338 flow_graph()->InsertAfter(instr, extract, NULL, FlowGraph::kValue); |
340 } | 339 } |
341 | 340 |
342 | 341 |
343 // Dart: | 342 // Dart: |
344 // var x = d % 10; | 343 // var x = d % 10; |
345 // var y = d ~/ 10; | 344 // var y = d ~/ 10; |
346 // var z = x + y; | 345 // var z = x + y; |
347 // | 346 // |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 AppendExtractNthOutputForMerged( | 387 AppendExtractNthOutputForMerged( |
389 curr_instr, | 388 curr_instr, |
390 MergedMathInstr::OutputIndexOf(curr_instr->op_kind()), | 389 MergedMathInstr::OutputIndexOf(curr_instr->op_kind()), |
391 kTagged, kSmiCid); | 390 kTagged, kSmiCid); |
392 ASSERT(other_binop->HasUses()); | 391 ASSERT(other_binop->HasUses()); |
393 AppendExtractNthOutputForMerged( | 392 AppendExtractNthOutputForMerged( |
394 other_binop, | 393 other_binop, |
395 MergedMathInstr::OutputIndexOf(other_binop->op_kind()), | 394 MergedMathInstr::OutputIndexOf(other_binop->op_kind()), |
396 kTagged, kSmiCid); | 395 kTagged, kSmiCid); |
397 | 396 |
398 ZoneGrowableArray<Value*>* args = | 397 ZoneGrowableArray<Value*>* args = new(I) ZoneGrowableArray<Value*>(2); |
399 new(isolate()) ZoneGrowableArray<Value*>(2); | 398 args->Add(new(I) Value(curr_instr->left()->definition())); |
400 args->Add(new(isolate()) Value(curr_instr->left()->definition())); | 399 args->Add(new(I) Value(curr_instr->right()->definition())); |
401 args->Add(new(isolate()) Value(curr_instr->right()->definition())); | |
402 | 400 |
403 // Replace with TruncDivMod. | 401 // Replace with TruncDivMod. |
404 MergedMathInstr* div_mod = new(isolate()) MergedMathInstr( | 402 MergedMathInstr* div_mod = new(I) MergedMathInstr( |
405 args, | 403 args, |
406 curr_instr->deopt_id(), | 404 curr_instr->deopt_id(), |
407 MergedMathInstr::kTruncDivMod); | 405 MergedMathInstr::kTruncDivMod); |
408 curr_instr->ReplaceWith(div_mod, current_iterator()); | 406 curr_instr->ReplaceWith(div_mod, current_iterator()); |
409 other_binop->ReplaceUsesWith(div_mod); | 407 other_binop->ReplaceUsesWith(div_mod); |
410 other_binop->RemoveFromGraph(); | 408 other_binop->RemoveFromGraph(); |
411 // Only one merge possible. Because canonicalization happens later, | 409 // Only one merge possible. Because canonicalization happens later, |
412 // more candidates are possible. | 410 // more candidates are possible. |
413 // TODO(srdjan): Allow merging of trunc-div/mod into truncDivMod. | 411 // TODO(srdjan): Allow merging of trunc-div/mod into truncDivMod. |
414 break; | 412 break; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 (*merge_candidates)[k] = NULL; // Clear it. | 447 (*merge_candidates)[k] = NULL; // Clear it. |
450 ASSERT(curr_instr->HasUses()); | 448 ASSERT(curr_instr->HasUses()); |
451 AppendExtractNthOutputForMerged(curr_instr, | 449 AppendExtractNthOutputForMerged(curr_instr, |
452 MergedMathInstr::OutputIndexOf(kind), | 450 MergedMathInstr::OutputIndexOf(kind), |
453 kUnboxedDouble, kDoubleCid); | 451 kUnboxedDouble, kDoubleCid); |
454 ASSERT(other_op->HasUses()); | 452 ASSERT(other_op->HasUses()); |
455 AppendExtractNthOutputForMerged( | 453 AppendExtractNthOutputForMerged( |
456 other_op, | 454 other_op, |
457 MergedMathInstr::OutputIndexOf(other_kind), | 455 MergedMathInstr::OutputIndexOf(other_kind), |
458 kUnboxedDouble, kDoubleCid); | 456 kUnboxedDouble, kDoubleCid); |
459 ZoneGrowableArray<Value*>* args = | 457 ZoneGrowableArray<Value*>* args = new(I) ZoneGrowableArray<Value*>(1); |
460 new(isolate()) ZoneGrowableArray<Value*>(1); | 458 args->Add(new(I) Value(curr_instr->value()->definition())); |
461 args->Add(new(isolate()) Value(curr_instr->value()->definition())); | |
462 // Replace with SinCos. | 459 // Replace with SinCos. |
463 MergedMathInstr* sin_cos = | 460 MergedMathInstr* sin_cos = |
464 new(isolate()) MergedMathInstr(args, | 461 new(I) MergedMathInstr(args, |
465 curr_instr->DeoptimizationTarget(), | 462 curr_instr->DeoptimizationTarget(), |
466 MergedMathInstr::kSinCos); | 463 MergedMathInstr::kSinCos); |
467 curr_instr->ReplaceWith(sin_cos, current_iterator()); | 464 curr_instr->ReplaceWith(sin_cos, current_iterator()); |
468 other_op->ReplaceUsesWith(sin_cos); | 465 other_op->ReplaceUsesWith(sin_cos); |
469 other_op->RemoveFromGraph(); | 466 other_op->RemoveFromGraph(); |
470 // Only one merge possible. Because canonicalization happens later, | 467 // Only one merge possible. Because canonicalization happens later, |
471 // more candidates are possible. | 468 // more candidates are possible. |
472 // TODO(srdjan): Allow merging of sin/cos into sincos. | 469 // TODO(srdjan): Allow merging of sin/cos into sincos. |
473 break; | 470 break; |
474 } | 471 } |
475 } | 472 } |
476 } | 473 } |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 } else { | 600 } else { |
604 deopt_target = insert_before = use->instruction(); | 601 deopt_target = insert_before = use->instruction(); |
605 } | 602 } |
606 | 603 |
607 Definition* converted = NULL; | 604 Definition* converted = NULL; |
608 if ((from == kTagged) && (to == kUnboxedMint)) { | 605 if ((from == kTagged) && (to == kUnboxedMint)) { |
609 ASSERT((deopt_target != NULL) || | 606 ASSERT((deopt_target != NULL) || |
610 (use->Type()->ToCid() == kUnboxedMint)); | 607 (use->Type()->ToCid() == kUnboxedMint)); |
611 const intptr_t deopt_id = (deopt_target != NULL) ? | 608 const intptr_t deopt_id = (deopt_target != NULL) ? |
612 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 609 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
613 converted = new(isolate()) UnboxIntegerInstr(use->CopyWithType(), deopt_id); | 610 converted = new(I) UnboxIntegerInstr(use->CopyWithType(), deopt_id); |
614 | 611 |
615 } else if ((from == kUnboxedMint) && (to == kTagged)) { | 612 } else if ((from == kUnboxedMint) && (to == kTagged)) { |
616 converted = new(isolate()) BoxIntegerInstr(use->CopyWithType()); | 613 converted = new(I) BoxIntegerInstr(use->CopyWithType()); |
617 | 614 |
618 } else if (from == kUnboxedMint && to == kUnboxedDouble) { | 615 } else if (from == kUnboxedMint && to == kUnboxedDouble) { |
619 ASSERT(CanUnboxDouble()); | 616 ASSERT(CanUnboxDouble()); |
620 // Convert by boxing/unboxing. | 617 // Convert by boxing/unboxing. |
621 // TODO(fschneider): Implement direct unboxed mint-to-double conversion. | 618 // TODO(fschneider): Implement direct unboxed mint-to-double conversion. |
622 BoxIntegerInstr* boxed = | 619 BoxIntegerInstr* boxed = |
623 new(isolate()) BoxIntegerInstr(use->CopyWithType()); | 620 new(I) BoxIntegerInstr(use->CopyWithType()); |
624 use->BindTo(boxed); | 621 use->BindTo(boxed); |
625 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); | 622 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); |
626 | 623 |
627 const intptr_t deopt_id = (deopt_target != NULL) ? | 624 const intptr_t deopt_id = (deopt_target != NULL) ? |
628 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 625 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
629 converted = new(isolate()) UnboxDoubleInstr( | 626 converted = new(I) UnboxDoubleInstr(new(I) Value(boxed), deopt_id); |
630 new(isolate()) Value(boxed), deopt_id); | |
631 | 627 |
632 } else if ((from == kUnboxedDouble) && (to == kTagged)) { | 628 } else if ((from == kUnboxedDouble) && (to == kTagged)) { |
633 ASSERT(CanUnboxDouble()); | 629 ASSERT(CanUnboxDouble()); |
634 converted = new(isolate()) BoxDoubleInstr(use->CopyWithType()); | 630 converted = new(I) BoxDoubleInstr(use->CopyWithType()); |
635 | 631 |
636 } else if ((from == kTagged) && (to == kUnboxedDouble)) { | 632 } else if ((from == kTagged) && (to == kUnboxedDouble)) { |
637 ASSERT(CanUnboxDouble()); | 633 ASSERT(CanUnboxDouble()); |
638 ASSERT((deopt_target != NULL) || | 634 ASSERT((deopt_target != NULL) || |
639 (use->Type()->ToCid() == kDoubleCid)); | 635 (use->Type()->ToCid() == kDoubleCid)); |
640 const intptr_t deopt_id = (deopt_target != NULL) ? | 636 const intptr_t deopt_id = (deopt_target != NULL) ? |
641 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 637 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
642 ConstantInstr* constant = use->definition()->AsConstant(); | 638 ConstantInstr* constant = use->definition()->AsConstant(); |
643 if ((constant != NULL) && constant->value().IsSmi()) { | 639 if ((constant != NULL) && constant->value().IsSmi()) { |
644 const double dbl_val = Smi::Cast(constant->value()).AsDoubleValue(); | 640 const double dbl_val = Smi::Cast(constant->value()).AsDoubleValue(); |
645 const Double& dbl_obj = | 641 const Double& dbl_obj = |
646 Double::ZoneHandle(isolate(), Double::New(dbl_val, Heap::kOld)); | 642 Double::ZoneHandle(I, Double::New(dbl_val, Heap::kOld)); |
647 ConstantInstr* double_const = flow_graph()->GetConstant(dbl_obj); | 643 ConstantInstr* double_const = flow_graph()->GetConstant(dbl_obj); |
648 converted = new(isolate()) UnboxDoubleInstr( | 644 converted = new(I) UnboxDoubleInstr(new(I) Value(double_const), deopt_id); |
649 new(isolate()) Value(double_const), deopt_id); | |
650 } else { | 645 } else { |
651 converted = new(isolate()) UnboxDoubleInstr( | 646 converted = new(I) UnboxDoubleInstr(use->CopyWithType(), deopt_id); |
652 use->CopyWithType(), deopt_id); | |
653 } | 647 } |
654 } else if ((from == kTagged) && (to == kUnboxedFloat32x4)) { | 648 } else if ((from == kTagged) && (to == kUnboxedFloat32x4)) { |
655 ASSERT((deopt_target != NULL) || | 649 ASSERT((deopt_target != NULL) || |
656 (use->Type()->ToCid() == kFloat32x4Cid)); | 650 (use->Type()->ToCid() == kFloat32x4Cid)); |
657 const intptr_t deopt_id = (deopt_target != NULL) ? | 651 const intptr_t deopt_id = (deopt_target != NULL) ? |
658 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 652 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
659 converted = new(isolate()) UnboxFloat32x4Instr( | 653 converted = new(I) UnboxFloat32x4Instr( |
660 use->CopyWithType(), deopt_id); | 654 use->CopyWithType(), deopt_id); |
661 } else if ((from == kUnboxedFloat32x4) && (to == kTagged)) { | 655 } else if ((from == kUnboxedFloat32x4) && (to == kTagged)) { |
662 converted = new(isolate()) BoxFloat32x4Instr(use->CopyWithType()); | 656 converted = new(I) BoxFloat32x4Instr(use->CopyWithType()); |
663 } else if ((from == kTagged) && (to == kUnboxedInt32x4)) { | 657 } else if ((from == kTagged) && (to == kUnboxedInt32x4)) { |
664 ASSERT((deopt_target != NULL) || (use->Type()->ToCid() == kInt32x4Cid)); | 658 ASSERT((deopt_target != NULL) || (use->Type()->ToCid() == kInt32x4Cid)); |
665 const intptr_t deopt_id = (deopt_target != NULL) ? | 659 const intptr_t deopt_id = (deopt_target != NULL) ? |
666 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 660 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
667 converted = new(isolate()) UnboxInt32x4Instr(use->CopyWithType(), deopt_id); | 661 converted = new(I) UnboxInt32x4Instr(use->CopyWithType(), deopt_id); |
668 } else if ((from == kUnboxedInt32x4) && (to == kTagged)) { | 662 } else if ((from == kUnboxedInt32x4) && (to == kTagged)) { |
669 converted = new(isolate()) BoxInt32x4Instr(use->CopyWithType()); | 663 converted = new(I) BoxInt32x4Instr(use->CopyWithType()); |
670 } else if ((from == kTagged) && (to == kUnboxedFloat64x2)) { | 664 } else if ((from == kTagged) && (to == kUnboxedFloat64x2)) { |
671 ASSERT((deopt_target != NULL) || (use->Type()->ToCid() == kFloat64x2Cid)); | 665 ASSERT((deopt_target != NULL) || (use->Type()->ToCid() == kFloat64x2Cid)); |
672 const intptr_t deopt_id = (deopt_target != NULL) ? | 666 const intptr_t deopt_id = (deopt_target != NULL) ? |
673 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 667 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
674 converted = new(isolate()) UnboxFloat64x2Instr( | 668 converted = new(I) UnboxFloat64x2Instr(use->CopyWithType(), deopt_id); |
675 use->CopyWithType(), deopt_id); | |
676 } else if ((from == kUnboxedFloat64x2) && (to == kTagged)) { | 669 } else if ((from == kUnboxedFloat64x2) && (to == kTagged)) { |
677 converted = new(isolate()) BoxFloat64x2Instr(use->CopyWithType()); | 670 converted = new(I) BoxFloat64x2Instr(use->CopyWithType()); |
678 } else { | 671 } else { |
679 // We have failed to find a suitable conversion instruction. | 672 // We have failed to find a suitable conversion instruction. |
680 // Insert two "dummy" conversion instructions with the correct | 673 // Insert two "dummy" conversion instructions with the correct |
681 // "from" and "to" representation. The inserted instructions will | 674 // "from" and "to" representation. The inserted instructions will |
682 // trigger a deoptimization if executed. See #12417 for a discussion. | 675 // trigger a deoptimization if executed. See #12417 for a discussion. |
683 const intptr_t deopt_id = (deopt_target != NULL) ? | 676 const intptr_t deopt_id = (deopt_target != NULL) ? |
684 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 677 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
685 ASSERT(from != kTagged); | 678 ASSERT(from != kTagged); |
686 ASSERT(to != kTagged); | 679 ASSERT(to != kTagged); |
687 Definition* boxed = NULL; | 680 Definition* boxed = NULL; |
688 if (from == kUnboxedDouble) { | 681 if (from == kUnboxedDouble) { |
689 boxed = new(isolate()) BoxDoubleInstr(use->CopyWithType()); | 682 boxed = new(I) BoxDoubleInstr(use->CopyWithType()); |
690 } else if (from == kUnboxedInt32x4) { | 683 } else if (from == kUnboxedInt32x4) { |
691 boxed = new(isolate()) BoxInt32x4Instr(use->CopyWithType()); | 684 boxed = new(I) BoxInt32x4Instr(use->CopyWithType()); |
692 } else if (from == kUnboxedFloat32x4) { | 685 } else if (from == kUnboxedFloat32x4) { |
693 boxed = new(isolate()) BoxFloat32x4Instr(use->CopyWithType()); | 686 boxed = new(I) BoxFloat32x4Instr(use->CopyWithType()); |
694 } else if (from == kUnboxedMint) { | 687 } else if (from == kUnboxedMint) { |
695 boxed = new(isolate()) BoxIntegerInstr(use->CopyWithType()); | 688 boxed = new(I) BoxIntegerInstr(use->CopyWithType()); |
696 } else if (from == kUnboxedFloat64x2) { | 689 } else if (from == kUnboxedFloat64x2) { |
697 boxed = new(isolate()) BoxFloat64x2Instr(use->CopyWithType()); | 690 boxed = new(I) BoxFloat64x2Instr(use->CopyWithType()); |
698 } else { | 691 } else { |
699 UNIMPLEMENTED(); | 692 UNIMPLEMENTED(); |
700 } | 693 } |
701 use->BindTo(boxed); | 694 use->BindTo(boxed); |
702 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); | 695 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); |
703 Value* to_value = new(isolate()) Value(boxed); | 696 Value* to_value = new(I) Value(boxed); |
704 if (to == kUnboxedDouble) { | 697 if (to == kUnboxedDouble) { |
705 converted = new(isolate()) UnboxDoubleInstr(to_value, deopt_id); | 698 converted = new(I) UnboxDoubleInstr(to_value, deopt_id); |
706 } else if (to == kUnboxedInt32x4) { | 699 } else if (to == kUnboxedInt32x4) { |
707 converted = new(isolate()) UnboxInt32x4Instr(to_value, deopt_id); | 700 converted = new(I) UnboxInt32x4Instr(to_value, deopt_id); |
708 } else if (to == kUnboxedFloat32x4) { | 701 } else if (to == kUnboxedFloat32x4) { |
709 converted = new(isolate()) UnboxFloat32x4Instr(to_value, deopt_id); | 702 converted = new(I) UnboxFloat32x4Instr(to_value, deopt_id); |
710 } else if (to == kUnboxedMint) { | 703 } else if (to == kUnboxedMint) { |
711 converted = new(isolate()) UnboxIntegerInstr(to_value, deopt_id); | 704 converted = new(I) UnboxIntegerInstr(to_value, deopt_id); |
712 } else if (to == kUnboxedFloat64x2) { | 705 } else if (to == kUnboxedFloat64x2) { |
713 converted = new(isolate()) UnboxFloat64x2Instr(to_value, deopt_id); | 706 converted = new(I) UnboxFloat64x2Instr(to_value, deopt_id); |
714 } else { | 707 } else { |
715 UNIMPLEMENTED(); | 708 UNIMPLEMENTED(); |
716 } | 709 } |
717 } | 710 } |
718 ASSERT(converted != NULL); | 711 ASSERT(converted != NULL); |
719 InsertBefore(insert_before, converted, use->instruction()->env(), | 712 InsertBefore(insert_before, converted, use->instruction()->env(), |
720 FlowGraph::kValue); | 713 FlowGraph::kValue); |
721 if (is_environment_use) { | 714 if (is_environment_use) { |
722 use->BindToEnvironment(converted); | 715 use->BindToEnvironment(converted); |
723 } else { | 716 } else { |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
984 call->ReplaceWith(replacement, current_iterator()); | 977 call->ReplaceWith(replacement, current_iterator()); |
985 } | 978 } |
986 | 979 |
987 | 980 |
988 void FlowGraphOptimizer::AddCheckSmi(Definition* to_check, | 981 void FlowGraphOptimizer::AddCheckSmi(Definition* to_check, |
989 intptr_t deopt_id, | 982 intptr_t deopt_id, |
990 Environment* deopt_environment, | 983 Environment* deopt_environment, |
991 Instruction* insert_before) { | 984 Instruction* insert_before) { |
992 if (to_check->Type()->ToCid() != kSmiCid) { | 985 if (to_check->Type()->ToCid() != kSmiCid) { |
993 InsertBefore(insert_before, | 986 InsertBefore(insert_before, |
994 new(isolate()) CheckSmiInstr(new(isolate()) Value(to_check), | 987 new(I) CheckSmiInstr(new(I) Value(to_check), |
995 deopt_id, | 988 deopt_id, |
996 insert_before->token_pos()), | 989 insert_before->token_pos()), |
997 deopt_environment, | 990 deopt_environment, |
998 FlowGraph::kEffect); | 991 FlowGraph::kEffect); |
999 } | 992 } |
1000 } | 993 } |
1001 | 994 |
1002 | 995 |
1003 Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check, | 996 Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check, |
1004 const ICData& unary_checks, | 997 const ICData& unary_checks, |
1005 intptr_t deopt_id, | 998 intptr_t deopt_id, |
1006 intptr_t token_pos) { | 999 intptr_t token_pos) { |
1007 if ((unary_checks.NumberOfChecks() == 1) && | 1000 if ((unary_checks.NumberOfChecks() == 1) && |
1008 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) { | 1001 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) { |
1009 return new(isolate()) CheckSmiInstr(new(isolate()) Value(to_check), | 1002 return new(I) CheckSmiInstr(new(I) Value(to_check), |
1010 deopt_id, | 1003 deopt_id, |
1011 token_pos); | 1004 token_pos); |
1012 } | 1005 } |
1013 return new(isolate()) CheckClassInstr( | 1006 return new(I) CheckClassInstr( |
1014 new(isolate()) Value(to_check), deopt_id, unary_checks, token_pos); | 1007 new(I) Value(to_check), deopt_id, unary_checks, token_pos); |
1015 } | 1008 } |
1016 | 1009 |
1017 | 1010 |
1018 void FlowGraphOptimizer::AddCheckClass(Definition* to_check, | 1011 void FlowGraphOptimizer::AddCheckClass(Definition* to_check, |
1019 const ICData& unary_checks, | 1012 const ICData& unary_checks, |
1020 intptr_t deopt_id, | 1013 intptr_t deopt_id, |
1021 Environment* deopt_environment, | 1014 Environment* deopt_environment, |
1022 Instruction* insert_before) { | 1015 Instruction* insert_before) { |
1023 // Type propagation has not run yet, we cannot eliminate the check. | 1016 // Type propagation has not run yet, we cannot eliminate the check. |
1024 Instruction* check = GetCheckClass( | 1017 Instruction* check = GetCheckClass( |
1025 to_check, unary_checks, deopt_id, insert_before->token_pos()); | 1018 to_check, unary_checks, deopt_id, insert_before->token_pos()); |
1026 InsertBefore(insert_before, check, deopt_environment, FlowGraph::kEffect); | 1019 InsertBefore(insert_before, check, deopt_environment, FlowGraph::kEffect); |
1027 } | 1020 } |
1028 | 1021 |
1029 | 1022 |
1030 void FlowGraphOptimizer::AddReceiverCheck(InstanceCallInstr* call) { | 1023 void FlowGraphOptimizer::AddReceiverCheck(InstanceCallInstr* call) { |
1031 AddCheckClass(call->ArgumentAt(0), | 1024 AddCheckClass(call->ArgumentAt(0), |
1032 ICData::ZoneHandle(isolate(), | 1025 ICData::ZoneHandle(I, call->ic_data()->AsUnaryClassChecks()), |
1033 call->ic_data()->AsUnaryClassChecks()), | |
1034 call->deopt_id(), | 1026 call->deopt_id(), |
1035 call->env(), | 1027 call->env(), |
1036 call); | 1028 call); |
1037 } | 1029 } |
1038 | 1030 |
1039 | 1031 |
1040 static bool ArgIsAlways(intptr_t cid, | 1032 static bool ArgIsAlways(intptr_t cid, |
1041 const ICData& ic_data, | 1033 const ICData& ic_data, |
1042 intptr_t arg_number) { | 1034 intptr_t arg_number) { |
1043 ASSERT(ic_data.NumArgsTested() > arg_number); | 1035 ASSERT(ic_data.NumArgsTested() > arg_number); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 default: | 1121 default: |
1130 break; | 1122 break; |
1131 } | 1123 } |
1132 return kIllegalCid; | 1124 return kIllegalCid; |
1133 } | 1125 } |
1134 | 1126 |
1135 | 1127 |
1136 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { | 1128 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { |
1137 // Check for monomorphic IC data. | 1129 // Check for monomorphic IC data. |
1138 if (!call->HasICData()) return false; | 1130 if (!call->HasICData()) return false; |
1139 const ICData& ic_data = ICData::Handle(isolate(), | 1131 const ICData& ic_data = |
1140 call->ic_data()->AsUnaryClassChecks()); | 1132 ICData::Handle(I, call->ic_data()->AsUnaryClassChecks()); |
1141 if (ic_data.NumberOfChecks() != 1) return false; | 1133 if (ic_data.NumberOfChecks() != 1) return false; |
1142 ASSERT(ic_data.HasOneTarget()); | 1134 ASSERT(ic_data.HasOneTarget()); |
1143 | 1135 |
1144 const Function& target = Function::Handle(isolate(), ic_data.GetTargetAt(0)); | 1136 const Function& target = Function::Handle(I, ic_data.GetTargetAt(0)); |
1145 TargetEntryInstr* entry; | 1137 TargetEntryInstr* entry; |
1146 Definition* last; | 1138 Definition* last; |
1147 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), | 1139 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), |
1148 target, | 1140 target, |
1149 call, | 1141 call, |
1150 call->ArgumentAt(0), | 1142 call->ArgumentAt(0), |
1151 call->token_pos(), | 1143 call->token_pos(), |
1152 *call->ic_data(), | 1144 *call->ic_data(), |
1153 &entry, &last)) { | 1145 &entry, &last)) { |
1154 return false; | 1146 return false; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1187 const ICData& value_check, | 1179 const ICData& value_check, |
1188 TargetEntryInstr** entry, | 1180 TargetEntryInstr** entry, |
1189 Definition** last) { | 1181 Definition** last) { |
1190 intptr_t array_cid = MethodKindToCid(kind); | 1182 intptr_t array_cid = MethodKindToCid(kind); |
1191 ASSERT(array_cid != kIllegalCid); | 1183 ASSERT(array_cid != kIllegalCid); |
1192 | 1184 |
1193 Definition* array = receiver; | 1185 Definition* array = receiver; |
1194 Definition* index = call->ArgumentAt(1); | 1186 Definition* index = call->ArgumentAt(1); |
1195 Definition* stored_value = call->ArgumentAt(2); | 1187 Definition* stored_value = call->ArgumentAt(2); |
1196 | 1188 |
1197 *entry = new(isolate()) TargetEntryInstr(flow_graph()->allocate_block_id(), | 1189 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), |
1198 call->GetBlock()->try_index()); | 1190 call->GetBlock()->try_index()); |
1199 (*entry)->InheritDeoptTarget(isolate(), call); | 1191 (*entry)->InheritDeoptTarget(I, call); |
1200 Instruction* cursor = *entry; | 1192 Instruction* cursor = *entry; |
1201 if (FLAG_enable_type_checks) { | 1193 if (FLAG_enable_type_checks) { |
1202 // Only type check for the value. A type check for the index is not | 1194 // Only type check for the value. A type check for the index is not |
1203 // needed here because we insert a deoptimizing smi-check for the case | 1195 // needed here because we insert a deoptimizing smi-check for the case |
1204 // the index is not a smi. | 1196 // the index is not a smi. |
1205 const AbstractType& value_type = | 1197 const AbstractType& value_type = |
1206 AbstractType::ZoneHandle(isolate(), target.ParameterTypeAt(2)); | 1198 AbstractType::ZoneHandle(I, target.ParameterTypeAt(2)); |
1207 Definition* instantiator = NULL; | 1199 Definition* instantiator = NULL; |
1208 Definition* type_args = NULL; | 1200 Definition* type_args = NULL; |
1209 switch (array_cid) { | 1201 switch (array_cid) { |
1210 case kArrayCid: | 1202 case kArrayCid: |
1211 case kGrowableObjectArrayCid: { | 1203 case kGrowableObjectArrayCid: { |
1212 const Class& instantiator_class = | 1204 const Class& instantiator_class = Class::Handle(I, target.Owner()); |
1213 Class::Handle(isolate(), target.Owner()); | |
1214 intptr_t type_arguments_field_offset = | 1205 intptr_t type_arguments_field_offset = |
1215 instantiator_class.type_arguments_field_offset(); | 1206 instantiator_class.type_arguments_field_offset(); |
1216 LoadFieldInstr* load_type_args = | 1207 LoadFieldInstr* load_type_args = |
1217 new(isolate()) LoadFieldInstr( | 1208 new(I) LoadFieldInstr(new(I) Value(array), |
1218 new(isolate()) Value(array), | 1209 type_arguments_field_offset, |
1219 type_arguments_field_offset, | 1210 Type::ZoneHandle(I), // No type. |
1220 Type::ZoneHandle(isolate(), Type::null()), // No type. | 1211 call->token_pos()); |
1221 call->token_pos()); | |
1222 cursor = flow_graph()->AppendTo(cursor, | 1212 cursor = flow_graph()->AppendTo(cursor, |
1223 load_type_args, | 1213 load_type_args, |
1224 NULL, | 1214 NULL, |
1225 FlowGraph::kValue); | 1215 FlowGraph::kValue); |
1226 | 1216 |
1227 instantiator = array; | 1217 instantiator = array; |
1228 type_args = load_type_args; | 1218 type_args = load_type_args; |
1229 break; | 1219 break; |
1230 } | 1220 } |
1231 case kTypedDataInt8ArrayCid: | 1221 case kTypedDataInt8ArrayCid: |
(...skipping 28 matching lines...) Expand all Loading... |
1260 ASSERT((array_cid != kTypedDataFloat64x2ArrayCid) || | 1250 ASSERT((array_cid != kTypedDataFloat64x2ArrayCid) || |
1261 value_type.IsFloat64x2Type()); | 1251 value_type.IsFloat64x2Type()); |
1262 ASSERT(value_type.IsInstantiated()); | 1252 ASSERT(value_type.IsInstantiated()); |
1263 break; | 1253 break; |
1264 } | 1254 } |
1265 default: | 1255 default: |
1266 // TODO(fschneider): Add support for other array types. | 1256 // TODO(fschneider): Add support for other array types. |
1267 UNREACHABLE(); | 1257 UNREACHABLE(); |
1268 } | 1258 } |
1269 AssertAssignableInstr* assert_value = | 1259 AssertAssignableInstr* assert_value = |
1270 new(isolate()) AssertAssignableInstr(token_pos, | 1260 new(I) AssertAssignableInstr(token_pos, |
1271 new(isolate()) Value(stored_value), | 1261 new(I) Value(stored_value), |
1272 new(isolate()) Value(instantiator), | 1262 new(I) Value(instantiator), |
1273 new(isolate()) Value(type_args), | 1263 new(I) Value(type_args), |
1274 value_type, | 1264 value_type, |
1275 Symbols::Value()); | 1265 Symbols::Value()); |
1276 // Newly inserted instructions that can deoptimize or throw an exception | 1266 // Newly inserted instructions that can deoptimize or throw an exception |
1277 // must have a deoptimization id that is valid for lookup in the unoptimized | 1267 // must have a deoptimization id that is valid for lookup in the unoptimized |
1278 // code. | 1268 // code. |
1279 assert_value->deopt_id_ = call->deopt_id(); | 1269 assert_value->deopt_id_ = call->deopt_id(); |
1280 cursor = flow_graph()->AppendTo(cursor, | 1270 cursor = flow_graph()->AppendTo(cursor, |
1281 assert_value, | 1271 assert_value, |
1282 call->env(), | 1272 call->env(), |
1283 FlowGraph::kValue); | 1273 FlowGraph::kValue); |
1284 } | 1274 } |
1285 | 1275 |
(...skipping 16 matching lines...) Expand all Loading... |
1302 Instruction* check = GetCheckClass( | 1292 Instruction* check = GetCheckClass( |
1303 stored_value, value_check, call->deopt_id(), call->token_pos()); | 1293 stored_value, value_check, call->deopt_id(), call->token_pos()); |
1304 cursor = flow_graph()->AppendTo(cursor, | 1294 cursor = flow_graph()->AppendTo(cursor, |
1305 check, | 1295 check, |
1306 call->env(), | 1296 call->env(), |
1307 FlowGraph::kEffect); | 1297 FlowGraph::kEffect); |
1308 } | 1298 } |
1309 | 1299 |
1310 if (array_cid == kTypedDataFloat32ArrayCid) { | 1300 if (array_cid == kTypedDataFloat32ArrayCid) { |
1311 stored_value = | 1301 stored_value = |
1312 new(isolate()) DoubleToFloatInstr( | 1302 new(I) DoubleToFloatInstr( |
1313 new(isolate()) Value(stored_value), call->deopt_id()); | 1303 new(I) Value(stored_value), call->deopt_id()); |
1314 cursor = flow_graph()->AppendTo(cursor, | 1304 cursor = flow_graph()->AppendTo(cursor, |
1315 stored_value, | 1305 stored_value, |
1316 NULL, | 1306 NULL, |
1317 FlowGraph::kValue); | 1307 FlowGraph::kValue); |
1318 } | 1308 } |
1319 | 1309 |
1320 const intptr_t index_scale = Instance::ElementSizeFor(array_cid); | 1310 const intptr_t index_scale = Instance::ElementSizeFor(array_cid); |
1321 *last = new(isolate()) StoreIndexedInstr(new(isolate()) Value(array), | 1311 *last = new(I) StoreIndexedInstr(new(I) Value(array), |
1322 new(isolate()) Value(index), | 1312 new(I) Value(index), |
1323 new(isolate()) Value(stored_value), | 1313 new(I) Value(stored_value), |
1324 needs_store_barrier, | 1314 needs_store_barrier, |
1325 index_scale, | 1315 index_scale, |
1326 array_cid, | 1316 array_cid, |
1327 call->deopt_id(), | 1317 call->deopt_id(), |
1328 call->token_pos()); | 1318 call->token_pos()); |
1329 flow_graph()->AppendTo(cursor, | 1319 flow_graph()->AppendTo(cursor, |
1330 *last, | 1320 *last, |
1331 call->env(), | 1321 call->env(), |
1332 FlowGraph::kEffect); | 1322 FlowGraph::kEffect); |
1333 return true; | 1323 return true; |
1334 } | 1324 } |
1335 | 1325 |
1336 | 1326 |
1337 bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid, | 1327 bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid, |
1338 const Function& target, | 1328 const Function& target, |
1339 Instruction* call, | 1329 Instruction* call, |
1340 Definition* receiver, | 1330 Definition* receiver, |
1341 intptr_t token_pos, | 1331 intptr_t token_pos, |
1342 const ICData& ic_data, | 1332 const ICData& ic_data, |
1343 TargetEntryInstr** entry, | 1333 TargetEntryInstr** entry, |
1344 Definition** last) { | 1334 Definition** last) { |
1345 ICData& value_check = ICData::ZoneHandle(isolate()); | 1335 ICData& value_check = ICData::ZoneHandle(I); |
1346 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target); | 1336 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target); |
1347 switch (kind) { | 1337 switch (kind) { |
1348 // Recognized [] operators. | 1338 // Recognized [] operators. |
1349 case MethodRecognizer::kImmutableArrayGetIndexed: | 1339 case MethodRecognizer::kImmutableArrayGetIndexed: |
1350 case MethodRecognizer::kObjectArrayGetIndexed: | 1340 case MethodRecognizer::kObjectArrayGetIndexed: |
1351 case MethodRecognizer::kGrowableArrayGetIndexed: | 1341 case MethodRecognizer::kGrowableArrayGetIndexed: |
1352 case MethodRecognizer::kInt8ArrayGetIndexed: | 1342 case MethodRecognizer::kInt8ArrayGetIndexed: |
1353 case MethodRecognizer::kUint8ArrayGetIndexed: | 1343 case MethodRecognizer::kUint8ArrayGetIndexed: |
1354 case MethodRecognizer::kUint8ClampedArrayGetIndexed: | 1344 case MethodRecognizer::kUint8ClampedArrayGetIndexed: |
1355 case MethodRecognizer::kExternalUint8ArrayGetIndexed: | 1345 case MethodRecognizer::kExternalUint8ArrayGetIndexed: |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1573 | 1563 |
1574 | 1564 |
1575 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, | 1565 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, |
1576 intptr_t array_cid, | 1566 intptr_t array_cid, |
1577 Definition** array, | 1567 Definition** array, |
1578 Definition* index, | 1568 Definition* index, |
1579 Instruction** cursor) { | 1569 Instruction** cursor) { |
1580 // Insert index smi check. | 1570 // Insert index smi check. |
1581 *cursor = flow_graph()->AppendTo( | 1571 *cursor = flow_graph()->AppendTo( |
1582 *cursor, | 1572 *cursor, |
1583 new(isolate()) CheckSmiInstr(new(isolate()) Value(index), | 1573 new(I) CheckSmiInstr(new(I) Value(index), |
1584 call->deopt_id(), | 1574 call->deopt_id(), |
1585 call->token_pos()), | 1575 call->token_pos()), |
1586 call->env(), | 1576 call->env(), |
1587 FlowGraph::kEffect); | 1577 FlowGraph::kEffect); |
1588 | 1578 |
1589 // Insert array length load and bounds check. | 1579 // Insert array length load and bounds check. |
1590 LoadFieldInstr* length = | 1580 LoadFieldInstr* length = |
1591 new(isolate()) LoadFieldInstr( | 1581 new(I) LoadFieldInstr( |
1592 new(isolate()) Value(*array), | 1582 new(I) Value(*array), |
1593 CheckArrayBoundInstr::LengthOffsetFor(array_cid), | 1583 CheckArrayBoundInstr::LengthOffsetFor(array_cid), |
1594 Type::ZoneHandle(isolate(), Type::SmiType()), | 1584 Type::ZoneHandle(I, Type::SmiType()), |
1595 call->token_pos()); | 1585 call->token_pos()); |
1596 length->set_is_immutable( | 1586 length->set_is_immutable( |
1597 CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid)); | 1587 CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid)); |
1598 length->set_result_cid(kSmiCid); | 1588 length->set_result_cid(kSmiCid); |
1599 length->set_recognized_kind( | 1589 length->set_recognized_kind( |
1600 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); | 1590 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); |
1601 *cursor = flow_graph()->AppendTo(*cursor, | 1591 *cursor = flow_graph()->AppendTo(*cursor, |
1602 length, | 1592 length, |
1603 NULL, | 1593 NULL, |
1604 FlowGraph::kValue); | 1594 FlowGraph::kValue); |
1605 | 1595 |
1606 *cursor = flow_graph()->AppendTo(*cursor, | 1596 *cursor = flow_graph()->AppendTo(*cursor, |
1607 new(isolate()) CheckArrayBoundInstr( | 1597 new(I) CheckArrayBoundInstr( |
1608 new(isolate()) Value(length), | 1598 new(I) Value(length), |
1609 new(isolate()) Value(index), | 1599 new(I) Value(index), |
1610 call->deopt_id()), | 1600 call->deopt_id()), |
1611 call->env(), | 1601 call->env(), |
1612 FlowGraph::kEffect); | 1602 FlowGraph::kEffect); |
1613 | 1603 |
1614 if (array_cid == kGrowableObjectArrayCid) { | 1604 if (array_cid == kGrowableObjectArrayCid) { |
1615 // Insert data elements load. | 1605 // Insert data elements load. |
1616 LoadFieldInstr* elements = | 1606 LoadFieldInstr* elements = |
1617 new(isolate()) LoadFieldInstr( | 1607 new(I) LoadFieldInstr( |
1618 new(isolate()) Value(*array), | 1608 new(I) Value(*array), |
1619 GrowableObjectArray::data_offset(), | 1609 GrowableObjectArray::data_offset(), |
1620 Type::ZoneHandle(isolate(), Type::DynamicType()), | 1610 Type::ZoneHandle(I, Type::DynamicType()), |
1621 call->token_pos()); | 1611 call->token_pos()); |
1622 elements->set_result_cid(kArrayCid); | 1612 elements->set_result_cid(kArrayCid); |
1623 *cursor = flow_graph()->AppendTo(*cursor, | 1613 *cursor = flow_graph()->AppendTo(*cursor, |
1624 elements, | 1614 elements, |
1625 NULL, | 1615 NULL, |
1626 FlowGraph::kValue); | 1616 FlowGraph::kValue); |
1627 // Load from the data from backing store which is a fixed-length array. | 1617 // Load from the data from backing store which is a fixed-length array. |
1628 *array = elements; | 1618 *array = elements; |
1629 array_cid = kArrayCid; | 1619 array_cid = kArrayCid; |
1630 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { | 1620 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
1631 LoadUntaggedInstr* elements = | 1621 LoadUntaggedInstr* elements = |
1632 new(isolate()) LoadUntaggedInstr(new(isolate()) Value(*array), | 1622 new(I) LoadUntaggedInstr(new(I) Value(*array), |
1633 ExternalTypedData::data_offset()); | 1623 ExternalTypedData::data_offset()); |
1634 *cursor = flow_graph()->AppendTo(*cursor, | 1624 *cursor = flow_graph()->AppendTo(*cursor, |
1635 elements, | 1625 elements, |
1636 NULL, | 1626 NULL, |
1637 FlowGraph::kValue); | 1627 FlowGraph::kValue); |
1638 *array = elements; | 1628 *array = elements; |
1639 } | 1629 } |
1640 return array_cid; | 1630 return array_cid; |
1641 } | 1631 } |
1642 | 1632 |
1643 bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind, | 1633 bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind, |
1644 Instruction* call, | 1634 Instruction* call, |
1645 Definition* receiver, | 1635 Definition* receiver, |
1646 const ICData& ic_data, | 1636 const ICData& ic_data, |
1647 TargetEntryInstr** entry, | 1637 TargetEntryInstr** entry, |
1648 Definition** last) { | 1638 Definition** last) { |
1649 intptr_t array_cid = MethodKindToCid(kind); | 1639 intptr_t array_cid = MethodKindToCid(kind); |
1650 ASSERT(array_cid != kIllegalCid); | 1640 ASSERT(array_cid != kIllegalCid); |
1651 | 1641 |
1652 Definition* array = receiver; | 1642 Definition* array = receiver; |
1653 Definition* index = call->ArgumentAt(1); | 1643 Definition* index = call->ArgumentAt(1); |
1654 *entry = new(isolate()) TargetEntryInstr(flow_graph()->allocate_block_id(), | 1644 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), |
1655 call->GetBlock()->try_index()); | 1645 call->GetBlock()->try_index()); |
1656 (*entry)->InheritDeoptTarget(isolate(), call); | 1646 (*entry)->InheritDeoptTarget(I, call); |
1657 Instruction* cursor = *entry; | 1647 Instruction* cursor = *entry; |
1658 | 1648 |
1659 array_cid = PrepareInlineIndexedOp(call, | 1649 array_cid = PrepareInlineIndexedOp(call, |
1660 array_cid, | 1650 array_cid, |
1661 &array, | 1651 &array, |
1662 index, | 1652 index, |
1663 &cursor); | 1653 &cursor); |
1664 | 1654 |
1665 intptr_t deopt_id = Isolate::kNoDeoptId; | 1655 intptr_t deopt_id = Isolate::kNoDeoptId; |
1666 if ((array_cid == kTypedDataInt32ArrayCid) || | 1656 if ((array_cid == kTypedDataInt32ArrayCid) || |
1667 (array_cid == kTypedDataUint32ArrayCid)) { | 1657 (array_cid == kTypedDataUint32ArrayCid)) { |
1668 // Set deopt_id if we can optimistically assume that the result is Smi. | 1658 // Set deopt_id if we can optimistically assume that the result is Smi. |
1669 // Assume mixed Mint/Smi if this instruction caused deoptimization once. | 1659 // Assume mixed Mint/Smi if this instruction caused deoptimization once. |
1670 deopt_id = ic_data.HasDeoptReasons() ? | 1660 deopt_id = ic_data.HasDeoptReasons() ? |
1671 Isolate::kNoDeoptId : call->deopt_id(); | 1661 Isolate::kNoDeoptId : call->deopt_id(); |
1672 } | 1662 } |
1673 | 1663 |
1674 // Array load and return. | 1664 // Array load and return. |
1675 intptr_t index_scale = Instance::ElementSizeFor(array_cid); | 1665 intptr_t index_scale = Instance::ElementSizeFor(array_cid); |
1676 *last = new(isolate()) LoadIndexedInstr(new(isolate()) Value(array), | 1666 *last = new(I) LoadIndexedInstr(new(I) Value(array), |
1677 new(isolate()) Value(index), | 1667 new(I) Value(index), |
1678 index_scale, | 1668 index_scale, |
1679 array_cid, | 1669 array_cid, |
1680 deopt_id, | 1670 deopt_id, |
1681 call->token_pos()); | 1671 call->token_pos()); |
1682 cursor = flow_graph()->AppendTo( | 1672 cursor = flow_graph()->AppendTo( |
1683 cursor, | 1673 cursor, |
1684 *last, | 1674 *last, |
1685 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 1675 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
1686 FlowGraph::kValue); | 1676 FlowGraph::kValue); |
1687 | 1677 |
1688 if (array_cid == kTypedDataFloat32ArrayCid) { | 1678 if (array_cid == kTypedDataFloat32ArrayCid) { |
1689 *last = new(isolate()) FloatToDoubleInstr( | 1679 *last = new(I) FloatToDoubleInstr(new(I) Value(*last), deopt_id); |
1690 new(isolate()) Value(*last), deopt_id); | |
1691 flow_graph()->AppendTo(cursor, | 1680 flow_graph()->AppendTo(cursor, |
1692 *last, | 1681 *last, |
1693 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 1682 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
1694 FlowGraph::kValue); | 1683 FlowGraph::kValue); |
1695 } | 1684 } |
1696 return true; | 1685 return true; |
1697 } | 1686 } |
1698 | 1687 |
1699 | 1688 |
1700 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { | 1689 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { |
1701 // Check for monomorphic IC data. | 1690 // Check for monomorphic IC data. |
1702 if (!call->HasICData()) return false; | 1691 if (!call->HasICData()) return false; |
1703 const ICData& ic_data = | 1692 const ICData& ic_data = |
1704 ICData::Handle(isolate(), call->ic_data()->AsUnaryClassChecks()); | 1693 ICData::Handle(I, call->ic_data()->AsUnaryClassChecks()); |
1705 if (ic_data.NumberOfChecks() != 1) return false; | 1694 if (ic_data.NumberOfChecks() != 1) return false; |
1706 ASSERT(ic_data.HasOneTarget()); | 1695 ASSERT(ic_data.HasOneTarget()); |
1707 | 1696 |
1708 const Function& target = Function::Handle(isolate(), ic_data.GetTargetAt(0)); | 1697 const Function& target = Function::Handle(I, ic_data.GetTargetAt(0)); |
1709 TargetEntryInstr* entry; | 1698 TargetEntryInstr* entry; |
1710 Definition* last; | 1699 Definition* last; |
1711 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), | 1700 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), |
1712 target, | 1701 target, |
1713 call, | 1702 call, |
1714 call->ArgumentAt(0), | 1703 call->ArgumentAt(0), |
1715 call->token_pos(), | 1704 call->token_pos(), |
1716 *call->ic_data(), | 1705 *call->ic_data(), |
1717 &entry, &last)) { | 1706 &entry, &last)) { |
1718 return false; | 1707 return false; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1778 right = temp; | 1767 right = temp; |
1779 } | 1768 } |
1780 if (IsLengthOneString(left)) { | 1769 if (IsLengthOneString(left)) { |
1781 // Optimize if left is a string with length one (either constant or | 1770 // Optimize if left is a string with length one (either constant or |
1782 // result of string-from-char-code. | 1771 // result of string-from-char-code. |
1783 if (left->IsConstant()) { | 1772 if (left->IsConstant()) { |
1784 ConstantInstr* left_const = left->AsConstant(); | 1773 ConstantInstr* left_const = left->AsConstant(); |
1785 const String& str = String::Cast(left_const->value()); | 1774 const String& str = String::Cast(left_const->value()); |
1786 ASSERT(str.Length() == 1); | 1775 ASSERT(str.Length() == 1); |
1787 ConstantInstr* char_code_left = flow_graph()->GetConstant( | 1776 ConstantInstr* char_code_left = flow_graph()->GetConstant( |
1788 Smi::ZoneHandle(isolate(), Smi::New(str.CharAt(0)))); | 1777 Smi::ZoneHandle(I, Smi::New(str.CharAt(0)))); |
1789 left_val = new(isolate()) Value(char_code_left); | 1778 left_val = new(I) Value(char_code_left); |
1790 } else if (left->IsStringFromCharCode()) { | 1779 } else if (left->IsStringFromCharCode()) { |
1791 // Use input of string-from-charcode as left value. | 1780 // Use input of string-from-charcode as left value. |
1792 StringFromCharCodeInstr* instr = left->AsStringFromCharCode(); | 1781 StringFromCharCodeInstr* instr = left->AsStringFromCharCode(); |
1793 left_val = new(isolate()) Value(instr->char_code()->definition()); | 1782 left_val = new(I) Value(instr->char_code()->definition()); |
1794 to_remove_left = instr; | 1783 to_remove_left = instr; |
1795 } else { | 1784 } else { |
1796 // IsLengthOneString(left) should have been false. | 1785 // IsLengthOneString(left) should have been false. |
1797 UNREACHABLE(); | 1786 UNREACHABLE(); |
1798 } | 1787 } |
1799 | 1788 |
1800 Definition* to_remove_right = NULL; | 1789 Definition* to_remove_right = NULL; |
1801 Value* right_val = NULL; | 1790 Value* right_val = NULL; |
1802 if (right->IsStringFromCharCode()) { | 1791 if (right->IsStringFromCharCode()) { |
1803 // Skip string-from-char-code, and use its input as right value. | 1792 // Skip string-from-char-code, and use its input as right value. |
1804 StringFromCharCodeInstr* right_instr = right->AsStringFromCharCode(); | 1793 StringFromCharCodeInstr* right_instr = right->AsStringFromCharCode(); |
1805 right_val = new(isolate()) Value(right_instr->char_code()->definition()); | 1794 right_val = new(I) Value(right_instr->char_code()->definition()); |
1806 to_remove_right = right_instr; | 1795 to_remove_right = right_instr; |
1807 } else { | 1796 } else { |
1808 const ICData& unary_checks_1 = | 1797 const ICData& unary_checks_1 = |
1809 ICData::ZoneHandle(isolate(), | 1798 ICData::ZoneHandle(I, call->ic_data()->AsUnaryClassChecksForArgNr(1)); |
1810 call->ic_data()->AsUnaryClassChecksForArgNr(1)); | |
1811 AddCheckClass(right, | 1799 AddCheckClass(right, |
1812 unary_checks_1, | 1800 unary_checks_1, |
1813 call->deopt_id(), | 1801 call->deopt_id(), |
1814 call->env(), | 1802 call->env(), |
1815 call); | 1803 call); |
1816 // String-to-char-code instructions returns -1 (illegal charcode) if | 1804 // String-to-char-code instructions returns -1 (illegal charcode) if |
1817 // string is not of length one. | 1805 // string is not of length one. |
1818 StringToCharCodeInstr* char_code_right = | 1806 StringToCharCodeInstr* char_code_right = |
1819 new(isolate()) StringToCharCodeInstr( | 1807 new(I) StringToCharCodeInstr(new(I) Value(right), kOneByteStringCid); |
1820 new(isolate()) Value(right), kOneByteStringCid); | |
1821 InsertBefore(call, char_code_right, call->env(), FlowGraph::kValue); | 1808 InsertBefore(call, char_code_right, call->env(), FlowGraph::kValue); |
1822 right_val = new(isolate()) Value(char_code_right); | 1809 right_val = new(I) Value(char_code_right); |
1823 } | 1810 } |
1824 | 1811 |
1825 // Comparing char-codes instead of strings. | 1812 // Comparing char-codes instead of strings. |
1826 EqualityCompareInstr* comp = | 1813 EqualityCompareInstr* comp = |
1827 new(isolate()) EqualityCompareInstr(call->token_pos(), | 1814 new(I) EqualityCompareInstr(call->token_pos(), |
1828 op_kind, | 1815 op_kind, |
1829 left_val, | 1816 left_val, |
1830 right_val, | 1817 right_val, |
1831 kSmiCid, | 1818 kSmiCid, |
1832 call->deopt_id()); | 1819 call->deopt_id()); |
1833 ReplaceCall(call, comp); | 1820 ReplaceCall(call, comp); |
1834 | 1821 |
1835 // Remove dead instructions. | 1822 // Remove dead instructions. |
1836 if ((to_remove_left != NULL) && | 1823 if ((to_remove_left != NULL) && |
1837 (to_remove_left->input_use_list() == NULL)) { | 1824 (to_remove_left->input_use_list() == NULL)) { |
1838 to_remove_left->ReplaceUsesWith(flow_graph()->constant_null()); | 1825 to_remove_left->ReplaceUsesWith(flow_graph()->constant_null()); |
1839 to_remove_left->RemoveFromGraph(); | 1826 to_remove_left->RemoveFromGraph(); |
1840 } | 1827 } |
1841 if ((to_remove_right != NULL) && | 1828 if ((to_remove_right != NULL) && |
1842 (to_remove_right->input_use_list() == NULL)) { | 1829 (to_remove_right->input_use_list() == NULL)) { |
(...skipping 19 matching lines...) Expand all Loading... |
1862 | 1849 |
1863 intptr_t cid = kIllegalCid; | 1850 intptr_t cid = kIllegalCid; |
1864 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { | 1851 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { |
1865 if (TryStringLengthOneEquality(call, op_kind)) { | 1852 if (TryStringLengthOneEquality(call, op_kind)) { |
1866 return true; | 1853 return true; |
1867 } else { | 1854 } else { |
1868 return false; | 1855 return false; |
1869 } | 1856 } |
1870 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1857 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
1871 InsertBefore(call, | 1858 InsertBefore(call, |
1872 new(isolate()) CheckSmiInstr(new(isolate()) Value(left), | 1859 new(I) CheckSmiInstr(new(I) Value(left), |
1873 call->deopt_id(), | 1860 call->deopt_id(), |
1874 call->token_pos()), | 1861 call->token_pos()), |
1875 call->env(), | 1862 call->env(), |
1876 FlowGraph::kEffect); | 1863 FlowGraph::kEffect); |
1877 InsertBefore(call, | 1864 InsertBefore(call, |
1878 new(isolate()) CheckSmiInstr(new(isolate()) Value(right), | 1865 new(I) CheckSmiInstr(new(I) Value(right), |
1879 call->deopt_id(), | 1866 call->deopt_id(), |
1880 call->token_pos()), | 1867 call->token_pos()), |
1881 call->env(), | 1868 call->env(), |
1882 FlowGraph::kEffect); | 1869 FlowGraph::kEffect); |
1883 cid = kSmiCid; | 1870 cid = kSmiCid; |
1884 } else if (HasTwoMintOrSmi(ic_data) && | 1871 } else if (HasTwoMintOrSmi(ic_data) && |
1885 FlowGraphCompiler::SupportsUnboxedMints()) { | 1872 FlowGraphCompiler::SupportsUnboxedMints()) { |
1886 cid = kMintCid; | 1873 cid = kMintCid; |
1887 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) { | 1874 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) { |
1888 // Use double comparison. | 1875 // Use double comparison. |
1889 if (SmiFitsInDouble()) { | 1876 if (SmiFitsInDouble()) { |
1890 cid = kDoubleCid; | 1877 cid = kDoubleCid; |
1891 } else { | 1878 } else { |
1892 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { | 1879 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { |
1893 // We cannot use double comparison on two smis. Need polymorphic | 1880 // We cannot use double comparison on two smis. Need polymorphic |
1894 // call. | 1881 // call. |
1895 return false; | 1882 return false; |
1896 } else { | 1883 } else { |
1897 InsertBefore(call, | 1884 InsertBefore(call, |
1898 new(isolate()) CheckEitherNonSmiInstr( | 1885 new(I) CheckEitherNonSmiInstr( |
1899 new(isolate()) Value(left), | 1886 new(I) Value(left), |
1900 new(isolate()) Value(right), | 1887 new(I) Value(right), |
1901 call->deopt_id()), | 1888 call->deopt_id()), |
1902 call->env(), | 1889 call->env(), |
1903 FlowGraph::kEffect); | 1890 FlowGraph::kEffect); |
1904 cid = kDoubleCid; | 1891 cid = kDoubleCid; |
1905 } | 1892 } |
1906 } | 1893 } |
1907 } else { | 1894 } else { |
1908 // Check if ICDData contains checks with Smi/Null combinations. In that case | 1895 // Check if ICDData contains checks with Smi/Null combinations. In that case |
1909 // we can still emit the optimized Smi equality operation but need to add | 1896 // we can still emit the optimized Smi equality operation but need to add |
1910 // checks for null or Smi. | 1897 // checks for null or Smi. |
1911 GrowableArray<intptr_t> smi_or_null(2); | 1898 GrowableArray<intptr_t> smi_or_null(2); |
1912 smi_or_null.Add(kSmiCid); | 1899 smi_or_null.Add(kSmiCid); |
1913 smi_or_null.Add(kNullCid); | 1900 smi_or_null.Add(kNullCid); |
1914 if (ICDataHasOnlyReceiverArgumentClassIds(ic_data, | 1901 if (ICDataHasOnlyReceiverArgumentClassIds(ic_data, |
1915 smi_or_null, | 1902 smi_or_null, |
1916 smi_or_null)) { | 1903 smi_or_null)) { |
1917 const ICData& unary_checks_0 = | 1904 const ICData& unary_checks_0 = |
1918 ICData::ZoneHandle(isolate(), | 1905 ICData::ZoneHandle(I, call->ic_data()->AsUnaryClassChecks()); |
1919 call->ic_data()->AsUnaryClassChecks()); | |
1920 AddCheckClass(left, | 1906 AddCheckClass(left, |
1921 unary_checks_0, | 1907 unary_checks_0, |
1922 call->deopt_id(), | 1908 call->deopt_id(), |
1923 call->env(), | 1909 call->env(), |
1924 call); | 1910 call); |
1925 | 1911 |
1926 const ICData& unary_checks_1 = | 1912 const ICData& unary_checks_1 = |
1927 ICData::ZoneHandle(isolate(), | 1913 ICData::ZoneHandle(I, call->ic_data()->AsUnaryClassChecksForArgNr(1)); |
1928 call->ic_data()->AsUnaryClassChecksForArgNr(1)); | |
1929 AddCheckClass(right, | 1914 AddCheckClass(right, |
1930 unary_checks_1, | 1915 unary_checks_1, |
1931 call->deopt_id(), | 1916 call->deopt_id(), |
1932 call->env(), | 1917 call->env(), |
1933 call); | 1918 call); |
1934 cid = kSmiCid; | 1919 cid = kSmiCid; |
1935 } else { | 1920 } else { |
1936 // Shortcut for equality with null. | 1921 // Shortcut for equality with null. |
1937 ConstantInstr* right_const = right->AsConstant(); | 1922 ConstantInstr* right_const = right->AsConstant(); |
1938 ConstantInstr* left_const = left->AsConstant(); | 1923 ConstantInstr* left_const = left->AsConstant(); |
1939 if ((right_const != NULL && right_const->value().IsNull()) || | 1924 if ((right_const != NULL && right_const->value().IsNull()) || |
1940 (left_const != NULL && left_const->value().IsNull())) { | 1925 (left_const != NULL && left_const->value().IsNull())) { |
1941 StrictCompareInstr* comp = | 1926 StrictCompareInstr* comp = |
1942 new(isolate()) StrictCompareInstr(call->token_pos(), | 1927 new(I) StrictCompareInstr(call->token_pos(), |
1943 Token::kEQ_STRICT, | 1928 Token::kEQ_STRICT, |
1944 new(isolate()) Value(left), | 1929 new(I) Value(left), |
1945 new(isolate()) Value(right), | 1930 new(I) Value(right), |
1946 false); // No number check. | 1931 false); // No number check. |
1947 ReplaceCall(call, comp); | 1932 ReplaceCall(call, comp); |
1948 return true; | 1933 return true; |
1949 } | 1934 } |
1950 return false; | 1935 return false; |
1951 } | 1936 } |
1952 } | 1937 } |
1953 ASSERT(cid != kIllegalCid); | 1938 ASSERT(cid != kIllegalCid); |
1954 EqualityCompareInstr* comp = new(isolate()) EqualityCompareInstr( | 1939 EqualityCompareInstr* comp = new(I) EqualityCompareInstr(call->token_pos(), |
1955 call->token_pos(), | 1940 op_kind, |
1956 op_kind, | 1941 new(I) Value(left), |
1957 new(isolate()) Value(left), | 1942 new(I) Value(right), |
1958 new(isolate()) Value(right), | 1943 cid, |
1959 cid, | 1944 call->deopt_id()); |
1960 call->deopt_id()); | |
1961 ReplaceCall(call, comp); | 1945 ReplaceCall(call, comp); |
1962 return true; | 1946 return true; |
1963 } | 1947 } |
1964 | 1948 |
1965 | 1949 |
1966 bool FlowGraphOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call, | 1950 bool FlowGraphOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call, |
1967 Token::Kind op_kind) { | 1951 Token::Kind op_kind) { |
1968 const ICData& ic_data = *call->ic_data(); | 1952 const ICData& ic_data = *call->ic_data(); |
1969 ASSERT(ic_data.NumArgsTested() == 2); | 1953 ASSERT(ic_data.NumArgsTested() == 2); |
1970 | 1954 |
1971 ASSERT(call->ArgumentCount() == 2); | 1955 ASSERT(call->ArgumentCount() == 2); |
1972 Definition* left = call->ArgumentAt(0); | 1956 Definition* left = call->ArgumentAt(0); |
1973 Definition* right = call->ArgumentAt(1); | 1957 Definition* right = call->ArgumentAt(1); |
1974 | 1958 |
1975 intptr_t cid = kIllegalCid; | 1959 intptr_t cid = kIllegalCid; |
1976 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1960 if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
1977 InsertBefore(call, | 1961 InsertBefore(call, |
1978 new(isolate()) CheckSmiInstr(new(isolate()) Value(left), | 1962 new(I) CheckSmiInstr(new(I) Value(left), |
1979 call->deopt_id(), | 1963 call->deopt_id(), |
1980 call->token_pos()), | 1964 call->token_pos()), |
1981 call->env(), | 1965 call->env(), |
1982 FlowGraph::kEffect); | 1966 FlowGraph::kEffect); |
1983 InsertBefore(call, | 1967 InsertBefore(call, |
1984 new(isolate()) CheckSmiInstr(new(isolate()) Value(right), | 1968 new(I) CheckSmiInstr(new(I) Value(right), |
1985 call->deopt_id(), | 1969 call->deopt_id(), |
1986 call->token_pos()), | 1970 call->token_pos()), |
1987 call->env(), | 1971 call->env(), |
1988 FlowGraph::kEffect); | 1972 FlowGraph::kEffect); |
1989 cid = kSmiCid; | 1973 cid = kSmiCid; |
1990 } else if (HasTwoMintOrSmi(ic_data) && | 1974 } else if (HasTwoMintOrSmi(ic_data) && |
1991 FlowGraphCompiler::SupportsUnboxedMints()) { | 1975 FlowGraphCompiler::SupportsUnboxedMints()) { |
1992 cid = kMintCid; | 1976 cid = kMintCid; |
1993 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) { | 1977 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) { |
1994 // Use double comparison. | 1978 // Use double comparison. |
1995 if (SmiFitsInDouble()) { | 1979 if (SmiFitsInDouble()) { |
1996 cid = kDoubleCid; | 1980 cid = kDoubleCid; |
1997 } else { | 1981 } else { |
1998 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { | 1982 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { |
1999 // We cannot use double comparison on two smis. Need polymorphic | 1983 // We cannot use double comparison on two smis. Need polymorphic |
2000 // call. | 1984 // call. |
2001 return false; | 1985 return false; |
2002 } else { | 1986 } else { |
2003 InsertBefore(call, | 1987 InsertBefore(call, |
2004 new(isolate()) CheckEitherNonSmiInstr( | 1988 new(I) CheckEitherNonSmiInstr( |
2005 new(isolate()) Value(left), | 1989 new(I) Value(left), |
2006 new(isolate()) Value(right), | 1990 new(I) Value(right), |
2007 call->deopt_id()), | 1991 call->deopt_id()), |
2008 call->env(), | 1992 call->env(), |
2009 FlowGraph::kEffect); | 1993 FlowGraph::kEffect); |
2010 cid = kDoubleCid; | 1994 cid = kDoubleCid; |
2011 } | 1995 } |
2012 } | 1996 } |
2013 } else { | 1997 } else { |
2014 return false; | 1998 return false; |
2015 } | 1999 } |
2016 ASSERT(cid != kIllegalCid); | 2000 ASSERT(cid != kIllegalCid); |
2017 RelationalOpInstr* comp = new(isolate()) RelationalOpInstr( | 2001 RelationalOpInstr* comp = new(I) RelationalOpInstr(call->token_pos(), |
2018 call->token_pos(), | 2002 op_kind, |
2019 op_kind, | 2003 new(I) Value(left), |
2020 new(isolate()) Value(left), | 2004 new(I) Value(right), |
2021 new(isolate()) Value(right), | 2005 cid, |
2022 cid, | 2006 call->deopt_id()); |
2023 call->deopt_id()); | |
2024 ReplaceCall(call, comp); | 2007 ReplaceCall(call, comp); |
2025 return true; | 2008 return true; |
2026 } | 2009 } |
2027 | 2010 |
2028 | 2011 |
2029 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, | 2012 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, |
2030 Token::Kind op_kind) { | 2013 Token::Kind op_kind) { |
2031 intptr_t operands_type = kIllegalCid; | 2014 intptr_t operands_type = kIllegalCid; |
2032 ASSERT(call->HasICData()); | 2015 ASSERT(call->HasICData()); |
2033 const ICData& ic_data = *call->ic_data(); | 2016 const ICData& ic_data = *call->ic_data(); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2106 // Left shift may overflow from smi into mint or big ints. | 2089 // Left shift may overflow from smi into mint or big ints. |
2107 // Don't generate smi code if the IC data is marked because | 2090 // Don't generate smi code if the IC data is marked because |
2108 // of an overflow. | 2091 // of an overflow. |
2109 if (ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { | 2092 if (ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { |
2110 return false; | 2093 return false; |
2111 } | 2094 } |
2112 operands_type = ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp) | 2095 operands_type = ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp) |
2113 ? kMintCid | 2096 ? kMintCid |
2114 : kSmiCid; | 2097 : kSmiCid; |
2115 } else if (HasTwoMintOrSmi(ic_data) && | 2098 } else if (HasTwoMintOrSmi(ic_data) && |
2116 HasOnlyOneSmi(ICData::Handle(isolate(), | 2099 HasOnlyOneSmi(ICData::Handle(I, |
2117 ic_data.AsUnaryClassChecksForArgNr(1)))) { | 2100 ic_data.AsUnaryClassChecksForArgNr(1)))) { |
2118 // Don't generate mint code if the IC data is marked because of an | 2101 // Don't generate mint code if the IC data is marked because of an |
2119 // overflow. | 2102 // overflow. |
2120 if (ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { | 2103 if (ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { |
2121 return false; | 2104 return false; |
2122 } | 2105 } |
2123 // Check for smi/mint << smi or smi/mint >> smi. | 2106 // Check for smi/mint << smi or smi/mint >> smi. |
2124 operands_type = kMintCid; | 2107 operands_type = kMintCid; |
2125 } else { | 2108 } else { |
2126 return false; | 2109 return false; |
(...skipping 19 matching lines...) Expand all Loading... |
2146 Definition* right = call->ArgumentAt(1); | 2129 Definition* right = call->ArgumentAt(1); |
2147 if (operands_type == kDoubleCid) { | 2130 if (operands_type == kDoubleCid) { |
2148 if (!CanUnboxDouble()) { | 2131 if (!CanUnboxDouble()) { |
2149 return false; | 2132 return false; |
2150 } | 2133 } |
2151 // Check that either left or right are not a smi. Result of a | 2134 // Check that either left or right are not a smi. Result of a |
2152 // binary operation with two smis is a smi not a double, except '/' which | 2135 // binary operation with two smis is a smi not a double, except '/' which |
2153 // returns a double for two smis. | 2136 // returns a double for two smis. |
2154 if (op_kind != Token::kDIV) { | 2137 if (op_kind != Token::kDIV) { |
2155 InsertBefore(call, | 2138 InsertBefore(call, |
2156 new(isolate()) CheckEitherNonSmiInstr( | 2139 new(I) CheckEitherNonSmiInstr( |
2157 new(isolate()) Value(left), | 2140 new(I) Value(left), |
2158 new(isolate()) Value(right), | 2141 new(I) Value(right), |
2159 call->deopt_id()), | 2142 call->deopt_id()), |
2160 call->env(), | 2143 call->env(), |
2161 FlowGraph::kEffect); | 2144 FlowGraph::kEffect); |
2162 } | 2145 } |
2163 | 2146 |
2164 BinaryDoubleOpInstr* double_bin_op = | 2147 BinaryDoubleOpInstr* double_bin_op = |
2165 new(isolate()) BinaryDoubleOpInstr(op_kind, | 2148 new(I) BinaryDoubleOpInstr(op_kind, |
2166 new(isolate()) Value(left), | 2149 new(I) Value(left), |
2167 new(isolate()) Value(right), | 2150 new(I) Value(right), |
2168 call->deopt_id(), call->token_pos()); | 2151 call->deopt_id(), call->token_pos()); |
2169 ReplaceCall(call, double_bin_op); | 2152 ReplaceCall(call, double_bin_op); |
2170 } else if (operands_type == kMintCid) { | 2153 } else if (operands_type == kMintCid) { |
2171 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; | 2154 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; |
2172 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { | 2155 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { |
2173 ShiftMintOpInstr* shift_op = | 2156 ShiftMintOpInstr* shift_op = |
2174 new(isolate()) ShiftMintOpInstr( | 2157 new(I) ShiftMintOpInstr( |
2175 op_kind, new(isolate()) Value(left), new(isolate()) Value(right), | 2158 op_kind, new(I) Value(left), new(I) Value(right), |
2176 call->deopt_id()); | 2159 call->deopt_id()); |
2177 ReplaceCall(call, shift_op); | 2160 ReplaceCall(call, shift_op); |
2178 } else { | 2161 } else { |
2179 BinaryMintOpInstr* bin_op = | 2162 BinaryMintOpInstr* bin_op = |
2180 new(isolate()) BinaryMintOpInstr( | 2163 new(I) BinaryMintOpInstr( |
2181 op_kind, new(isolate()) Value(left), new(isolate()) Value(right), | 2164 op_kind, new(I) Value(left), new(I) Value(right), |
2182 call->deopt_id()); | 2165 call->deopt_id()); |
2183 ReplaceCall(call, bin_op); | 2166 ReplaceCall(call, bin_op); |
2184 } | 2167 } |
2185 } else if (operands_type == kFloat32x4Cid) { | 2168 } else if (operands_type == kFloat32x4Cid) { |
2186 return InlineFloat32x4BinaryOp(call, op_kind); | 2169 return InlineFloat32x4BinaryOp(call, op_kind); |
2187 } else if (operands_type == kInt32x4Cid) { | 2170 } else if (operands_type == kInt32x4Cid) { |
2188 return InlineInt32x4BinaryOp(call, op_kind); | 2171 return InlineInt32x4BinaryOp(call, op_kind); |
2189 } else if (operands_type == kFloat64x2Cid) { | 2172 } else if (operands_type == kFloat64x2Cid) { |
2190 return InlineFloat64x2BinaryOp(call, op_kind); | 2173 return InlineFloat64x2BinaryOp(call, op_kind); |
2191 } else if (op_kind == Token::kMOD) { | 2174 } else if (op_kind == Token::kMOD) { |
2192 ASSERT(operands_type == kSmiCid); | 2175 ASSERT(operands_type == kSmiCid); |
2193 if (right->IsConstant()) { | 2176 if (right->IsConstant()) { |
2194 const Object& obj = right->AsConstant()->value(); | 2177 const Object& obj = right->AsConstant()->value(); |
2195 if (obj.IsSmi() && Utils::IsPowerOfTwo(Smi::Cast(obj).Value())) { | 2178 if (obj.IsSmi() && Utils::IsPowerOfTwo(Smi::Cast(obj).Value())) { |
2196 // Insert smi check and attach a copy of the original environment | 2179 // Insert smi check and attach a copy of the original environment |
2197 // because the smi operation can still deoptimize. | 2180 // because the smi operation can still deoptimize. |
2198 InsertBefore(call, | 2181 InsertBefore(call, |
2199 new(isolate()) CheckSmiInstr(new(isolate()) Value(left), | 2182 new(I) CheckSmiInstr(new(I) Value(left), |
2200 call->deopt_id(), | 2183 call->deopt_id(), |
2201 call->token_pos()), | 2184 call->token_pos()), |
2202 call->env(), | 2185 call->env(), |
2203 FlowGraph::kEffect); | 2186 FlowGraph::kEffect); |
2204 ConstantInstr* constant = | 2187 ConstantInstr* constant = |
2205 flow_graph()->GetConstant(Smi::Handle(isolate(), | 2188 flow_graph()->GetConstant(Smi::Handle(I, |
2206 Smi::New(Smi::Cast(obj).Value() - 1))); | 2189 Smi::New(Smi::Cast(obj).Value() - 1))); |
2207 BinarySmiOpInstr* bin_op = | 2190 BinarySmiOpInstr* bin_op = |
2208 new(isolate()) BinarySmiOpInstr(Token::kBIT_AND, | 2191 new(I) BinarySmiOpInstr(Token::kBIT_AND, |
2209 new(isolate()) Value(left), | 2192 new(I) Value(left), |
2210 new(isolate()) Value(constant), | 2193 new(I) Value(constant), |
2211 call->deopt_id(), | 2194 call->deopt_id(), |
2212 call->token_pos()); | 2195 call->token_pos()); |
2213 ReplaceCall(call, bin_op); | 2196 ReplaceCall(call, bin_op); |
2214 return true; | 2197 return true; |
2215 } | 2198 } |
2216 } | 2199 } |
2217 // Insert two smi checks and attach a copy of the original | 2200 // Insert two smi checks and attach a copy of the original |
2218 // environment because the smi operation can still deoptimize. | 2201 // environment because the smi operation can still deoptimize. |
2219 AddCheckSmi(left, call->deopt_id(), call->env(), call); | 2202 AddCheckSmi(left, call->deopt_id(), call->env(), call); |
2220 AddCheckSmi(right, call->deopt_id(), call->env(), call); | 2203 AddCheckSmi(right, call->deopt_id(), call->env(), call); |
2221 BinarySmiOpInstr* bin_op = | 2204 BinarySmiOpInstr* bin_op = |
2222 new(isolate()) BinarySmiOpInstr(op_kind, | 2205 new(I) BinarySmiOpInstr(op_kind, |
2223 new(isolate()) Value(left), | 2206 new(I) Value(left), |
2224 new(isolate()) Value(right), | 2207 new(I) Value(right), |
2225 call->deopt_id(), call->token_pos()); | 2208 call->deopt_id(), call->token_pos()); |
2226 ReplaceCall(call, bin_op); | 2209 ReplaceCall(call, bin_op); |
2227 } else { | 2210 } else { |
2228 ASSERT(operands_type == kSmiCid); | 2211 ASSERT(operands_type == kSmiCid); |
2229 // Insert two smi checks and attach a copy of the original | 2212 // Insert two smi checks and attach a copy of the original |
2230 // environment because the smi operation can still deoptimize. | 2213 // environment because the smi operation can still deoptimize. |
2231 AddCheckSmi(left, call->deopt_id(), call->env(), call); | 2214 AddCheckSmi(left, call->deopt_id(), call->env(), call); |
2232 AddCheckSmi(right, call->deopt_id(), call->env(), call); | 2215 AddCheckSmi(right, call->deopt_id(), call->env(), call); |
2233 if (left->IsConstant() && | 2216 if (left->IsConstant() && |
2234 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { | 2217 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { |
2235 // Constant should be on the right side. | 2218 // Constant should be on the right side. |
2236 Definition* temp = left; | 2219 Definition* temp = left; |
2237 left = right; | 2220 left = right; |
2238 right = temp; | 2221 right = temp; |
2239 } | 2222 } |
2240 BinarySmiOpInstr* bin_op = | 2223 BinarySmiOpInstr* bin_op = |
2241 new(isolate()) BinarySmiOpInstr( | 2224 new(I) BinarySmiOpInstr( |
2242 op_kind, new(isolate()) Value(left), new(isolate()) Value(right), | 2225 op_kind, new(I) Value(left), new(I) Value(right), |
2243 call->deopt_id(), call->token_pos()); | 2226 call->deopt_id(), call->token_pos()); |
2244 ReplaceCall(call, bin_op); | 2227 ReplaceCall(call, bin_op); |
2245 } | 2228 } |
2246 return true; | 2229 return true; |
2247 } | 2230 } |
2248 | 2231 |
2249 | 2232 |
2250 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, | 2233 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, |
2251 Token::Kind op_kind) { | 2234 Token::Kind op_kind) { |
2252 ASSERT(call->ArgumentCount() == 1); | 2235 ASSERT(call->ArgumentCount() == 1); |
2253 Definition* input = call->ArgumentAt(0); | 2236 Definition* input = call->ArgumentAt(0); |
2254 Definition* unary_op = NULL; | 2237 Definition* unary_op = NULL; |
2255 if (HasOnlyOneSmi(*call->ic_data())) { | 2238 if (HasOnlyOneSmi(*call->ic_data())) { |
2256 InsertBefore(call, | 2239 InsertBefore(call, |
2257 new(isolate()) CheckSmiInstr(new(isolate()) Value(input), | 2240 new(I) CheckSmiInstr(new(I) Value(input), |
2258 call->deopt_id(), | 2241 call->deopt_id(), |
2259 call->token_pos()), | 2242 call->token_pos()), |
2260 call->env(), | 2243 call->env(), |
2261 FlowGraph::kEffect); | 2244 FlowGraph::kEffect); |
2262 unary_op = new(isolate()) UnarySmiOpInstr( | 2245 unary_op = new(I) UnarySmiOpInstr( |
2263 op_kind, new(isolate()) Value(input), call->deopt_id()); | 2246 op_kind, new(I) Value(input), call->deopt_id()); |
2264 } else if ((op_kind == Token::kBIT_NOT) && | 2247 } else if ((op_kind == Token::kBIT_NOT) && |
2265 HasOnlySmiOrMint(*call->ic_data()) && | 2248 HasOnlySmiOrMint(*call->ic_data()) && |
2266 FlowGraphCompiler::SupportsUnboxedMints()) { | 2249 FlowGraphCompiler::SupportsUnboxedMints()) { |
2267 unary_op = new(isolate()) UnaryMintOpInstr( | 2250 unary_op = new(I) UnaryMintOpInstr( |
2268 op_kind, new(isolate()) Value(input), call->deopt_id()); | 2251 op_kind, new(I) Value(input), call->deopt_id()); |
2269 } else if (HasOnlyOneDouble(*call->ic_data()) && | 2252 } else if (HasOnlyOneDouble(*call->ic_data()) && |
2270 (op_kind == Token::kNEGATE) && | 2253 (op_kind == Token::kNEGATE) && |
2271 CanUnboxDouble()) { | 2254 CanUnboxDouble()) { |
2272 AddReceiverCheck(call); | 2255 AddReceiverCheck(call); |
2273 unary_op = new(isolate()) UnaryDoubleOpInstr( | 2256 unary_op = new(I) UnaryDoubleOpInstr( |
2274 Token::kNEGATE, new(isolate()) Value(input), call->deopt_id()); | 2257 Token::kNEGATE, new(I) Value(input), call->deopt_id()); |
2275 } else { | 2258 } else { |
2276 return false; | 2259 return false; |
2277 } | 2260 } |
2278 ASSERT(unary_op != NULL); | 2261 ASSERT(unary_op != NULL); |
2279 ReplaceCall(call, unary_op); | 2262 ReplaceCall(call, unary_op); |
2280 return true; | 2263 return true; |
2281 } | 2264 } |
2282 | 2265 |
2283 | 2266 |
2284 // Using field class | 2267 // Using field class |
2285 static RawField* GetField(intptr_t class_id, const String& field_name) { | 2268 static RawField* GetField(intptr_t class_id, const String& field_name) { |
2286 Class& cls = Class::Handle(Isolate::Current()->class_table()->At(class_id)); | 2269 Isolate* isolate = Isolate::Current(); |
2287 Field& field = Field::Handle(); | 2270 Class& cls = Class::Handle(isolate, isolate->class_table()->At(class_id)); |
| 2271 Field& field = Field::Handle(isolate); |
2288 while (!cls.IsNull()) { | 2272 while (!cls.IsNull()) { |
2289 field = cls.LookupInstanceField(field_name); | 2273 field = cls.LookupInstanceField(field_name); |
2290 if (!field.IsNull()) { | 2274 if (!field.IsNull()) { |
2291 return field.raw(); | 2275 return field.raw(); |
2292 } | 2276 } |
2293 cls = cls.SuperClass(); | 2277 cls = cls.SuperClass(); |
2294 } | 2278 } |
2295 return Field::null(); | 2279 return Field::null(); |
2296 } | 2280 } |
2297 | 2281 |
2298 | 2282 |
2299 // Use CHA to determine if the call needs a class check: if the callee's | 2283 // Use CHA to determine if the call needs a class check: if the callee's |
2300 // receiver is the same as the caller's receiver and there are no overriden | 2284 // receiver is the same as the caller's receiver and there are no overriden |
2301 // callee functions, then no class check is needed. | 2285 // callee functions, then no class check is needed. |
2302 bool FlowGraphOptimizer::InstanceCallNeedsClassCheck( | 2286 bool FlowGraphOptimizer::InstanceCallNeedsClassCheck( |
2303 InstanceCallInstr* call) const { | 2287 InstanceCallInstr* call) const { |
2304 if (!FLAG_use_cha) return true; | 2288 if (!FLAG_use_cha) return true; |
2305 Definition* callee_receiver = call->ArgumentAt(0); | 2289 Definition* callee_receiver = call->ArgumentAt(0); |
2306 ASSERT(callee_receiver != NULL); | 2290 ASSERT(callee_receiver != NULL); |
2307 const Function& function = flow_graph_->parsed_function().function(); | 2291 const Function& function = flow_graph_->parsed_function().function(); |
2308 if (function.IsDynamicFunction() && | 2292 if (function.IsDynamicFunction() && |
2309 callee_receiver->IsParameter() && | 2293 callee_receiver->IsParameter() && |
2310 (callee_receiver->AsParameter()->index() == 0)) { | 2294 (callee_receiver->AsParameter()->index() == 0)) { |
2311 return CHA::HasOverride(Class::Handle(isolate(), function.Owner()), | 2295 return CHA::HasOverride(Class::Handle(I, function.Owner()), |
2312 call->function_name()); | 2296 call->function_name()); |
2313 } | 2297 } |
2314 return true; | 2298 return true; |
2315 } | 2299 } |
2316 | 2300 |
2317 | 2301 |
2318 bool FlowGraphOptimizer::MethodExtractorNeedsClassCheck( | 2302 bool FlowGraphOptimizer::MethodExtractorNeedsClassCheck( |
2319 InstanceCallInstr* call) const { | 2303 InstanceCallInstr* call) const { |
2320 if (!FLAG_use_cha) return true; | 2304 if (!FLAG_use_cha) return true; |
2321 Definition* callee_receiver = call->ArgumentAt(0); | 2305 Definition* callee_receiver = call->ArgumentAt(0); |
2322 ASSERT(callee_receiver != NULL); | 2306 ASSERT(callee_receiver != NULL); |
2323 const Function& function = flow_graph_->parsed_function().function(); | 2307 const Function& function = flow_graph_->parsed_function().function(); |
2324 if (function.IsDynamicFunction() && | 2308 if (function.IsDynamicFunction() && |
2325 callee_receiver->IsParameter() && | 2309 callee_receiver->IsParameter() && |
2326 (callee_receiver->AsParameter()->index() == 0)) { | 2310 (callee_receiver->AsParameter()->index() == 0)) { |
2327 const String& field_name = | 2311 const String& field_name = |
2328 String::Handle(isolate(), Field::NameFromGetter(call->function_name())); | 2312 String::Handle(I, Field::NameFromGetter(call->function_name())); |
2329 return CHA::HasOverride(Class::Handle(isolate(), function.Owner()), | 2313 return CHA::HasOverride(Class::Handle(I, function.Owner()), field_name); |
2330 field_name); | |
2331 } | 2314 } |
2332 return true; | 2315 return true; |
2333 } | 2316 } |
2334 | 2317 |
2335 | 2318 |
2336 void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { | 2319 void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { |
2337 ASSERT(call->HasICData()); | 2320 ASSERT(call->HasICData()); |
2338 const ICData& ic_data = *call->ic_data(); | 2321 const ICData& ic_data = *call->ic_data(); |
2339 ASSERT(ic_data.HasOneTarget()); | 2322 ASSERT(ic_data.HasOneTarget()); |
2340 Function& target = Function::Handle(isolate(), Function::null()); | 2323 Function& target = Function::Handle(I); |
2341 GrowableArray<intptr_t> class_ids; | 2324 GrowableArray<intptr_t> class_ids; |
2342 ic_data.GetCheckAt(0, &class_ids, &target); | 2325 ic_data.GetCheckAt(0, &class_ids, &target); |
2343 ASSERT(class_ids.length() == 1); | 2326 ASSERT(class_ids.length() == 1); |
2344 // Inline implicit instance getter. | 2327 // Inline implicit instance getter. |
2345 const String& field_name = | 2328 const String& field_name = |
2346 String::Handle(isolate(), Field::NameFromGetter(call->function_name())); | 2329 String::Handle(I, Field::NameFromGetter(call->function_name())); |
2347 const Field& field = | 2330 const Field& field = |
2348 Field::ZoneHandle(isolate(), GetField(class_ids[0], field_name)); | 2331 Field::ZoneHandle(I, GetField(class_ids[0], field_name)); |
2349 ASSERT(!field.IsNull()); | 2332 ASSERT(!field.IsNull()); |
2350 | 2333 |
2351 if (InstanceCallNeedsClassCheck(call)) { | 2334 if (InstanceCallNeedsClassCheck(call)) { |
2352 AddReceiverCheck(call); | 2335 AddReceiverCheck(call); |
2353 } | 2336 } |
2354 LoadFieldInstr* load = new(isolate()) LoadFieldInstr( | 2337 LoadFieldInstr* load = new(I) LoadFieldInstr( |
2355 new(isolate()) Value(call->ArgumentAt(0)), | 2338 new(I) Value(call->ArgumentAt(0)), |
2356 &field, | 2339 &field, |
2357 AbstractType::ZoneHandle(isolate(), field.type()), | 2340 AbstractType::ZoneHandle(I, field.type()), |
2358 call->token_pos()); | 2341 call->token_pos()); |
2359 load->set_is_immutable(field.is_final()); | 2342 load->set_is_immutable(field.is_final()); |
2360 if (field.guarded_cid() != kIllegalCid) { | 2343 if (field.guarded_cid() != kIllegalCid) { |
2361 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { | 2344 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { |
2362 load->set_result_cid(field.guarded_cid()); | 2345 load->set_result_cid(field.guarded_cid()); |
2363 } | 2346 } |
2364 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | 2347 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
2365 } | 2348 } |
2366 | 2349 |
2367 // Discard the environment from the original instruction because the load | 2350 // Discard the environment from the original instruction because the load |
2368 // can't deoptimize. | 2351 // can't deoptimize. |
2369 call->RemoveEnvironment(); | 2352 call->RemoveEnvironment(); |
2370 ReplaceCall(call, load); | 2353 ReplaceCall(call, load); |
2371 | 2354 |
2372 if (load->result_cid() != kDynamicCid) { | 2355 if (load->result_cid() != kDynamicCid) { |
2373 // Reset value types if guarded_cid was used. | 2356 // Reset value types if guarded_cid was used. |
2374 for (Value::Iterator it(load->input_use_list()); | 2357 for (Value::Iterator it(load->input_use_list()); |
2375 !it.Done(); | 2358 !it.Done(); |
2376 it.Advance()) { | 2359 it.Advance()) { |
2377 it.Current()->SetReachingType(NULL); | 2360 it.Current()->SetReachingType(NULL); |
2378 } | 2361 } |
2379 } | 2362 } |
2380 } | 2363 } |
2381 | 2364 |
2382 | 2365 |
2383 LoadFieldInstr* FlowGraphOptimizer::BuildLoadStringLength(Definition* str) { | 2366 LoadFieldInstr* FlowGraphOptimizer::BuildLoadStringLength(Definition* str) { |
2384 // Treat length loads as mutable (i.e. affected by side effects) to avoid | 2367 // Treat length loads as mutable (i.e. affected by side effects) to avoid |
2385 // hoisting them since we can't hoist the preceding class-check. This | 2368 // hoisting them since we can't hoist the preceding class-check. This |
2386 // is because of externalization of strings that affects their class-id. | 2369 // is because of externalization of strings that affects their class-id. |
2387 LoadFieldInstr* load = new(isolate()) LoadFieldInstr( | 2370 LoadFieldInstr* load = new(I) LoadFieldInstr( |
2388 new(isolate()) Value(str), | 2371 new(I) Value(str), |
2389 String::length_offset(), | 2372 String::length_offset(), |
2390 Type::ZoneHandle(isolate(), Type::SmiType()), | 2373 Type::ZoneHandle(I, Type::SmiType()), |
2391 str->token_pos()); | 2374 str->token_pos()); |
2392 load->set_result_cid(kSmiCid); | 2375 load->set_result_cid(kSmiCid); |
2393 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); | 2376 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); |
2394 return load; | 2377 return load; |
2395 } | 2378 } |
2396 | 2379 |
2397 | 2380 |
2398 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, | 2381 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, |
2399 MethodRecognizer::Kind getter) { | 2382 MethodRecognizer::Kind getter) { |
2400 if (!ShouldInlineSimd()) { | 2383 if (!ShouldInlineSimd()) { |
2401 return false; | 2384 return false; |
2402 } | 2385 } |
2403 AddCheckClass(call->ArgumentAt(0), | 2386 AddCheckClass(call->ArgumentAt(0), |
2404 ICData::ZoneHandle( | 2387 ICData::ZoneHandle( |
2405 isolate(), call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 2388 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
2406 call->deopt_id(), | 2389 call->deopt_id(), |
2407 call->env(), | 2390 call->env(), |
2408 call); | 2391 call); |
2409 intptr_t mask = 0; | 2392 intptr_t mask = 0; |
2410 if ((getter == MethodRecognizer::kFloat32x4Shuffle) || | 2393 if ((getter == MethodRecognizer::kFloat32x4Shuffle) || |
2411 (getter == MethodRecognizer::kFloat32x4ShuffleMix)) { | 2394 (getter == MethodRecognizer::kFloat32x4ShuffleMix)) { |
2412 // Extract shuffle mask. | 2395 // Extract shuffle mask. |
2413 Definition* mask_definition = NULL; | 2396 Definition* mask_definition = NULL; |
2414 if (getter == MethodRecognizer::kFloat32x4Shuffle) { | 2397 if (getter == MethodRecognizer::kFloat32x4Shuffle) { |
2415 ASSERT(call->ArgumentCount() == 2); | 2398 ASSERT(call->ArgumentCount() == 2); |
(...skipping 13 matching lines...) Expand all Loading... |
2429 return false; | 2412 return false; |
2430 } | 2413 } |
2431 ASSERT(constant_mask.IsSmi()); | 2414 ASSERT(constant_mask.IsSmi()); |
2432 mask = Smi::Cast(constant_mask).Value(); | 2415 mask = Smi::Cast(constant_mask).Value(); |
2433 if ((mask < 0) || (mask > 255)) { | 2416 if ((mask < 0) || (mask > 255)) { |
2434 // Not a valid mask. | 2417 // Not a valid mask. |
2435 return false; | 2418 return false; |
2436 } | 2419 } |
2437 } | 2420 } |
2438 if (getter == MethodRecognizer::kFloat32x4GetSignMask) { | 2421 if (getter == MethodRecognizer::kFloat32x4GetSignMask) { |
2439 Simd32x4GetSignMaskInstr* instr = new(isolate()) Simd32x4GetSignMaskInstr( | 2422 Simd32x4GetSignMaskInstr* instr = new(I) Simd32x4GetSignMaskInstr( |
2440 getter, | 2423 getter, |
2441 new(isolate()) Value(call->ArgumentAt(0)), | 2424 new(I) Value(call->ArgumentAt(0)), |
2442 call->deopt_id()); | 2425 call->deopt_id()); |
2443 ReplaceCall(call, instr); | 2426 ReplaceCall(call, instr); |
2444 return true; | 2427 return true; |
2445 } else if (getter == MethodRecognizer::kFloat32x4ShuffleMix) { | 2428 } else if (getter == MethodRecognizer::kFloat32x4ShuffleMix) { |
2446 Simd32x4ShuffleMixInstr* instr = new(isolate()) Simd32x4ShuffleMixInstr( | 2429 Simd32x4ShuffleMixInstr* instr = new(I) Simd32x4ShuffleMixInstr( |
2447 getter, | 2430 getter, |
2448 new(isolate()) Value(call->ArgumentAt(0)), | 2431 new(I) Value(call->ArgumentAt(0)), |
2449 new(isolate()) Value(call->ArgumentAt(1)), | 2432 new(I) Value(call->ArgumentAt(1)), |
2450 mask, | 2433 mask, |
2451 call->deopt_id()); | 2434 call->deopt_id()); |
2452 ReplaceCall(call, instr); | 2435 ReplaceCall(call, instr); |
2453 return true; | 2436 return true; |
2454 } else { | 2437 } else { |
2455 ASSERT((getter == MethodRecognizer::kFloat32x4Shuffle) || | 2438 ASSERT((getter == MethodRecognizer::kFloat32x4Shuffle) || |
2456 (getter == MethodRecognizer::kFloat32x4ShuffleX) || | 2439 (getter == MethodRecognizer::kFloat32x4ShuffleX) || |
2457 (getter == MethodRecognizer::kFloat32x4ShuffleY) || | 2440 (getter == MethodRecognizer::kFloat32x4ShuffleY) || |
2458 (getter == MethodRecognizer::kFloat32x4ShuffleZ) || | 2441 (getter == MethodRecognizer::kFloat32x4ShuffleZ) || |
2459 (getter == MethodRecognizer::kFloat32x4ShuffleW)); | 2442 (getter == MethodRecognizer::kFloat32x4ShuffleW)); |
2460 Simd32x4ShuffleInstr* instr = new(isolate()) Simd32x4ShuffleInstr( | 2443 Simd32x4ShuffleInstr* instr = new(I) Simd32x4ShuffleInstr( |
2461 getter, | 2444 getter, |
2462 new(isolate()) Value(call->ArgumentAt(0)), | 2445 new(I) Value(call->ArgumentAt(0)), |
2463 mask, | 2446 mask, |
2464 call->deopt_id()); | 2447 call->deopt_id()); |
2465 ReplaceCall(call, instr); | 2448 ReplaceCall(call, instr); |
2466 return true; | 2449 return true; |
2467 } | 2450 } |
2468 UNREACHABLE(); | 2451 UNREACHABLE(); |
2469 return false; | 2452 return false; |
2470 } | 2453 } |
2471 | 2454 |
2472 | 2455 |
2473 bool FlowGraphOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call, | 2456 bool FlowGraphOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call, |
2474 MethodRecognizer::Kind getter) { | 2457 MethodRecognizer::Kind getter) { |
2475 if (!ShouldInlineSimd()) { | 2458 if (!ShouldInlineSimd()) { |
2476 return false; | 2459 return false; |
2477 } | 2460 } |
2478 AddCheckClass(call->ArgumentAt(0), | 2461 AddCheckClass(call->ArgumentAt(0), |
2479 ICData::ZoneHandle( | 2462 ICData::ZoneHandle( |
2480 isolate(), call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 2463 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
2481 call->deopt_id(), | 2464 call->deopt_id(), |
2482 call->env(), | 2465 call->env(), |
2483 call); | 2466 call); |
2484 if ((getter == MethodRecognizer::kFloat64x2GetX) || | 2467 if ((getter == MethodRecognizer::kFloat64x2GetX) || |
2485 (getter == MethodRecognizer::kFloat64x2GetY)) { | 2468 (getter == MethodRecognizer::kFloat64x2GetY)) { |
2486 Simd64x2ShuffleInstr* instr = new(isolate()) Simd64x2ShuffleInstr( | 2469 Simd64x2ShuffleInstr* instr = new(I) Simd64x2ShuffleInstr( |
2487 getter, | 2470 getter, |
2488 new(isolate()) Value(call->ArgumentAt(0)), | 2471 new(I) Value(call->ArgumentAt(0)), |
2489 0, | 2472 0, |
2490 call->deopt_id()); | 2473 call->deopt_id()); |
2491 ReplaceCall(call, instr); | 2474 ReplaceCall(call, instr); |
2492 return true; | 2475 return true; |
2493 } | 2476 } |
2494 UNREACHABLE(); | 2477 UNREACHABLE(); |
2495 return false; | 2478 return false; |
2496 } | 2479 } |
2497 | 2480 |
2498 | 2481 |
2499 bool FlowGraphOptimizer::InlineInt32x4Getter(InstanceCallInstr* call, | 2482 bool FlowGraphOptimizer::InlineInt32x4Getter(InstanceCallInstr* call, |
2500 MethodRecognizer::Kind getter) { | 2483 MethodRecognizer::Kind getter) { |
2501 if (!ShouldInlineSimd()) { | 2484 if (!ShouldInlineSimd()) { |
2502 return false; | 2485 return false; |
2503 } | 2486 } |
2504 AddCheckClass(call->ArgumentAt(0), | 2487 AddCheckClass(call->ArgumentAt(0), |
2505 ICData::ZoneHandle( | 2488 ICData::ZoneHandle( |
2506 isolate(), call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 2489 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
2507 call->deopt_id(), | 2490 call->deopt_id(), |
2508 call->env(), | 2491 call->env(), |
2509 call); | 2492 call); |
2510 intptr_t mask = 0; | 2493 intptr_t mask = 0; |
2511 if ((getter == MethodRecognizer::kInt32x4Shuffle) || | 2494 if ((getter == MethodRecognizer::kInt32x4Shuffle) || |
2512 (getter == MethodRecognizer::kInt32x4ShuffleMix)) { | 2495 (getter == MethodRecognizer::kInt32x4ShuffleMix)) { |
2513 // Extract shuffle mask. | 2496 // Extract shuffle mask. |
2514 Definition* mask_definition = NULL; | 2497 Definition* mask_definition = NULL; |
2515 if (getter == MethodRecognizer::kInt32x4Shuffle) { | 2498 if (getter == MethodRecognizer::kInt32x4Shuffle) { |
2516 ASSERT(call->ArgumentCount() == 2); | 2499 ASSERT(call->ArgumentCount() == 2); |
(...skipping 13 matching lines...) Expand all Loading... |
2530 return false; | 2513 return false; |
2531 } | 2514 } |
2532 ASSERT(constant_mask.IsSmi()); | 2515 ASSERT(constant_mask.IsSmi()); |
2533 mask = Smi::Cast(constant_mask).Value(); | 2516 mask = Smi::Cast(constant_mask).Value(); |
2534 if ((mask < 0) || (mask > 255)) { | 2517 if ((mask < 0) || (mask > 255)) { |
2535 // Not a valid mask. | 2518 // Not a valid mask. |
2536 return false; | 2519 return false; |
2537 } | 2520 } |
2538 } | 2521 } |
2539 if (getter == MethodRecognizer::kInt32x4GetSignMask) { | 2522 if (getter == MethodRecognizer::kInt32x4GetSignMask) { |
2540 Simd32x4GetSignMaskInstr* instr = new(isolate()) Simd32x4GetSignMaskInstr( | 2523 Simd32x4GetSignMaskInstr* instr = new(I) Simd32x4GetSignMaskInstr( |
2541 getter, | 2524 getter, |
2542 new(isolate()) Value(call->ArgumentAt(0)), | 2525 new(I) Value(call->ArgumentAt(0)), |
2543 call->deopt_id()); | 2526 call->deopt_id()); |
2544 ReplaceCall(call, instr); | 2527 ReplaceCall(call, instr); |
2545 return true; | 2528 return true; |
2546 } else if (getter == MethodRecognizer::kInt32x4ShuffleMix) { | 2529 } else if (getter == MethodRecognizer::kInt32x4ShuffleMix) { |
2547 Simd32x4ShuffleMixInstr* instr = new(isolate()) Simd32x4ShuffleMixInstr( | 2530 Simd32x4ShuffleMixInstr* instr = new(I) Simd32x4ShuffleMixInstr( |
2548 getter, | 2531 getter, |
2549 new(isolate()) Value(call->ArgumentAt(0)), | 2532 new(I) Value(call->ArgumentAt(0)), |
2550 new(isolate()) Value(call->ArgumentAt(1)), | 2533 new(I) Value(call->ArgumentAt(1)), |
2551 mask, | 2534 mask, |
2552 call->deopt_id()); | 2535 call->deopt_id()); |
2553 ReplaceCall(call, instr); | 2536 ReplaceCall(call, instr); |
2554 return true; | 2537 return true; |
2555 } else if (getter == MethodRecognizer::kInt32x4Shuffle) { | 2538 } else if (getter == MethodRecognizer::kInt32x4Shuffle) { |
2556 Simd32x4ShuffleInstr* instr = new(isolate()) Simd32x4ShuffleInstr( | 2539 Simd32x4ShuffleInstr* instr = new(I) Simd32x4ShuffleInstr( |
2557 getter, | 2540 getter, |
2558 new(isolate()) Value(call->ArgumentAt(0)), | 2541 new(I) Value(call->ArgumentAt(0)), |
2559 mask, | 2542 mask, |
2560 call->deopt_id()); | 2543 call->deopt_id()); |
2561 ReplaceCall(call, instr); | 2544 ReplaceCall(call, instr); |
2562 return true; | 2545 return true; |
2563 } else { | 2546 } else { |
2564 Int32x4GetFlagInstr* instr = new(isolate()) Int32x4GetFlagInstr( | 2547 Int32x4GetFlagInstr* instr = new(I) Int32x4GetFlagInstr( |
2565 getter, | 2548 getter, |
2566 new(isolate()) Value(call->ArgumentAt(0)), | 2549 new(I) Value(call->ArgumentAt(0)), |
2567 call->deopt_id()); | 2550 call->deopt_id()); |
2568 ReplaceCall(call, instr); | 2551 ReplaceCall(call, instr); |
2569 return true; | 2552 return true; |
2570 } | 2553 } |
2571 } | 2554 } |
2572 | 2555 |
2573 | 2556 |
2574 bool FlowGraphOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, | 2557 bool FlowGraphOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, |
2575 Token::Kind op_kind) { | 2558 Token::Kind op_kind) { |
2576 if (!ShouldInlineSimd()) { | 2559 if (!ShouldInlineSimd()) { |
2577 return false; | 2560 return false; |
2578 } | 2561 } |
2579 ASSERT(call->ArgumentCount() == 2); | 2562 ASSERT(call->ArgumentCount() == 2); |
2580 Definition* left = call->ArgumentAt(0); | 2563 Definition* left = call->ArgumentAt(0); |
2581 Definition* right = call->ArgumentAt(1); | 2564 Definition* right = call->ArgumentAt(1); |
2582 // Type check left. | 2565 // Type check left. |
2583 AddCheckClass(left, | 2566 AddCheckClass(left, |
2584 ICData::ZoneHandle( | 2567 ICData::ZoneHandle( |
2585 isolate(), call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 2568 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
2586 call->deopt_id(), | 2569 call->deopt_id(), |
2587 call->env(), | 2570 call->env(), |
2588 call); | 2571 call); |
2589 // Type check right. | 2572 // Type check right. |
2590 AddCheckClass(right, | 2573 AddCheckClass(right, |
2591 ICData::ZoneHandle( | 2574 ICData::ZoneHandle( |
2592 isolate(), call->ic_data()->AsUnaryClassChecksForArgNr(1)), | 2575 I, call->ic_data()->AsUnaryClassChecksForArgNr(1)), |
2593 call->deopt_id(), | 2576 call->deopt_id(), |
2594 call->env(), | 2577 call->env(), |
2595 call); | 2578 call); |
2596 // Replace call. | 2579 // Replace call. |
2597 BinaryFloat32x4OpInstr* float32x4_bin_op = | 2580 BinaryFloat32x4OpInstr* float32x4_bin_op = |
2598 new(isolate()) BinaryFloat32x4OpInstr( | 2581 new(I) BinaryFloat32x4OpInstr( |
2599 op_kind, new(isolate()) Value(left), new(isolate()) Value(right), | 2582 op_kind, new(I) Value(left), new(I) Value(right), |
2600 call->deopt_id()); | 2583 call->deopt_id()); |
2601 ReplaceCall(call, float32x4_bin_op); | 2584 ReplaceCall(call, float32x4_bin_op); |
2602 | 2585 |
2603 return true; | 2586 return true; |
2604 } | 2587 } |
2605 | 2588 |
2606 | 2589 |
2607 bool FlowGraphOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, | 2590 bool FlowGraphOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, |
2608 Token::Kind op_kind) { | 2591 Token::Kind op_kind) { |
2609 if (!ShouldInlineSimd()) { | 2592 if (!ShouldInlineSimd()) { |
2610 return false; | 2593 return false; |
2611 } | 2594 } |
2612 ASSERT(call->ArgumentCount() == 2); | 2595 ASSERT(call->ArgumentCount() == 2); |
2613 Definition* left = call->ArgumentAt(0); | 2596 Definition* left = call->ArgumentAt(0); |
2614 Definition* right = call->ArgumentAt(1); | 2597 Definition* right = call->ArgumentAt(1); |
2615 // Type check left. | 2598 // Type check left. |
2616 AddCheckClass(left, | 2599 AddCheckClass(left, |
2617 ICData::ZoneHandle( | 2600 ICData::ZoneHandle( |
2618 isolate(), call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 2601 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
2619 call->deopt_id(), | 2602 call->deopt_id(), |
2620 call->env(), | 2603 call->env(), |
2621 call); | 2604 call); |
2622 // Type check right. | 2605 // Type check right. |
2623 AddCheckClass(right, | 2606 AddCheckClass(right, |
2624 ICData::ZoneHandle(isolate(), | 2607 ICData::ZoneHandle(I, |
2625 call->ic_data()->AsUnaryClassChecksForArgNr(1)), | 2608 call->ic_data()->AsUnaryClassChecksForArgNr(1)), |
2626 call->deopt_id(), | 2609 call->deopt_id(), |
2627 call->env(), | 2610 call->env(), |
2628 call); | 2611 call); |
2629 // Replace call. | 2612 // Replace call. |
2630 BinaryInt32x4OpInstr* int32x4_bin_op = | 2613 BinaryInt32x4OpInstr* int32x4_bin_op = |
2631 new(isolate()) BinaryInt32x4OpInstr( | 2614 new(I) BinaryInt32x4OpInstr( |
2632 op_kind, new(isolate()) Value(left), new(isolate()) Value(right), | 2615 op_kind, new(I) Value(left), new(I) Value(right), |
2633 call->deopt_id()); | 2616 call->deopt_id()); |
2634 ReplaceCall(call, int32x4_bin_op); | 2617 ReplaceCall(call, int32x4_bin_op); |
2635 return true; | 2618 return true; |
2636 } | 2619 } |
2637 | 2620 |
2638 | 2621 |
2639 bool FlowGraphOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, | 2622 bool FlowGraphOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, |
2640 Token::Kind op_kind) { | 2623 Token::Kind op_kind) { |
2641 if (!ShouldInlineSimd()) { | 2624 if (!ShouldInlineSimd()) { |
2642 return false; | 2625 return false; |
(...skipping 10 matching lines...) Expand all Loading... |
2653 call); | 2636 call); |
2654 // Type check right. | 2637 // Type check right. |
2655 AddCheckClass(right, | 2638 AddCheckClass(right, |
2656 ICData::ZoneHandle( | 2639 ICData::ZoneHandle( |
2657 call->ic_data()->AsUnaryClassChecksForArgNr(1)), | 2640 call->ic_data()->AsUnaryClassChecksForArgNr(1)), |
2658 call->deopt_id(), | 2641 call->deopt_id(), |
2659 call->env(), | 2642 call->env(), |
2660 call); | 2643 call); |
2661 // Replace call. | 2644 // Replace call. |
2662 BinaryFloat64x2OpInstr* float64x2_bin_op = | 2645 BinaryFloat64x2OpInstr* float64x2_bin_op = |
2663 new(isolate()) BinaryFloat64x2OpInstr( | 2646 new(I) BinaryFloat64x2OpInstr( |
2664 op_kind, new(isolate()) Value(left), new(isolate()) Value(right), | 2647 op_kind, new(I) Value(left), new(I) Value(right), |
2665 call->deopt_id()); | 2648 call->deopt_id()); |
2666 ReplaceCall(call, float64x2_bin_op); | 2649 ReplaceCall(call, float64x2_bin_op); |
2667 return true; | 2650 return true; |
2668 } | 2651 } |
2669 | 2652 |
2670 | 2653 |
2671 // Only unique implicit instance getters can be currently handled. | 2654 // Only unique implicit instance getters can be currently handled. |
2672 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { | 2655 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { |
2673 ASSERT(call->HasICData()); | 2656 ASSERT(call->HasICData()); |
2674 const ICData& ic_data = *call->ic_data(); | 2657 const ICData& ic_data = *call->ic_data(); |
2675 if (ic_data.NumberOfChecks() == 0) { | 2658 if (ic_data.NumberOfChecks() == 0) { |
2676 // No type feedback collected. | 2659 // No type feedback collected. |
2677 return false; | 2660 return false; |
2678 } | 2661 } |
2679 | 2662 |
2680 if (!ic_data.HasOneTarget()) { | 2663 if (!ic_data.HasOneTarget()) { |
2681 // Polymorphic sites are inlined like normal methods by conventional | 2664 // Polymorphic sites are inlined like normal methods by conventional |
2682 // inlining in FlowGraphInliner. | 2665 // inlining in FlowGraphInliner. |
2683 return false; | 2666 return false; |
2684 } | 2667 } |
2685 | 2668 |
2686 const Function& target = Function::Handle(isolate(), ic_data.GetTargetAt(0)); | 2669 const Function& target = Function::Handle(I, ic_data.GetTargetAt(0)); |
2687 if (target.kind() != RawFunction::kImplicitGetter) { | 2670 if (target.kind() != RawFunction::kImplicitGetter) { |
2688 // Non-implicit getters are inlined like normal methods by conventional | 2671 // Non-implicit getters are inlined like normal methods by conventional |
2689 // inlining in FlowGraphInliner. | 2672 // inlining in FlowGraphInliner. |
2690 return false; | 2673 return false; |
2691 } | 2674 } |
2692 InlineImplicitInstanceGetter(call); | 2675 InlineImplicitInstanceGetter(call); |
2693 return true; | 2676 return true; |
2694 } | 2677 } |
2695 | 2678 |
2696 | 2679 |
2697 bool FlowGraphOptimizer::TryReplaceInstanceCallWithInline( | 2680 bool FlowGraphOptimizer::TryReplaceInstanceCallWithInline( |
2698 InstanceCallInstr* call) { | 2681 InstanceCallInstr* call) { |
2699 ASSERT(call->HasICData()); | 2682 ASSERT(call->HasICData()); |
2700 Function& target = Function::Handle(isolate(), Function::null()); | 2683 Function& target = Function::Handle(I); |
2701 GrowableArray<intptr_t> class_ids; | 2684 GrowableArray<intptr_t> class_ids; |
2702 call->ic_data()->GetCheckAt(0, &class_ids, &target); | 2685 call->ic_data()->GetCheckAt(0, &class_ids, &target); |
2703 const intptr_t receiver_cid = class_ids[0]; | 2686 const intptr_t receiver_cid = class_ids[0]; |
2704 | 2687 |
2705 TargetEntryInstr* entry; | 2688 TargetEntryInstr* entry; |
2706 Definition* last; | 2689 Definition* last; |
2707 if (!TryInlineRecognizedMethod(receiver_cid, | 2690 if (!TryInlineRecognizedMethod(receiver_cid, |
2708 target, | 2691 target, |
2709 call, | 2692 call, |
2710 call->ArgumentAt(0), | 2693 call->ArgumentAt(0), |
(...skipping 29 matching lines...) Expand all Loading... |
2740 | 2723 |
2741 // Returns the LoadIndexedInstr. | 2724 // Returns the LoadIndexedInstr. |
2742 Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp( | 2725 Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp( |
2743 Instruction* call, | 2726 Instruction* call, |
2744 intptr_t cid, | 2727 intptr_t cid, |
2745 Definition* str, | 2728 Definition* str, |
2746 Definition* index, | 2729 Definition* index, |
2747 Instruction* cursor) { | 2730 Instruction* cursor) { |
2748 | 2731 |
2749 cursor = flow_graph()->AppendTo(cursor, | 2732 cursor = flow_graph()->AppendTo(cursor, |
2750 new(isolate()) CheckSmiInstr( | 2733 new(I) CheckSmiInstr( |
2751 new(isolate()) Value(index), | 2734 new(I) Value(index), |
2752 call->deopt_id(), | 2735 call->deopt_id(), |
2753 call->token_pos()), | 2736 call->token_pos()), |
2754 call->env(), | 2737 call->env(), |
2755 FlowGraph::kEffect); | 2738 FlowGraph::kEffect); |
2756 | 2739 |
2757 // Load the length of the string. | 2740 // Load the length of the string. |
2758 LoadFieldInstr* length = BuildLoadStringLength(str); | 2741 LoadFieldInstr* length = BuildLoadStringLength(str); |
2759 cursor = flow_graph()->AppendTo(cursor, length, NULL, FlowGraph::kValue); | 2742 cursor = flow_graph()->AppendTo(cursor, length, NULL, FlowGraph::kValue); |
2760 // Bounds check. | 2743 // Bounds check. |
2761 cursor = flow_graph()->AppendTo(cursor, | 2744 cursor = flow_graph()->AppendTo(cursor, |
2762 new(isolate()) CheckArrayBoundInstr( | 2745 new(I) CheckArrayBoundInstr( |
2763 new(isolate()) Value(length), | 2746 new(I) Value(length), |
2764 new(isolate()) Value(index), | 2747 new(I) Value(index), |
2765 call->deopt_id()), | 2748 call->deopt_id()), |
2766 call->env(), | 2749 call->env(), |
2767 FlowGraph::kEffect); | 2750 FlowGraph::kEffect); |
2768 | 2751 |
2769 LoadIndexedInstr* load_indexed = new(isolate()) LoadIndexedInstr( | 2752 LoadIndexedInstr* load_indexed = new(I) LoadIndexedInstr( |
2770 new(isolate()) Value(str), | 2753 new(I) Value(str), |
2771 new(isolate()) Value(index), | 2754 new(I) Value(index), |
2772 Instance::ElementSizeFor(cid), | 2755 Instance::ElementSizeFor(cid), |
2773 cid, | 2756 cid, |
2774 Isolate::kNoDeoptId, | 2757 Isolate::kNoDeoptId, |
2775 call->token_pos()); | 2758 call->token_pos()); |
2776 | 2759 |
2777 cursor = flow_graph()->AppendTo(cursor, | 2760 cursor = flow_graph()->AppendTo(cursor, |
2778 load_indexed, | 2761 load_indexed, |
2779 NULL, | 2762 NULL, |
2780 FlowGraph::kValue); | 2763 FlowGraph::kValue); |
2781 ASSERT(cursor == load_indexed); | 2764 ASSERT(cursor == load_indexed); |
2782 return load_indexed; | 2765 return load_indexed; |
2783 } | 2766 } |
2784 | 2767 |
2785 | 2768 |
2786 bool FlowGraphOptimizer::InlineStringCodeUnitAt( | 2769 bool FlowGraphOptimizer::InlineStringCodeUnitAt( |
2787 Instruction* call, | 2770 Instruction* call, |
2788 intptr_t cid, | 2771 intptr_t cid, |
2789 TargetEntryInstr** entry, | 2772 TargetEntryInstr** entry, |
2790 Definition** last) { | 2773 Definition** last) { |
2791 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. | 2774 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. |
2792 if (RawObject::IsExternalStringClassId(cid)) { | 2775 if (RawObject::IsExternalStringClassId(cid)) { |
2793 return false; | 2776 return false; |
2794 } | 2777 } |
2795 | 2778 |
2796 Definition* str = call->ArgumentAt(0); | 2779 Definition* str = call->ArgumentAt(0); |
2797 Definition* index = call->ArgumentAt(1); | 2780 Definition* index = call->ArgumentAt(1); |
2798 | 2781 |
2799 *entry = new(isolate()) TargetEntryInstr(flow_graph()->allocate_block_id(), | 2782 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), |
2800 call->GetBlock()->try_index()); | 2783 call->GetBlock()->try_index()); |
2801 (*entry)->InheritDeoptTarget(isolate(), call); | 2784 (*entry)->InheritDeoptTarget(I, call); |
2802 | 2785 |
2803 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); | 2786 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); |
2804 | 2787 |
2805 return true; | 2788 return true; |
2806 } | 2789 } |
2807 | 2790 |
2808 | 2791 |
2809 bool FlowGraphOptimizer::InlineStringBaseCharAt( | 2792 bool FlowGraphOptimizer::InlineStringBaseCharAt( |
2810 Instruction* call, | 2793 Instruction* call, |
2811 intptr_t cid, | 2794 intptr_t cid, |
2812 TargetEntryInstr** entry, | 2795 TargetEntryInstr** entry, |
2813 Definition** last) { | 2796 Definition** last) { |
2814 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. | 2797 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. |
2815 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { | 2798 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { |
2816 return false; | 2799 return false; |
2817 } | 2800 } |
2818 Definition* str = call->ArgumentAt(0); | 2801 Definition* str = call->ArgumentAt(0); |
2819 Definition* index = call->ArgumentAt(1); | 2802 Definition* index = call->ArgumentAt(1); |
2820 | 2803 |
2821 *entry = new(isolate()) TargetEntryInstr(flow_graph()->allocate_block_id(), | 2804 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), |
2822 call->GetBlock()->try_index()); | 2805 call->GetBlock()->try_index()); |
2823 (*entry)->InheritDeoptTarget(isolate(), call); | 2806 (*entry)->InheritDeoptTarget(I, call); |
2824 | 2807 |
2825 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); | 2808 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); |
2826 | 2809 |
2827 StringFromCharCodeInstr* char_at = new(isolate()) StringFromCharCodeInstr( | 2810 StringFromCharCodeInstr* char_at = new(I) StringFromCharCodeInstr( |
2828 new(isolate()) Value(*last), cid); | 2811 new(I) Value(*last), cid); |
2829 | 2812 |
2830 flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue); | 2813 flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue); |
2831 *last = char_at; | 2814 *last = char_at; |
2832 | 2815 |
2833 return true; | 2816 return true; |
2834 } | 2817 } |
2835 | 2818 |
2836 | 2819 |
2837 void FlowGraphOptimizer::ReplaceWithMathCFunction( | 2820 void FlowGraphOptimizer::ReplaceWithMathCFunction( |
2838 InstanceCallInstr* call, | 2821 InstanceCallInstr* call, |
2839 MethodRecognizer::Kind recognized_kind) { | 2822 MethodRecognizer::Kind recognized_kind) { |
2840 AddReceiverCheck(call); | 2823 AddReceiverCheck(call); |
2841 ZoneGrowableArray<Value*>* args = | 2824 ZoneGrowableArray<Value*>* args = |
2842 new(isolate()) ZoneGrowableArray<Value*>(call->ArgumentCount()); | 2825 new(I) ZoneGrowableArray<Value*>(call->ArgumentCount()); |
2843 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | 2826 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { |
2844 args->Add(new(isolate()) Value(call->ArgumentAt(i))); | 2827 args->Add(new(I) Value(call->ArgumentAt(i))); |
2845 } | 2828 } |
2846 InvokeMathCFunctionInstr* invoke = | 2829 InvokeMathCFunctionInstr* invoke = |
2847 new(isolate()) InvokeMathCFunctionInstr(args, | 2830 new(I) InvokeMathCFunctionInstr(args, |
2848 call->deopt_id(), | 2831 call->deopt_id(), |
2849 recognized_kind, | 2832 recognized_kind, |
2850 call->token_pos()); | 2833 call->token_pos()); |
2851 ReplaceCall(call, invoke); | 2834 ReplaceCall(call, invoke); |
2852 } | 2835 } |
2853 | 2836 |
2854 | 2837 |
2855 static bool IsSupportedByteArrayViewCid(intptr_t cid) { | 2838 static bool IsSupportedByteArrayViewCid(intptr_t cid) { |
2856 switch (cid) { | 2839 switch (cid) { |
2857 case kTypedDataInt8ArrayCid: | 2840 case kTypedDataInt8ArrayCid: |
2858 case kTypedDataUint8ArrayCid: | 2841 case kTypedDataUint8ArrayCid: |
2859 case kExternalTypedDataUint8ArrayCid: | 2842 case kExternalTypedDataUint8ArrayCid: |
2860 case kTypedDataUint8ClampedArrayCid: | 2843 case kTypedDataUint8ClampedArrayCid: |
(...skipping 15 matching lines...) Expand all Loading... |
2876 | 2859 |
2877 // Inline only simple, frequently called core library methods. | 2860 // Inline only simple, frequently called core library methods. |
2878 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { | 2861 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { |
2879 ASSERT(call->HasICData()); | 2862 ASSERT(call->HasICData()); |
2880 const ICData& ic_data = *call->ic_data(); | 2863 const ICData& ic_data = *call->ic_data(); |
2881 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { | 2864 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { |
2882 // No type feedback collected or multiple targets found. | 2865 // No type feedback collected or multiple targets found. |
2883 return false; | 2866 return false; |
2884 } | 2867 } |
2885 | 2868 |
2886 Function& target = Function::Handle(isolate(), Function::null()); | 2869 Function& target = Function::Handle(I); |
2887 GrowableArray<intptr_t> class_ids; | 2870 GrowableArray<intptr_t> class_ids; |
2888 ic_data.GetCheckAt(0, &class_ids, &target); | 2871 ic_data.GetCheckAt(0, &class_ids, &target); |
2889 MethodRecognizer::Kind recognized_kind = | 2872 MethodRecognizer::Kind recognized_kind = |
2890 MethodRecognizer::RecognizeKind(target); | 2873 MethodRecognizer::RecognizeKind(target); |
2891 | 2874 |
2892 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) && | 2875 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) && |
2893 (ic_data.NumberOfChecks() == 1) && | 2876 (ic_data.NumberOfChecks() == 1) && |
2894 (class_ids[0] == kGrowableObjectArrayCid)) { | 2877 (class_ids[0] == kGrowableObjectArrayCid)) { |
2895 // This is an internal method, no need to check argument types. | 2878 // This is an internal method, no need to check argument types. |
2896 Definition* array = call->ArgumentAt(0); | 2879 Definition* array = call->ArgumentAt(0); |
2897 Definition* value = call->ArgumentAt(1); | 2880 Definition* value = call->ArgumentAt(1); |
2898 StoreInstanceFieldInstr* store = new(isolate()) StoreInstanceFieldInstr( | 2881 StoreInstanceFieldInstr* store = new(I) StoreInstanceFieldInstr( |
2899 GrowableObjectArray::data_offset(), | 2882 GrowableObjectArray::data_offset(), |
2900 new(isolate()) Value(array), | 2883 new(I) Value(array), |
2901 new(isolate()) Value(value), | 2884 new(I) Value(value), |
2902 kEmitStoreBarrier, | 2885 kEmitStoreBarrier, |
2903 call->token_pos()); | 2886 call->token_pos()); |
2904 ReplaceCall(call, store); | 2887 ReplaceCall(call, store); |
2905 return true; | 2888 return true; |
2906 } | 2889 } |
2907 | 2890 |
2908 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) && | 2891 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) && |
2909 (ic_data.NumberOfChecks() == 1) && | 2892 (ic_data.NumberOfChecks() == 1) && |
2910 (class_ids[0] == kGrowableObjectArrayCid)) { | 2893 (class_ids[0] == kGrowableObjectArrayCid)) { |
2911 // This is an internal method, no need to check argument types nor | 2894 // This is an internal method, no need to check argument types nor |
2912 // range. | 2895 // range. |
2913 Definition* array = call->ArgumentAt(0); | 2896 Definition* array = call->ArgumentAt(0); |
2914 Definition* value = call->ArgumentAt(1); | 2897 Definition* value = call->ArgumentAt(1); |
2915 StoreInstanceFieldInstr* store = new(isolate()) StoreInstanceFieldInstr( | 2898 StoreInstanceFieldInstr* store = new(I) StoreInstanceFieldInstr( |
2916 GrowableObjectArray::length_offset(), | 2899 GrowableObjectArray::length_offset(), |
2917 new(isolate()) Value(array), | 2900 new(I) Value(array), |
2918 new(isolate()) Value(value), | 2901 new(I) Value(value), |
2919 kEmitStoreBarrier, | 2902 kEmitStoreBarrier, |
2920 call->token_pos()); | 2903 call->token_pos()); |
2921 ReplaceCall(call, store); | 2904 ReplaceCall(call, store); |
2922 return true; | 2905 return true; |
2923 } | 2906 } |
2924 | 2907 |
2925 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || | 2908 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || |
2926 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && | 2909 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && |
2927 (ic_data.NumberOfChecks() == 1) && | 2910 (ic_data.NumberOfChecks() == 1) && |
2928 ((class_ids[0] == kOneByteStringCid) || | 2911 ((class_ids[0] == kOneByteStringCid) || |
2929 (class_ids[0] == kTwoByteStringCid))) { | 2912 (class_ids[0] == kTwoByteStringCid))) { |
2930 return TryReplaceInstanceCallWithInline(call); | 2913 return TryReplaceInstanceCallWithInline(call); |
2931 } | 2914 } |
2932 | 2915 |
2933 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { | 2916 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { |
2934 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { | 2917 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { |
2935 // This is an internal method, no need to check argument types nor | 2918 // This is an internal method, no need to check argument types nor |
2936 // range. | 2919 // range. |
2937 Definition* str = call->ArgumentAt(0); | 2920 Definition* str = call->ArgumentAt(0); |
2938 Definition* index = call->ArgumentAt(1); | 2921 Definition* index = call->ArgumentAt(1); |
2939 Definition* value = call->ArgumentAt(2); | 2922 Definition* value = call->ArgumentAt(2); |
2940 StoreIndexedInstr* store_op = new(isolate()) StoreIndexedInstr( | 2923 StoreIndexedInstr* store_op = new(I) StoreIndexedInstr( |
2941 new(isolate()) Value(str), | 2924 new(I) Value(str), |
2942 new(isolate()) Value(index), | 2925 new(I) Value(index), |
2943 new(isolate()) Value(value), | 2926 new(I) Value(value), |
2944 kNoStoreBarrier, | 2927 kNoStoreBarrier, |
2945 1, // Index scale | 2928 1, // Index scale |
2946 kOneByteStringCid, | 2929 kOneByteStringCid, |
2947 call->deopt_id(), | 2930 call->deopt_id(), |
2948 call->token_pos()); | 2931 call->token_pos()); |
2949 ReplaceCall(call, store_op); | 2932 ReplaceCall(call, store_op); |
2950 return true; | 2933 return true; |
2951 } | 2934 } |
2952 return false; | 2935 return false; |
2953 } | 2936 } |
2954 | 2937 |
2955 if (CanUnboxDouble() && | 2938 if (CanUnboxDouble() && |
2956 (recognized_kind == MethodRecognizer::kIntegerToDouble) && | 2939 (recognized_kind == MethodRecognizer::kIntegerToDouble) && |
2957 (ic_data.NumberOfChecks() == 1) && | 2940 (ic_data.NumberOfChecks() == 1) && |
2958 (class_ids[0] == kSmiCid)) { | 2941 (class_ids[0] == kSmiCid)) { |
2959 AddReceiverCheck(call); | 2942 AddReceiverCheck(call); |
2960 ReplaceCall(call, | 2943 ReplaceCall(call, |
2961 new(isolate()) SmiToDoubleInstr( | 2944 new(I) SmiToDoubleInstr( |
2962 new(isolate()) Value(call->ArgumentAt(0)), | 2945 new(I) Value(call->ArgumentAt(0)), |
2963 call->token_pos())); | 2946 call->token_pos())); |
2964 return true; | 2947 return true; |
2965 } | 2948 } |
2966 | 2949 |
2967 if (class_ids[0] == kDoubleCid) { | 2950 if (class_ids[0] == kDoubleCid) { |
2968 if (!CanUnboxDouble()) { | 2951 if (!CanUnboxDouble()) { |
2969 return false; | 2952 return false; |
2970 } | 2953 } |
2971 switch (recognized_kind) { | 2954 switch (recognized_kind) { |
2972 case MethodRecognizer::kDoubleToInteger: { | 2955 case MethodRecognizer::kDoubleToInteger: { |
2973 AddReceiverCheck(call); | 2956 AddReceiverCheck(call); |
2974 ASSERT(call->HasICData()); | 2957 ASSERT(call->HasICData()); |
2975 const ICData& ic_data = *call->ic_data(); | 2958 const ICData& ic_data = *call->ic_data(); |
2976 Definition* input = call->ArgumentAt(0); | 2959 Definition* input = call->ArgumentAt(0); |
2977 Definition* d2i_instr = NULL; | 2960 Definition* d2i_instr = NULL; |
2978 if (ic_data.HasDeoptReason(ICData::kDeoptDoubleToSmi)) { | 2961 if (ic_data.HasDeoptReason(ICData::kDeoptDoubleToSmi)) { |
2979 // Do not repeatedly deoptimize because result didn't fit into Smi. | 2962 // Do not repeatedly deoptimize because result didn't fit into Smi. |
2980 d2i_instr = new(isolate()) DoubleToIntegerInstr( | 2963 d2i_instr = new(I) DoubleToIntegerInstr( |
2981 new(isolate()) Value(input), call); | 2964 new(I) Value(input), call); |
2982 } else { | 2965 } else { |
2983 // Optimistically assume result fits into Smi. | 2966 // Optimistically assume result fits into Smi. |
2984 d2i_instr = new(isolate()) DoubleToSmiInstr( | 2967 d2i_instr = new(I) DoubleToSmiInstr( |
2985 new(isolate()) Value(input), call->deopt_id()); | 2968 new(I) Value(input), call->deopt_id()); |
2986 } | 2969 } |
2987 ReplaceCall(call, d2i_instr); | 2970 ReplaceCall(call, d2i_instr); |
2988 return true; | 2971 return true; |
2989 } | 2972 } |
2990 case MethodRecognizer::kDoubleMod: | 2973 case MethodRecognizer::kDoubleMod: |
2991 case MethodRecognizer::kDoubleRound: | 2974 case MethodRecognizer::kDoubleRound: |
2992 ReplaceWithMathCFunction(call, recognized_kind); | 2975 ReplaceWithMathCFunction(call, recognized_kind); |
2993 return true; | 2976 return true; |
2994 case MethodRecognizer::kDoubleTruncate: | 2977 case MethodRecognizer::kDoubleTruncate: |
2995 case MethodRecognizer::kDoubleFloor: | 2978 case MethodRecognizer::kDoubleFloor: |
2996 case MethodRecognizer::kDoubleCeil: | 2979 case MethodRecognizer::kDoubleCeil: |
2997 if (!TargetCPUFeatures::double_truncate_round_supported()) { | 2980 if (!TargetCPUFeatures::double_truncate_round_supported()) { |
2998 ReplaceWithMathCFunction(call, recognized_kind); | 2981 ReplaceWithMathCFunction(call, recognized_kind); |
2999 } else { | 2982 } else { |
3000 AddReceiverCheck(call); | 2983 AddReceiverCheck(call); |
3001 DoubleToDoubleInstr* d2d_instr = | 2984 DoubleToDoubleInstr* d2d_instr = |
3002 new(isolate()) DoubleToDoubleInstr( | 2985 new(I) DoubleToDoubleInstr(new(I) Value(call->ArgumentAt(0)), |
3003 new(isolate()) Value(call->ArgumentAt(0)), | 2986 recognized_kind, call->deopt_id()); |
3004 recognized_kind, call->deopt_id()); | |
3005 ReplaceCall(call, d2d_instr); | 2987 ReplaceCall(call, d2d_instr); |
3006 } | 2988 } |
3007 return true; | 2989 return true; |
3008 default: | 2990 default: |
3009 // Unsupported method. | 2991 // Unsupported method. |
3010 return false; | 2992 return false; |
3011 } | 2993 } |
3012 } | 2994 } |
3013 | 2995 |
3014 if (IsSupportedByteArrayViewCid(class_ids[0]) && | 2996 if (IsSupportedByteArrayViewCid(class_ids[0]) && |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3111 ASSERT(int32_mask->IsConstant()); | 3093 ASSERT(int32_mask->IsConstant()); |
3112 const Integer& mask_literal = Integer::Cast( | 3094 const Integer& mask_literal = Integer::Cast( |
3113 int32_mask->AsConstant()->value()); | 3095 int32_mask->AsConstant()->value()); |
3114 const int64_t mask_value = mask_literal.AsInt64Value(); | 3096 const int64_t mask_value = mask_literal.AsInt64Value(); |
3115 ASSERT(mask_value >= 0); | 3097 ASSERT(mask_value >= 0); |
3116 if (mask_value > Smi::kMaxValue) { | 3098 if (mask_value > Smi::kMaxValue) { |
3117 // The result will not be Smi. | 3099 // The result will not be Smi. |
3118 return false; | 3100 return false; |
3119 } | 3101 } |
3120 BinarySmiOpInstr* left_shift = | 3102 BinarySmiOpInstr* left_shift = |
3121 new(isolate()) BinarySmiOpInstr(Token::kSHL, | 3103 new(I) BinarySmiOpInstr(Token::kSHL, |
3122 new(isolate()) Value(value), | 3104 new(I) Value(value), |
3123 new(isolate()) Value(count), | 3105 new(I) Value(count), |
3124 call->deopt_id(), call->token_pos()); | 3106 call->deopt_id(), call->token_pos()); |
3125 left_shift->set_is_truncating(true); | 3107 left_shift->set_is_truncating(true); |
3126 if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) { | 3108 if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) { |
3127 // No BIT_AND operation needed. | 3109 // No BIT_AND operation needed. |
3128 ReplaceCall(call, left_shift); | 3110 ReplaceCall(call, left_shift); |
3129 } else { | 3111 } else { |
3130 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue); | 3112 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue); |
3131 BinarySmiOpInstr* bit_and = | 3113 BinarySmiOpInstr* bit_and = |
3132 new(isolate()) BinarySmiOpInstr(Token::kBIT_AND, | 3114 new(I) BinarySmiOpInstr(Token::kBIT_AND, |
3133 new(isolate()) Value(left_shift), | 3115 new(I) Value(left_shift), |
3134 new(isolate()) Value(int32_mask), | 3116 new(I) Value(int32_mask), |
3135 call->deopt_id(), | 3117 call->deopt_id(), |
3136 call->token_pos()); | 3118 call->token_pos()); |
3137 ReplaceCall(call, bit_and); | 3119 ReplaceCall(call, bit_and); |
3138 } | 3120 } |
3139 return true; | 3121 return true; |
3140 } | 3122 } |
3141 | 3123 |
3142 if (HasTwoMintOrSmi(ic_data) && | 3124 if (HasTwoMintOrSmi(ic_data) && |
3143 HasOnlyOneSmi(ICData::Handle(isolate(), | 3125 HasOnlyOneSmi(ICData::Handle(I, |
3144 ic_data.AsUnaryClassChecksForArgNr(1)))) { | 3126 ic_data.AsUnaryClassChecksForArgNr(1)))) { |
3145 if (!FlowGraphCompiler::SupportsUnboxedMints() || | 3127 if (!FlowGraphCompiler::SupportsUnboxedMints() || |
3146 ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { | 3128 ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { |
3147 return false; | 3129 return false; |
3148 } | 3130 } |
3149 ShiftMintOpInstr* left_shift = | 3131 ShiftMintOpInstr* left_shift = |
3150 new(isolate()) ShiftMintOpInstr(Token::kSHL, | 3132 new(I) ShiftMintOpInstr(Token::kSHL, |
3151 new(isolate()) Value(value), | 3133 new(I) Value(value), |
3152 new(isolate()) Value(count), | 3134 new(I) Value(count), |
3153 call->deopt_id()); | 3135 call->deopt_id()); |
3154 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue); | 3136 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue); |
3155 BinaryMintOpInstr* bit_and = | 3137 BinaryMintOpInstr* bit_and = |
3156 new(isolate()) BinaryMintOpInstr(Token::kBIT_AND, | 3138 new(I) BinaryMintOpInstr(Token::kBIT_AND, |
3157 new(isolate()) Value(left_shift), | 3139 new(I) Value(left_shift), |
3158 new(isolate()) Value(int32_mask), | 3140 new(I) Value(int32_mask), |
3159 call->deopt_id()); | 3141 call->deopt_id()); |
3160 ReplaceCall(call, bit_and); | 3142 ReplaceCall(call, bit_and); |
3161 return true; | 3143 return true; |
3162 } | 3144 } |
3163 } | 3145 } |
3164 return false; | 3146 return false; |
3165 } | 3147 } |
3166 | 3148 |
3167 | 3149 |
3168 bool FlowGraphOptimizer::TryInlineFloat32x4Constructor( | 3150 bool FlowGraphOptimizer::TryInlineFloat32x4Constructor( |
3169 StaticCallInstr* call, | 3151 StaticCallInstr* call, |
3170 MethodRecognizer::Kind recognized_kind) { | 3152 MethodRecognizer::Kind recognized_kind) { |
3171 if (!ShouldInlineSimd()) { | 3153 if (!ShouldInlineSimd()) { |
3172 return false; | 3154 return false; |
3173 } | 3155 } |
3174 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) { | 3156 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) { |
3175 Float32x4ZeroInstr* zero = | 3157 Float32x4ZeroInstr* zero = |
3176 new(isolate()) Float32x4ZeroInstr(call->deopt_id()); | 3158 new(I) Float32x4ZeroInstr(call->deopt_id()); |
3177 ReplaceCall(call, zero); | 3159 ReplaceCall(call, zero); |
3178 return true; | 3160 return true; |
3179 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) { | 3161 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) { |
3180 Float32x4SplatInstr* splat = | 3162 Float32x4SplatInstr* splat = |
3181 new(isolate()) Float32x4SplatInstr( | 3163 new(I) Float32x4SplatInstr( |
3182 new(isolate()) Value(call->ArgumentAt(1)), call->deopt_id()); | 3164 new(I) Value(call->ArgumentAt(1)), call->deopt_id()); |
3183 ReplaceCall(call, splat); | 3165 ReplaceCall(call, splat); |
3184 return true; | 3166 return true; |
3185 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) { | 3167 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) { |
3186 Float32x4ConstructorInstr* con = | 3168 Float32x4ConstructorInstr* con = |
3187 new(isolate()) Float32x4ConstructorInstr( | 3169 new(I) Float32x4ConstructorInstr( |
3188 new(isolate()) Value(call->ArgumentAt(1)), | 3170 new(I) Value(call->ArgumentAt(1)), |
3189 new(isolate()) Value(call->ArgumentAt(2)), | 3171 new(I) Value(call->ArgumentAt(2)), |
3190 new(isolate()) Value(call->ArgumentAt(3)), | 3172 new(I) Value(call->ArgumentAt(3)), |
3191 new(isolate()) Value(call->ArgumentAt(4)), | 3173 new(I) Value(call->ArgumentAt(4)), |
3192 call->deopt_id()); | 3174 call->deopt_id()); |
3193 ReplaceCall(call, con); | 3175 ReplaceCall(call, con); |
3194 return true; | 3176 return true; |
3195 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromInt32x4Bits) { | 3177 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromInt32x4Bits) { |
3196 Int32x4ToFloat32x4Instr* cast = | 3178 Int32x4ToFloat32x4Instr* cast = |
3197 new(isolate()) Int32x4ToFloat32x4Instr( | 3179 new(I) Int32x4ToFloat32x4Instr( |
3198 new(isolate()) Value(call->ArgumentAt(1)), call->deopt_id()); | 3180 new(I) Value(call->ArgumentAt(1)), call->deopt_id()); |
3199 ReplaceCall(call, cast); | 3181 ReplaceCall(call, cast); |
3200 return true; | 3182 return true; |
3201 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2) { | 3183 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2) { |
3202 Float64x2ToFloat32x4Instr* cast = | 3184 Float64x2ToFloat32x4Instr* cast = |
3203 new(isolate()) Float64x2ToFloat32x4Instr( | 3185 new(I) Float64x2ToFloat32x4Instr( |
3204 new(isolate()) Value(call->ArgumentAt(1)), call->deopt_id()); | 3186 new(I) Value(call->ArgumentAt(1)), call->deopt_id()); |
3205 ReplaceCall(call, cast); | 3187 ReplaceCall(call, cast); |
3206 return true; | 3188 return true; |
3207 } | 3189 } |
3208 return false; | 3190 return false; |
3209 } | 3191 } |
3210 | 3192 |
3211 | 3193 |
3212 bool FlowGraphOptimizer::TryInlineFloat64x2Constructor( | 3194 bool FlowGraphOptimizer::TryInlineFloat64x2Constructor( |
3213 StaticCallInstr* call, | 3195 StaticCallInstr* call, |
3214 MethodRecognizer::Kind recognized_kind) { | 3196 MethodRecognizer::Kind recognized_kind) { |
3215 if (!ShouldInlineSimd()) { | 3197 if (!ShouldInlineSimd()) { |
3216 return false; | 3198 return false; |
3217 } | 3199 } |
3218 if (recognized_kind == MethodRecognizer::kFloat64x2Zero) { | 3200 if (recognized_kind == MethodRecognizer::kFloat64x2Zero) { |
3219 Float64x2ZeroInstr* zero = | 3201 Float64x2ZeroInstr* zero = |
3220 new(isolate()) Float64x2ZeroInstr(call->deopt_id()); | 3202 new(I) Float64x2ZeroInstr(call->deopt_id()); |
3221 ReplaceCall(call, zero); | 3203 ReplaceCall(call, zero); |
3222 return true; | 3204 return true; |
3223 } else if (recognized_kind == MethodRecognizer::kFloat64x2Splat) { | 3205 } else if (recognized_kind == MethodRecognizer::kFloat64x2Splat) { |
3224 Float64x2SplatInstr* splat = | 3206 Float64x2SplatInstr* splat = |
3225 new(isolate()) Float64x2SplatInstr( | 3207 new(I) Float64x2SplatInstr( |
3226 new(isolate()) Value(call->ArgumentAt(1)), call->deopt_id()); | 3208 new(I) Value(call->ArgumentAt(1)), call->deopt_id()); |
3227 ReplaceCall(call, splat); | 3209 ReplaceCall(call, splat); |
3228 return true; | 3210 return true; |
3229 } else if (recognized_kind == MethodRecognizer::kFloat64x2Constructor) { | 3211 } else if (recognized_kind == MethodRecognizer::kFloat64x2Constructor) { |
3230 Float64x2ConstructorInstr* con = | 3212 Float64x2ConstructorInstr* con = |
3231 new(isolate()) Float64x2ConstructorInstr( | 3213 new(I) Float64x2ConstructorInstr( |
3232 new(isolate()) Value(call->ArgumentAt(1)), | 3214 new(I) Value(call->ArgumentAt(1)), |
3233 new(isolate()) Value(call->ArgumentAt(2)), | 3215 new(I) Value(call->ArgumentAt(2)), |
3234 call->deopt_id()); | 3216 call->deopt_id()); |
3235 ReplaceCall(call, con); | 3217 ReplaceCall(call, con); |
3236 return true; | 3218 return true; |
3237 } else if (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4) { | 3219 } else if (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4) { |
3238 Float32x4ToFloat64x2Instr* cast = | 3220 Float32x4ToFloat64x2Instr* cast = |
3239 new(isolate()) Float32x4ToFloat64x2Instr( | 3221 new(I) Float32x4ToFloat64x2Instr( |
3240 new(isolate()) Value(call->ArgumentAt(1)), call->deopt_id()); | 3222 new(I) Value(call->ArgumentAt(1)), call->deopt_id()); |
3241 ReplaceCall(call, cast); | 3223 ReplaceCall(call, cast); |
3242 return true; | 3224 return true; |
3243 } | 3225 } |
3244 return false; | 3226 return false; |
3245 } | 3227 } |
3246 | 3228 |
3247 | 3229 |
3248 bool FlowGraphOptimizer::TryInlineInt32x4Constructor( | 3230 bool FlowGraphOptimizer::TryInlineInt32x4Constructor( |
3249 StaticCallInstr* call, | 3231 StaticCallInstr* call, |
3250 MethodRecognizer::Kind recognized_kind) { | 3232 MethodRecognizer::Kind recognized_kind) { |
3251 if (!ShouldInlineSimd()) { | 3233 if (!ShouldInlineSimd()) { |
3252 return false; | 3234 return false; |
3253 } | 3235 } |
3254 if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) { | 3236 if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) { |
3255 Int32x4BoolConstructorInstr* con = | 3237 Int32x4BoolConstructorInstr* con = |
3256 new(isolate()) Int32x4BoolConstructorInstr( | 3238 new(I) Int32x4BoolConstructorInstr( |
3257 new(isolate()) Value(call->ArgumentAt(1)), | 3239 new(I) Value(call->ArgumentAt(1)), |
3258 new(isolate()) Value(call->ArgumentAt(2)), | 3240 new(I) Value(call->ArgumentAt(2)), |
3259 new(isolate()) Value(call->ArgumentAt(3)), | 3241 new(I) Value(call->ArgumentAt(3)), |
3260 new(isolate()) Value(call->ArgumentAt(4)), | 3242 new(I) Value(call->ArgumentAt(4)), |
3261 call->deopt_id()); | 3243 call->deopt_id()); |
3262 ReplaceCall(call, con); | 3244 ReplaceCall(call, con); |
3263 return true; | 3245 return true; |
3264 } else if (recognized_kind == MethodRecognizer::kInt32x4FromFloat32x4Bits) { | 3246 } else if (recognized_kind == MethodRecognizer::kInt32x4FromFloat32x4Bits) { |
3265 Float32x4ToInt32x4Instr* cast = | 3247 Float32x4ToInt32x4Instr* cast = |
3266 new(isolate()) Float32x4ToInt32x4Instr( | 3248 new(I) Float32x4ToInt32x4Instr( |
3267 new(isolate()) Value(call->ArgumentAt(1)), call->deopt_id()); | 3249 new(I) Value(call->ArgumentAt(1)), call->deopt_id()); |
3268 ReplaceCall(call, cast); | 3250 ReplaceCall(call, cast); |
3269 return true; | 3251 return true; |
3270 } | 3252 } |
3271 return false; | 3253 return false; |
3272 } | 3254 } |
3273 | 3255 |
3274 | 3256 |
3275 bool FlowGraphOptimizer::TryInlineFloat32x4Method( | 3257 bool FlowGraphOptimizer::TryInlineFloat32x4Method( |
3276 InstanceCallInstr* call, | 3258 InstanceCallInstr* call, |
3277 MethodRecognizer::Kind recognized_kind) { | 3259 MethodRecognizer::Kind recognized_kind) { |
(...skipping 15 matching lines...) Expand all Loading... |
3293 case MethodRecognizer::kFloat32x4GreaterThan: | 3275 case MethodRecognizer::kFloat32x4GreaterThan: |
3294 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: | 3276 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: |
3295 case MethodRecognizer::kFloat32x4LessThan: | 3277 case MethodRecognizer::kFloat32x4LessThan: |
3296 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 3278 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
3297 case MethodRecognizer::kFloat32x4NotEqual: { | 3279 case MethodRecognizer::kFloat32x4NotEqual: { |
3298 Definition* left = call->ArgumentAt(0); | 3280 Definition* left = call->ArgumentAt(0); |
3299 Definition* right = call->ArgumentAt(1); | 3281 Definition* right = call->ArgumentAt(1); |
3300 // Type check left. | 3282 // Type check left. |
3301 AddCheckClass(left, | 3283 AddCheckClass(left, |
3302 ICData::ZoneHandle( | 3284 ICData::ZoneHandle( |
3303 isolate(), | 3285 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3304 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
3305 call->deopt_id(), | 3286 call->deopt_id(), |
3306 call->env(), | 3287 call->env(), |
3307 call); | 3288 call); |
3308 // Replace call. | 3289 // Replace call. |
3309 Float32x4ComparisonInstr* cmp = | 3290 Float32x4ComparisonInstr* cmp = |
3310 new(isolate()) Float32x4ComparisonInstr( | 3291 new(I) Float32x4ComparisonInstr(recognized_kind, |
3311 recognized_kind, | 3292 new(I) Value(left), |
3312 new(isolate()) Value(left), | 3293 new(I) Value(right), |
3313 new(isolate()) Value(right), | 3294 call->deopt_id()); |
3314 call->deopt_id()); | |
3315 ReplaceCall(call, cmp); | 3295 ReplaceCall(call, cmp); |
3316 return true; | 3296 return true; |
3317 } | 3297 } |
3318 case MethodRecognizer::kFloat32x4Min: | 3298 case MethodRecognizer::kFloat32x4Min: |
3319 case MethodRecognizer::kFloat32x4Max: { | 3299 case MethodRecognizer::kFloat32x4Max: { |
3320 Definition* left = call->ArgumentAt(0); | 3300 Definition* left = call->ArgumentAt(0); |
3321 Definition* right = call->ArgumentAt(1); | 3301 Definition* right = call->ArgumentAt(1); |
3322 // Type check left. | 3302 // Type check left. |
3323 AddCheckClass(left, | 3303 AddCheckClass(left, |
3324 ICData::ZoneHandle( | 3304 ICData::ZoneHandle( |
3325 isolate(), | 3305 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3326 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
3327 call->deopt_id(), | 3306 call->deopt_id(), |
3328 call->env(), | 3307 call->env(), |
3329 call); | 3308 call); |
3330 Float32x4MinMaxInstr* minmax = | 3309 Float32x4MinMaxInstr* minmax = |
3331 new(isolate()) Float32x4MinMaxInstr( | 3310 new(I) Float32x4MinMaxInstr( |
3332 recognized_kind, | 3311 recognized_kind, |
3333 new(isolate()) Value(left), | 3312 new(I) Value(left), |
3334 new(isolate()) Value(right), | 3313 new(I) Value(right), |
3335 call->deopt_id()); | 3314 call->deopt_id()); |
3336 ReplaceCall(call, minmax); | 3315 ReplaceCall(call, minmax); |
3337 return true; | 3316 return true; |
3338 } | 3317 } |
3339 case MethodRecognizer::kFloat32x4Scale: { | 3318 case MethodRecognizer::kFloat32x4Scale: { |
3340 Definition* left = call->ArgumentAt(0); | 3319 Definition* left = call->ArgumentAt(0); |
3341 Definition* right = call->ArgumentAt(1); | 3320 Definition* right = call->ArgumentAt(1); |
3342 // Type check left. | 3321 // Type check left. |
3343 AddCheckClass(left, | 3322 AddCheckClass(left, |
3344 ICData::ZoneHandle( | 3323 ICData::ZoneHandle( |
3345 isolate(), | 3324 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3346 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
3347 call->deopt_id(), | 3325 call->deopt_id(), |
3348 call->env(), | 3326 call->env(), |
3349 call); | 3327 call); |
3350 // Left and right values are swapped when handed to the instruction, | 3328 // Left and right values are swapped when handed to the instruction, |
3351 // this is done so that the double value is loaded into the output | 3329 // this is done so that the double value is loaded into the output |
3352 // register and can be destroyed. | 3330 // register and can be destroyed. |
3353 Float32x4ScaleInstr* scale = | 3331 Float32x4ScaleInstr* scale = |
3354 new(isolate()) Float32x4ScaleInstr( | 3332 new(I) Float32x4ScaleInstr(recognized_kind, |
3355 recognized_kind, | 3333 new(I) Value(right), |
3356 new(isolate()) Value(right), | 3334 new(I) Value(left), |
3357 new(isolate()) Value(left), | 3335 call->deopt_id()); |
3358 call->deopt_id()); | |
3359 ReplaceCall(call, scale); | 3336 ReplaceCall(call, scale); |
3360 return true; | 3337 return true; |
3361 } | 3338 } |
3362 case MethodRecognizer::kFloat32x4Sqrt: | 3339 case MethodRecognizer::kFloat32x4Sqrt: |
3363 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 3340 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
3364 case MethodRecognizer::kFloat32x4Reciprocal: { | 3341 case MethodRecognizer::kFloat32x4Reciprocal: { |
3365 Definition* left = call->ArgumentAt(0); | 3342 Definition* left = call->ArgumentAt(0); |
3366 AddCheckClass(left, | 3343 AddCheckClass(left, |
3367 ICData::ZoneHandle( | 3344 ICData::ZoneHandle( |
3368 isolate(), | 3345 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3369 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
3370 call->deopt_id(), | 3346 call->deopt_id(), |
3371 call->env(), | 3347 call->env(), |
3372 call); | 3348 call); |
3373 Float32x4SqrtInstr* sqrt = | 3349 Float32x4SqrtInstr* sqrt = |
3374 new(isolate()) Float32x4SqrtInstr( | 3350 new(I) Float32x4SqrtInstr(recognized_kind, |
3375 recognized_kind, | 3351 new(I) Value(left), |
3376 new(isolate()) Value(left), | 3352 call->deopt_id()); |
3377 call->deopt_id()); | |
3378 ReplaceCall(call, sqrt); | 3353 ReplaceCall(call, sqrt); |
3379 return true; | 3354 return true; |
3380 } | 3355 } |
3381 case MethodRecognizer::kFloat32x4WithX: | 3356 case MethodRecognizer::kFloat32x4WithX: |
3382 case MethodRecognizer::kFloat32x4WithY: | 3357 case MethodRecognizer::kFloat32x4WithY: |
3383 case MethodRecognizer::kFloat32x4WithZ: | 3358 case MethodRecognizer::kFloat32x4WithZ: |
3384 case MethodRecognizer::kFloat32x4WithW: { | 3359 case MethodRecognizer::kFloat32x4WithW: { |
3385 Definition* left = call->ArgumentAt(0); | 3360 Definition* left = call->ArgumentAt(0); |
3386 Definition* right = call->ArgumentAt(1); | 3361 Definition* right = call->ArgumentAt(1); |
3387 // Type check left. | 3362 // Type check left. |
3388 AddCheckClass(left, | 3363 AddCheckClass(left, |
3389 ICData::ZoneHandle( | 3364 ICData::ZoneHandle( |
3390 isolate(), | 3365 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3391 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
3392 call->deopt_id(), | 3366 call->deopt_id(), |
3393 call->env(), | 3367 call->env(), |
3394 call); | 3368 call); |
3395 Float32x4WithInstr* with = new(isolate()) Float32x4WithInstr( | 3369 Float32x4WithInstr* with = new(I) Float32x4WithInstr(recognized_kind, |
3396 recognized_kind, | 3370 new(I) Value(left), |
3397 new(isolate()) Value(left), | 3371 new(I) Value(right), |
3398 new(isolate()) Value(right), | 3372 call->deopt_id()); |
3399 call->deopt_id()); | |
3400 ReplaceCall(call, with); | 3373 ReplaceCall(call, with); |
3401 return true; | 3374 return true; |
3402 } | 3375 } |
3403 case MethodRecognizer::kFloat32x4Absolute: | 3376 case MethodRecognizer::kFloat32x4Absolute: |
3404 case MethodRecognizer::kFloat32x4Negate: { | 3377 case MethodRecognizer::kFloat32x4Negate: { |
3405 Definition* left = call->ArgumentAt(0); | 3378 Definition* left = call->ArgumentAt(0); |
3406 // Type check left. | 3379 // Type check left. |
3407 AddCheckClass(left, | 3380 AddCheckClass(left, |
3408 ICData::ZoneHandle( | 3381 ICData::ZoneHandle( |
3409 isolate(), | 3382 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3410 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
3411 call->deopt_id(), | 3383 call->deopt_id(), |
3412 call->env(), | 3384 call->env(), |
3413 call); | 3385 call); |
3414 Float32x4ZeroArgInstr* zeroArg = | 3386 Float32x4ZeroArgInstr* zeroArg = |
3415 new(isolate()) Float32x4ZeroArgInstr( | 3387 new(I) Float32x4ZeroArgInstr( |
3416 recognized_kind, new(isolate()) Value(left), call->deopt_id()); | 3388 recognized_kind, new(I) Value(left), call->deopt_id()); |
3417 ReplaceCall(call, zeroArg); | 3389 ReplaceCall(call, zeroArg); |
3418 return true; | 3390 return true; |
3419 } | 3391 } |
3420 case MethodRecognizer::kFloat32x4Clamp: { | 3392 case MethodRecognizer::kFloat32x4Clamp: { |
3421 Definition* left = call->ArgumentAt(0); | 3393 Definition* left = call->ArgumentAt(0); |
3422 Definition* lower = call->ArgumentAt(1); | 3394 Definition* lower = call->ArgumentAt(1); |
3423 Definition* upper = call->ArgumentAt(2); | 3395 Definition* upper = call->ArgumentAt(2); |
3424 // Type check left. | 3396 // Type check left. |
3425 AddCheckClass(left, | 3397 AddCheckClass(left, |
3426 ICData::ZoneHandle( | 3398 ICData::ZoneHandle( |
3427 isolate(), | 3399 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3428 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
3429 call->deopt_id(), | 3400 call->deopt_id(), |
3430 call->env(), | 3401 call->env(), |
3431 call); | 3402 call); |
3432 Float32x4ClampInstr* clamp = new(isolate()) Float32x4ClampInstr( | 3403 Float32x4ClampInstr* clamp = new(I) Float32x4ClampInstr( |
3433 new(isolate()) Value(left), | 3404 new(I) Value(left), |
3434 new(isolate()) Value(lower), | 3405 new(I) Value(lower), |
3435 new(isolate()) Value(upper), | 3406 new(I) Value(upper), |
3436 call->deopt_id()); | 3407 call->deopt_id()); |
3437 ReplaceCall(call, clamp); | 3408 ReplaceCall(call, clamp); |
3438 return true; | 3409 return true; |
3439 } | 3410 } |
3440 case MethodRecognizer::kFloat32x4ShuffleMix: | 3411 case MethodRecognizer::kFloat32x4ShuffleMix: |
3441 case MethodRecognizer::kFloat32x4Shuffle: { | 3412 case MethodRecognizer::kFloat32x4Shuffle: { |
3442 return InlineFloat32x4Getter(call, recognized_kind); | 3413 return InlineFloat32x4Getter(call, recognized_kind); |
3443 } | 3414 } |
3444 default: | 3415 default: |
3445 return false; | 3416 return false; |
(...skipping 15 matching lines...) Expand all Loading... |
3461 ASSERT(call->ic_data()->HasOneTarget()); | 3432 ASSERT(call->ic_data()->HasOneTarget()); |
3462 return InlineFloat64x2Getter(call, recognized_kind); | 3433 return InlineFloat64x2Getter(call, recognized_kind); |
3463 case MethodRecognizer::kFloat64x2Negate: | 3434 case MethodRecognizer::kFloat64x2Negate: |
3464 case MethodRecognizer::kFloat64x2Abs: | 3435 case MethodRecognizer::kFloat64x2Abs: |
3465 case MethodRecognizer::kFloat64x2Sqrt: | 3436 case MethodRecognizer::kFloat64x2Sqrt: |
3466 case MethodRecognizer::kFloat64x2GetSignMask: { | 3437 case MethodRecognizer::kFloat64x2GetSignMask: { |
3467 Definition* left = call->ArgumentAt(0); | 3438 Definition* left = call->ArgumentAt(0); |
3468 // Type check left. | 3439 // Type check left. |
3469 AddCheckClass(left, | 3440 AddCheckClass(left, |
3470 ICData::ZoneHandle( | 3441 ICData::ZoneHandle( |
3471 isolate(), | 3442 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3472 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
3473 call->deopt_id(), | 3443 call->deopt_id(), |
3474 call->env(), | 3444 call->env(), |
3475 call); | 3445 call); |
3476 Float64x2ZeroArgInstr* zeroArg = | 3446 Float64x2ZeroArgInstr* zeroArg = |
3477 new(isolate()) Float64x2ZeroArgInstr( | 3447 new(I) Float64x2ZeroArgInstr( |
3478 recognized_kind, new(isolate()) Value(left), call->deopt_id()); | 3448 recognized_kind, new(I) Value(left), call->deopt_id()); |
3479 ReplaceCall(call, zeroArg); | 3449 ReplaceCall(call, zeroArg); |
3480 return true; | 3450 return true; |
3481 } | 3451 } |
3482 case MethodRecognizer::kFloat64x2Scale: | 3452 case MethodRecognizer::kFloat64x2Scale: |
3483 case MethodRecognizer::kFloat64x2WithX: | 3453 case MethodRecognizer::kFloat64x2WithX: |
3484 case MethodRecognizer::kFloat64x2WithY: | 3454 case MethodRecognizer::kFloat64x2WithY: |
3485 case MethodRecognizer::kFloat64x2Min: | 3455 case MethodRecognizer::kFloat64x2Min: |
3486 case MethodRecognizer::kFloat64x2Max: { | 3456 case MethodRecognizer::kFloat64x2Max: { |
3487 Definition* left = call->ArgumentAt(0); | 3457 Definition* left = call->ArgumentAt(0); |
3488 Definition* right = call->ArgumentAt(1); | 3458 Definition* right = call->ArgumentAt(1); |
3489 // Type check left. | 3459 // Type check left. |
3490 AddCheckClass(left, | 3460 AddCheckClass(left, |
3491 ICData::ZoneHandle( | 3461 ICData::ZoneHandle( |
3492 isolate(), | 3462 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3493 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
3494 call->deopt_id(), | 3463 call->deopt_id(), |
3495 call->env(), | 3464 call->env(), |
3496 call); | 3465 call); |
3497 Float64x2OneArgInstr* zeroArg = | 3466 Float64x2OneArgInstr* zeroArg = |
3498 new(isolate()) Float64x2OneArgInstr( | 3467 new(I) Float64x2OneArgInstr(recognized_kind, |
3499 recognized_kind, | 3468 new(I) Value(left), |
3500 new(isolate()) Value(left), | 3469 new(I) Value(right), |
3501 new(isolate()) Value(right), | 3470 call->deopt_id()); |
3502 call->deopt_id()); | |
3503 ReplaceCall(call, zeroArg); | 3471 ReplaceCall(call, zeroArg); |
3504 return true; | 3472 return true; |
3505 } | 3473 } |
3506 default: | 3474 default: |
3507 return false; | 3475 return false; |
3508 } | 3476 } |
3509 } | 3477 } |
3510 | 3478 |
3511 | 3479 |
3512 bool FlowGraphOptimizer::TryInlineInt32x4Method( | 3480 bool FlowGraphOptimizer::TryInlineInt32x4Method( |
(...skipping 15 matching lines...) Expand all Loading... |
3528 ASSERT(call->ic_data()->HasOneTarget()); | 3496 ASSERT(call->ic_data()->HasOneTarget()); |
3529 return InlineInt32x4Getter(call, recognized_kind); | 3497 return InlineInt32x4Getter(call, recognized_kind); |
3530 | 3498 |
3531 case MethodRecognizer::kInt32x4Select: { | 3499 case MethodRecognizer::kInt32x4Select: { |
3532 Definition* mask = call->ArgumentAt(0); | 3500 Definition* mask = call->ArgumentAt(0); |
3533 Definition* trueValue = call->ArgumentAt(1); | 3501 Definition* trueValue = call->ArgumentAt(1); |
3534 Definition* falseValue = call->ArgumentAt(2); | 3502 Definition* falseValue = call->ArgumentAt(2); |
3535 // Type check left. | 3503 // Type check left. |
3536 AddCheckClass(mask, | 3504 AddCheckClass(mask, |
3537 ICData::ZoneHandle( | 3505 ICData::ZoneHandle( |
3538 isolate(), | 3506 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3539 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
3540 call->deopt_id(), | 3507 call->deopt_id(), |
3541 call->env(), | 3508 call->env(), |
3542 call); | 3509 call); |
3543 Int32x4SelectInstr* select = new(isolate()) Int32x4SelectInstr( | 3510 Int32x4SelectInstr* select = new(I) Int32x4SelectInstr( |
3544 new(isolate()) Value(mask), | 3511 new(I) Value(mask), |
3545 new(isolate()) Value(trueValue), | 3512 new(I) Value(trueValue), |
3546 new(isolate()) Value(falseValue), | 3513 new(I) Value(falseValue), |
3547 call->deopt_id()); | 3514 call->deopt_id()); |
3548 ReplaceCall(call, select); | 3515 ReplaceCall(call, select); |
3549 return true; | 3516 return true; |
3550 } | 3517 } |
3551 case MethodRecognizer::kInt32x4WithFlagX: | 3518 case MethodRecognizer::kInt32x4WithFlagX: |
3552 case MethodRecognizer::kInt32x4WithFlagY: | 3519 case MethodRecognizer::kInt32x4WithFlagY: |
3553 case MethodRecognizer::kInt32x4WithFlagZ: | 3520 case MethodRecognizer::kInt32x4WithFlagZ: |
3554 case MethodRecognizer::kInt32x4WithFlagW: { | 3521 case MethodRecognizer::kInt32x4WithFlagW: { |
3555 Definition* left = call->ArgumentAt(0); | 3522 Definition* left = call->ArgumentAt(0); |
3556 Definition* flag = call->ArgumentAt(1); | 3523 Definition* flag = call->ArgumentAt(1); |
3557 // Type check left. | 3524 // Type check left. |
3558 AddCheckClass(left, | 3525 AddCheckClass(left, |
3559 ICData::ZoneHandle( | 3526 ICData::ZoneHandle( |
3560 isolate(), | 3527 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3561 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
3562 call->deopt_id(), | 3528 call->deopt_id(), |
3563 call->env(), | 3529 call->env(), |
3564 call); | 3530 call); |
3565 Int32x4SetFlagInstr* setFlag = new(isolate()) Int32x4SetFlagInstr( | 3531 Int32x4SetFlagInstr* setFlag = new(I) Int32x4SetFlagInstr( |
3566 recognized_kind, | 3532 recognized_kind, |
3567 new(isolate()) Value(left), | 3533 new(I) Value(left), |
3568 new(isolate()) Value(flag), | 3534 new(I) Value(flag), |
3569 call->deopt_id()); | 3535 call->deopt_id()); |
3570 ReplaceCall(call, setFlag); | 3536 ReplaceCall(call, setFlag); |
3571 return true; | 3537 return true; |
3572 } | 3538 } |
3573 default: | 3539 default: |
3574 return false; | 3540 return false; |
3575 } | 3541 } |
3576 } | 3542 } |
3577 | 3543 |
3578 | 3544 |
3579 bool FlowGraphOptimizer::InlineByteArrayViewLoad(Instruction* call, | 3545 bool FlowGraphOptimizer::InlineByteArrayViewLoad(Instruction* call, |
3580 Definition* receiver, | 3546 Definition* receiver, |
3581 intptr_t array_cid, | 3547 intptr_t array_cid, |
3582 intptr_t view_cid, | 3548 intptr_t view_cid, |
3583 const ICData& ic_data, | 3549 const ICData& ic_data, |
3584 TargetEntryInstr** entry, | 3550 TargetEntryInstr** entry, |
3585 Definition** last) { | 3551 Definition** last) { |
3586 ASSERT(array_cid != kIllegalCid); | 3552 ASSERT(array_cid != kIllegalCid); |
3587 Definition* array = receiver; | 3553 Definition* array = receiver; |
3588 Definition* index = call->ArgumentAt(1); | 3554 Definition* index = call->ArgumentAt(1); |
3589 *entry = new(isolate()) TargetEntryInstr(flow_graph()->allocate_block_id(), | 3555 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), |
3590 call->GetBlock()->try_index()); | 3556 call->GetBlock()->try_index()); |
3591 (*entry)->InheritDeoptTarget(isolate(), call); | 3557 (*entry)->InheritDeoptTarget(I, call); |
3592 Instruction* cursor = *entry; | 3558 Instruction* cursor = *entry; |
3593 | 3559 |
3594 array_cid = PrepareInlineByteArrayViewOp(call, | 3560 array_cid = PrepareInlineByteArrayViewOp(call, |
3595 array_cid, | 3561 array_cid, |
3596 view_cid, | 3562 view_cid, |
3597 &array, | 3563 &array, |
3598 index, | 3564 index, |
3599 &cursor); | 3565 &cursor); |
3600 | 3566 |
3601 intptr_t deopt_id = Isolate::kNoDeoptId; | 3567 intptr_t deopt_id = Isolate::kNoDeoptId; |
3602 if ((array_cid == kTypedDataInt32ArrayCid) || | 3568 if ((array_cid == kTypedDataInt32ArrayCid) || |
3603 (array_cid == kTypedDataUint32ArrayCid)) { | 3569 (array_cid == kTypedDataUint32ArrayCid)) { |
3604 // Set deopt_id if we can optimistically assume that the result is Smi. | 3570 // Set deopt_id if we can optimistically assume that the result is Smi. |
3605 // Assume mixed Mint/Smi if this instruction caused deoptimization once. | 3571 // Assume mixed Mint/Smi if this instruction caused deoptimization once. |
3606 deopt_id = ic_data.HasDeoptReasons() ? | 3572 deopt_id = ic_data.HasDeoptReasons() ? |
3607 Isolate::kNoDeoptId : call->deopt_id(); | 3573 Isolate::kNoDeoptId : call->deopt_id(); |
3608 } | 3574 } |
3609 | 3575 |
3610 *last = new(isolate()) LoadIndexedInstr(new(isolate()) Value(array), | 3576 *last = new(I) LoadIndexedInstr(new(I) Value(array), |
3611 new(isolate()) Value(index), | 3577 new(I) Value(index), |
3612 1, | 3578 1, |
3613 view_cid, | 3579 view_cid, |
3614 deopt_id, | 3580 deopt_id, |
3615 call->token_pos()); | 3581 call->token_pos()); |
3616 cursor = flow_graph()->AppendTo( | 3582 cursor = flow_graph()->AppendTo( |
3617 cursor, | 3583 cursor, |
3618 *last, | 3584 *last, |
3619 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 3585 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
3620 FlowGraph::kValue); | 3586 FlowGraph::kValue); |
3621 | 3587 |
3622 if (view_cid == kTypedDataFloat32ArrayCid) { | 3588 if (view_cid == kTypedDataFloat32ArrayCid) { |
3623 *last = new(isolate()) FloatToDoubleInstr( | 3589 *last = new(I) FloatToDoubleInstr(new(I) Value(*last), deopt_id); |
3624 new(isolate()) Value(*last), deopt_id); | |
3625 flow_graph()->AppendTo(cursor, | 3590 flow_graph()->AppendTo(cursor, |
3626 *last, | 3591 *last, |
3627 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 3592 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
3628 FlowGraph::kValue); | 3593 FlowGraph::kValue); |
3629 } | 3594 } |
3630 return true; | 3595 return true; |
3631 } | 3596 } |
3632 | 3597 |
3633 | 3598 |
3634 bool FlowGraphOptimizer::InlineByteArrayViewStore(const Function& target, | 3599 bool FlowGraphOptimizer::InlineByteArrayViewStore(const Function& target, |
3635 Instruction* call, | 3600 Instruction* call, |
3636 Definition* receiver, | 3601 Definition* receiver, |
3637 intptr_t array_cid, | 3602 intptr_t array_cid, |
3638 intptr_t view_cid, | 3603 intptr_t view_cid, |
3639 const ICData& ic_data, | 3604 const ICData& ic_data, |
3640 TargetEntryInstr** entry, | 3605 TargetEntryInstr** entry, |
3641 Definition** last) { | 3606 Definition** last) { |
3642 ASSERT(array_cid != kIllegalCid); | 3607 ASSERT(array_cid != kIllegalCid); |
3643 Definition* array = receiver; | 3608 Definition* array = receiver; |
3644 Definition* index = call->ArgumentAt(1); | 3609 Definition* index = call->ArgumentAt(1); |
3645 *entry = new(isolate()) TargetEntryInstr(flow_graph()->allocate_block_id(), | 3610 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), |
3646 call->GetBlock()->try_index()); | 3611 call->GetBlock()->try_index()); |
3647 (*entry)->InheritDeoptTarget(isolate(), call); | 3612 (*entry)->InheritDeoptTarget(I, call); |
3648 Instruction* cursor = *entry; | 3613 Instruction* cursor = *entry; |
3649 | 3614 |
3650 array_cid = PrepareInlineByteArrayViewOp(call, | 3615 array_cid = PrepareInlineByteArrayViewOp(call, |
3651 array_cid, | 3616 array_cid, |
3652 view_cid, | 3617 view_cid, |
3653 &array, | 3618 &array, |
3654 index, | 3619 index, |
3655 &cursor); | 3620 &cursor); |
3656 | 3621 |
3657 // Extract the instance call so we can use the function_name in the stored | 3622 // Extract the instance call so we can use the function_name in the stored |
3658 // value check ICData. | 3623 // value check ICData. |
3659 InstanceCallInstr* i_call = NULL; | 3624 InstanceCallInstr* i_call = NULL; |
3660 if (call->IsPolymorphicInstanceCall()) { | 3625 if (call->IsPolymorphicInstanceCall()) { |
3661 i_call = call->AsPolymorphicInstanceCall()->instance_call(); | 3626 i_call = call->AsPolymorphicInstanceCall()->instance_call(); |
3662 } else { | 3627 } else { |
3663 ASSERT(call->IsInstanceCall()); | 3628 ASSERT(call->IsInstanceCall()); |
3664 i_call = call->AsInstanceCall(); | 3629 i_call = call->AsInstanceCall(); |
3665 } | 3630 } |
3666 ASSERT(i_call != NULL); | 3631 ASSERT(i_call != NULL); |
3667 ICData& value_check = ICData::ZoneHandle(isolate()); | 3632 ICData& value_check = ICData::ZoneHandle(I); |
3668 switch (view_cid) { | 3633 switch (view_cid) { |
3669 case kTypedDataInt8ArrayCid: | 3634 case kTypedDataInt8ArrayCid: |
3670 case kTypedDataUint8ArrayCid: | 3635 case kTypedDataUint8ArrayCid: |
3671 case kTypedDataUint8ClampedArrayCid: | 3636 case kTypedDataUint8ClampedArrayCid: |
3672 case kExternalTypedDataUint8ArrayCid: | 3637 case kExternalTypedDataUint8ArrayCid: |
3673 case kExternalTypedDataUint8ClampedArrayCid: | 3638 case kExternalTypedDataUint8ClampedArrayCid: |
3674 case kTypedDataInt16ArrayCid: | 3639 case kTypedDataInt16ArrayCid: |
3675 case kTypedDataUint16ArrayCid: { | 3640 case kTypedDataUint16ArrayCid: { |
3676 // Check that value is always smi. | 3641 // Check that value is always smi. |
3677 value_check = ICData::New(flow_graph_->parsed_function().function(), | 3642 value_check = ICData::New(flow_graph_->parsed_function().function(), |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3732 UNREACHABLE(); | 3697 UNREACHABLE(); |
3733 } | 3698 } |
3734 | 3699 |
3735 Definition* stored_value = call->ArgumentAt(2); | 3700 Definition* stored_value = call->ArgumentAt(2); |
3736 if (!value_check.IsNull()) { | 3701 if (!value_check.IsNull()) { |
3737 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), | 3702 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), |
3738 call); | 3703 call); |
3739 } | 3704 } |
3740 | 3705 |
3741 if (view_cid == kTypedDataFloat32ArrayCid) { | 3706 if (view_cid == kTypedDataFloat32ArrayCid) { |
3742 stored_value = new(isolate()) DoubleToFloatInstr( | 3707 stored_value = new(I) DoubleToFloatInstr( |
3743 new(isolate()) Value(stored_value), call->deopt_id()); | 3708 new(I) Value(stored_value), call->deopt_id()); |
3744 cursor = flow_graph()->AppendTo(cursor, | 3709 cursor = flow_graph()->AppendTo(cursor, |
3745 stored_value, | 3710 stored_value, |
3746 NULL, | 3711 NULL, |
3747 FlowGraph::kValue); | 3712 FlowGraph::kValue); |
3748 } | 3713 } |
3749 | 3714 |
3750 StoreBarrierType needs_store_barrier = kNoStoreBarrier; | 3715 StoreBarrierType needs_store_barrier = kNoStoreBarrier; |
3751 *last = new(isolate()) StoreIndexedInstr(new(isolate()) Value(array), | 3716 *last = new(I) StoreIndexedInstr(new(I) Value(array), |
3752 new(isolate()) Value(index), | 3717 new(I) Value(index), |
3753 new(isolate()) Value(stored_value), | 3718 new(I) Value(stored_value), |
3754 needs_store_barrier, | 3719 needs_store_barrier, |
3755 1, // Index scale | 3720 1, // Index scale |
3756 view_cid, | 3721 view_cid, |
3757 call->deopt_id(), | 3722 call->deopt_id(), |
3758 call->token_pos()); | 3723 call->token_pos()); |
3759 | 3724 |
3760 flow_graph()->AppendTo(cursor, | 3725 flow_graph()->AppendTo(cursor, |
3761 *last, | 3726 *last, |
3762 call->deopt_id() != Isolate::kNoDeoptId ? | 3727 call->deopt_id() != Isolate::kNoDeoptId ? |
3763 call->env() : NULL, | 3728 call->env() : NULL, |
3764 FlowGraph::kEffect); | 3729 FlowGraph::kEffect); |
3765 return true; | 3730 return true; |
3766 } | 3731 } |
3767 | 3732 |
3768 | 3733 |
3769 | 3734 |
3770 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp( | 3735 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp( |
3771 Instruction* call, | 3736 Instruction* call, |
3772 intptr_t array_cid, | 3737 intptr_t array_cid, |
3773 intptr_t view_cid, | 3738 intptr_t view_cid, |
3774 Definition** array, | 3739 Definition** array, |
3775 Definition* byte_index, | 3740 Definition* byte_index, |
3776 Instruction** cursor) { | 3741 Instruction** cursor) { |
3777 // Insert byte_index smi check. | 3742 // Insert byte_index smi check. |
3778 *cursor = flow_graph()->AppendTo(*cursor, | 3743 *cursor = flow_graph()->AppendTo(*cursor, |
3779 new(isolate()) CheckSmiInstr( | 3744 new(I) CheckSmiInstr( |
3780 new(isolate()) Value(byte_index), | 3745 new(I) Value(byte_index), |
3781 call->deopt_id(), | 3746 call->deopt_id(), |
3782 call->token_pos()), | 3747 call->token_pos()), |
3783 call->env(), | 3748 call->env(), |
3784 FlowGraph::kEffect); | 3749 FlowGraph::kEffect); |
3785 | 3750 |
3786 LoadFieldInstr* length = | 3751 LoadFieldInstr* length = |
3787 new(isolate()) LoadFieldInstr( | 3752 new(I) LoadFieldInstr( |
3788 new(isolate()) Value(*array), | 3753 new(I) Value(*array), |
3789 CheckArrayBoundInstr::LengthOffsetFor(array_cid), | 3754 CheckArrayBoundInstr::LengthOffsetFor(array_cid), |
3790 Type::ZoneHandle(isolate(), Type::SmiType()), | 3755 Type::ZoneHandle(I, Type::SmiType()), |
3791 call->token_pos()); | 3756 call->token_pos()); |
3792 length->set_is_immutable(true); | 3757 length->set_is_immutable(true); |
3793 length->set_result_cid(kSmiCid); | 3758 length->set_result_cid(kSmiCid); |
3794 length->set_recognized_kind( | 3759 length->set_recognized_kind( |
3795 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); | 3760 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); |
3796 *cursor = flow_graph()->AppendTo(*cursor, | 3761 *cursor = flow_graph()->AppendTo(*cursor, |
3797 length, | 3762 length, |
3798 NULL, | 3763 NULL, |
3799 FlowGraph::kValue); | 3764 FlowGraph::kValue); |
3800 | 3765 |
3801 intptr_t element_size = Instance::ElementSizeFor(array_cid); | 3766 intptr_t element_size = Instance::ElementSizeFor(array_cid); |
3802 ConstantInstr* bytes_per_element = | 3767 ConstantInstr* bytes_per_element = |
3803 flow_graph()->GetConstant(Smi::Handle(isolate(), Smi::New(element_size))); | 3768 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(element_size))); |
3804 BinarySmiOpInstr* len_in_bytes = | 3769 BinarySmiOpInstr* len_in_bytes = |
3805 new(isolate()) BinarySmiOpInstr(Token::kMUL, | 3770 new(I) BinarySmiOpInstr(Token::kMUL, |
3806 new(isolate()) Value(length), | 3771 new(I) Value(length), |
3807 new(isolate()) Value(bytes_per_element), | 3772 new(I) Value(bytes_per_element), |
3808 call->deopt_id(), call->token_pos()); | 3773 call->deopt_id(), call->token_pos()); |
3809 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(), | 3774 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(), |
3810 FlowGraph::kValue); | 3775 FlowGraph::kValue); |
3811 | 3776 |
3812 ConstantInstr* length_adjustment = | 3777 ConstantInstr* length_adjustment = |
3813 flow_graph()->GetConstant(Smi::Handle(isolate(), Smi::New( | 3778 flow_graph()->GetConstant(Smi::Handle(I, Smi::New( |
3814 Instance::ElementSizeFor(view_cid) - 1))); | 3779 Instance::ElementSizeFor(view_cid) - 1))); |
3815 // adjusted_length = len_in_bytes - (element_size - 1). | 3780 // adjusted_length = len_in_bytes - (element_size - 1). |
3816 BinarySmiOpInstr* adjusted_length = | 3781 BinarySmiOpInstr* adjusted_length = |
3817 new(isolate()) BinarySmiOpInstr(Token::kSUB, | 3782 new(I) BinarySmiOpInstr(Token::kSUB, |
3818 new(isolate()) Value(len_in_bytes), | 3783 new(I) Value(len_in_bytes), |
3819 new(isolate()) Value(length_adjustment), | 3784 new(I) Value(length_adjustment), |
3820 call->deopt_id(), call->token_pos()); | 3785 call->deopt_id(), call->token_pos()); |
3821 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(), | 3786 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(), |
3822 FlowGraph::kValue); | 3787 FlowGraph::kValue); |
3823 | 3788 |
3824 // Check adjusted_length > 0. | 3789 // Check adjusted_length > 0. |
3825 ConstantInstr* zero = | 3790 ConstantInstr* zero = |
3826 flow_graph()->GetConstant(Smi::Handle(isolate(), Smi::New(0))); | 3791 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(0))); |
3827 *cursor = flow_graph()->AppendTo(*cursor, | 3792 *cursor = flow_graph()->AppendTo(*cursor, |
3828 new(isolate()) CheckArrayBoundInstr( | 3793 new(I) CheckArrayBoundInstr( |
3829 new(isolate()) Value(adjusted_length), | 3794 new(I) Value(adjusted_length), |
3830 new(isolate()) Value(zero), | 3795 new(I) Value(zero), |
3831 call->deopt_id()), | 3796 call->deopt_id()), |
3832 call->env(), | 3797 call->env(), |
3833 FlowGraph::kEffect); | 3798 FlowGraph::kEffect); |
3834 // Check 0 <= byte_index < adjusted_length. | 3799 // Check 0 <= byte_index < adjusted_length. |
3835 *cursor = flow_graph()->AppendTo(*cursor, | 3800 *cursor = flow_graph()->AppendTo(*cursor, |
3836 new(isolate()) CheckArrayBoundInstr( | 3801 new(I) CheckArrayBoundInstr( |
3837 new(isolate()) Value(adjusted_length), | 3802 new(I) Value(adjusted_length), |
3838 new(isolate()) Value(byte_index), | 3803 new(I) Value(byte_index), |
3839 call->deopt_id()), | 3804 call->deopt_id()), |
3840 call->env(), | 3805 call->env(), |
3841 FlowGraph::kEffect); | 3806 FlowGraph::kEffect); |
3842 | 3807 |
3843 if (RawObject::IsExternalTypedDataClassId(array_cid)) { | 3808 if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
3844 LoadUntaggedInstr* elements = | 3809 LoadUntaggedInstr* elements = |
3845 new(isolate()) LoadUntaggedInstr(new(isolate()) Value(*array), | 3810 new(I) LoadUntaggedInstr(new(I) Value(*array), |
3846 ExternalTypedData::data_offset()); | 3811 ExternalTypedData::data_offset()); |
3847 *cursor = flow_graph()->AppendTo(*cursor, | 3812 *cursor = flow_graph()->AppendTo(*cursor, |
3848 elements, | 3813 elements, |
3849 NULL, | 3814 NULL, |
3850 FlowGraph::kValue); | 3815 FlowGraph::kValue); |
3851 *array = elements; | 3816 *array = elements; |
3852 } | 3817 } |
3853 return array_cid; | 3818 return array_cid; |
3854 } | 3819 } |
3855 | 3820 |
3856 | 3821 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3894 // check. | 3859 // check. |
3895 RawBool* FlowGraphOptimizer::InstanceOfAsBool( | 3860 RawBool* FlowGraphOptimizer::InstanceOfAsBool( |
3896 const ICData& ic_data, | 3861 const ICData& ic_data, |
3897 const AbstractType& type, | 3862 const AbstractType& type, |
3898 ZoneGrowableArray<intptr_t>* results) const { | 3863 ZoneGrowableArray<intptr_t>* results) const { |
3899 ASSERT(results->is_empty()); | 3864 ASSERT(results->is_empty()); |
3900 ASSERT(ic_data.NumArgsTested() == 1); // Unary checks only. | 3865 ASSERT(ic_data.NumArgsTested() == 1); // Unary checks only. |
3901 if (!type.IsInstantiated() || type.IsMalformedOrMalbounded()) { | 3866 if (!type.IsInstantiated() || type.IsMalformedOrMalbounded()) { |
3902 return Bool::null(); | 3867 return Bool::null(); |
3903 } | 3868 } |
3904 const Class& type_class = Class::Handle(isolate(), type.type_class()); | 3869 const Class& type_class = Class::Handle(I, type.type_class()); |
3905 const intptr_t num_type_args = type_class.NumTypeArguments(); | 3870 const intptr_t num_type_args = type_class.NumTypeArguments(); |
3906 if (num_type_args > 0) { | 3871 if (num_type_args > 0) { |
3907 // Only raw types can be directly compared, thus disregarding type | 3872 // Only raw types can be directly compared, thus disregarding type |
3908 // arguments. | 3873 // arguments. |
3909 const intptr_t num_type_params = type_class.NumTypeParameters(); | 3874 const intptr_t num_type_params = type_class.NumTypeParameters(); |
3910 const intptr_t from_index = num_type_args - num_type_params; | 3875 const intptr_t from_index = num_type_args - num_type_params; |
3911 const TypeArguments& type_arguments = | 3876 const TypeArguments& type_arguments = |
3912 TypeArguments::Handle(isolate(), type.arguments()); | 3877 TypeArguments::Handle(I, type.arguments()); |
3913 const bool is_raw_type = type_arguments.IsNull() || | 3878 const bool is_raw_type = type_arguments.IsNull() || |
3914 type_arguments.IsRaw(from_index, num_type_params); | 3879 type_arguments.IsRaw(from_index, num_type_params); |
3915 if (!is_raw_type) { | 3880 if (!is_raw_type) { |
3916 // Unknown result. | 3881 // Unknown result. |
3917 return Bool::null(); | 3882 return Bool::null(); |
3918 } | 3883 } |
3919 } | 3884 } |
3920 | 3885 |
3921 const ClassTable& class_table = *isolate()->class_table(); | 3886 const ClassTable& class_table = *isolate()->class_table(); |
3922 Bool& prev = Bool::Handle(isolate(), Bool::null()); | 3887 Bool& prev = Bool::Handle(I); |
3923 Class& cls = Class::Handle(isolate(), Class::null()); | 3888 Class& cls = Class::Handle(I); |
3924 | 3889 |
3925 bool results_differ = false; | 3890 bool results_differ = false; |
3926 for (int i = 0; i < ic_data.NumberOfChecks(); i++) { | 3891 for (int i = 0; i < ic_data.NumberOfChecks(); i++) { |
3927 cls = class_table.At(ic_data.GetReceiverClassIdAt(i)); | 3892 cls = class_table.At(ic_data.GetReceiverClassIdAt(i)); |
3928 if (cls.NumTypeArguments() > 0) { | 3893 if (cls.NumTypeArguments() > 0) { |
3929 return Bool::null(); | 3894 return Bool::null(); |
3930 } | 3895 } |
3931 const bool is_subtype = cls.IsSubtypeOf( | 3896 const bool is_subtype = cls.IsSubtypeOf( |
3932 TypeArguments::Handle(isolate(), TypeArguments::null()), | 3897 TypeArguments::Handle(I), |
3933 type_class, | 3898 type_class, |
3934 TypeArguments::Handle(isolate(), TypeArguments::null()), | 3899 TypeArguments::Handle(I), |
3935 NULL); | 3900 NULL); |
3936 results->Add(cls.id()); | 3901 results->Add(cls.id()); |
3937 results->Add(is_subtype); | 3902 results->Add(is_subtype); |
3938 if (prev.IsNull()) { | 3903 if (prev.IsNull()) { |
3939 prev = Bool::Get(is_subtype).raw(); | 3904 prev = Bool::Get(is_subtype).raw(); |
3940 } else { | 3905 } else { |
3941 if (is_subtype != prev.value()) { | 3906 if (is_subtype != prev.value()) { |
3942 results_differ = true; | 3907 results_differ = true; |
3943 } | 3908 } |
3944 } | 3909 } |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4036 void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { | 4001 void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { |
4037 ASSERT(Token::IsTypeTestOperator(call->token_kind())); | 4002 ASSERT(Token::IsTypeTestOperator(call->token_kind())); |
4038 Definition* left = call->ArgumentAt(0); | 4003 Definition* left = call->ArgumentAt(0); |
4039 Definition* instantiator = call->ArgumentAt(1); | 4004 Definition* instantiator = call->ArgumentAt(1); |
4040 Definition* type_args = call->ArgumentAt(2); | 4005 Definition* type_args = call->ArgumentAt(2); |
4041 const AbstractType& type = | 4006 const AbstractType& type = |
4042 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); | 4007 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); |
4043 const bool negate = Bool::Cast( | 4008 const bool negate = Bool::Cast( |
4044 call->ArgumentAt(4)->OriginalDefinition()->AsConstant()->value()).value(); | 4009 call->ArgumentAt(4)->OriginalDefinition()->AsConstant()->value()).value(); |
4045 const ICData& unary_checks = | 4010 const ICData& unary_checks = |
4046 ICData::ZoneHandle(isolate(), call->ic_data()->AsUnaryClassChecks()); | 4011 ICData::ZoneHandle(I, call->ic_data()->AsUnaryClassChecks()); |
4047 if (FLAG_warn_on_javascript_compatibility && | 4012 if (FLAG_warn_on_javascript_compatibility && |
4048 !unary_checks.IssuedJSWarning() && | 4013 !unary_checks.IssuedJSWarning() && |
4049 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { | 4014 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { |
4050 // No warning was reported yet for this type check, either because it has | 4015 // No warning was reported yet for this type check, either because it has |
4051 // not been executed yet, or because no problematic combinations of instance | 4016 // not been executed yet, or because no problematic combinations of instance |
4052 // type and test type have been encountered so far. A warning may still be | 4017 // type and test type have been encountered so far. A warning may still be |
4053 // reported, so do not replace the instance call. | 4018 // reported, so do not replace the instance call. |
4054 return; | 4019 return; |
4055 } | 4020 } |
4056 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { | 4021 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { |
4057 ZoneGrowableArray<intptr_t>* results = | 4022 ZoneGrowableArray<intptr_t>* results = |
4058 new(isolate()) ZoneGrowableArray<intptr_t>( | 4023 new(I) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); |
4059 unary_checks.NumberOfChecks() * 2); | |
4060 Bool& as_bool = | 4024 Bool& as_bool = |
4061 Bool::ZoneHandle(isolate(), | 4025 Bool::ZoneHandle(I, InstanceOfAsBool(unary_checks, type, results)); |
4062 InstanceOfAsBool(unary_checks, type, results)); | |
4063 if (as_bool.IsNull()) { | 4026 if (as_bool.IsNull()) { |
4064 if (results->length() == unary_checks.NumberOfChecks() * 2) { | 4027 if (results->length() == unary_checks.NumberOfChecks() * 2) { |
4065 const bool can_deopt = TryExpandTestCidsResult(results, type); | 4028 const bool can_deopt = TryExpandTestCidsResult(results, type); |
4066 TestCidsInstr* test_cids = new(isolate()) TestCidsInstr( | 4029 TestCidsInstr* test_cids = new(I) TestCidsInstr( |
4067 call->token_pos(), | 4030 call->token_pos(), |
4068 negate ? Token::kISNOT : Token::kIS, | 4031 negate ? Token::kISNOT : Token::kIS, |
4069 new(isolate()) Value(left), | 4032 new(I) Value(left), |
4070 *results, | 4033 *results, |
4071 can_deopt ? call->deopt_id() : Isolate::kNoDeoptId); | 4034 can_deopt ? call->deopt_id() : Isolate::kNoDeoptId); |
4072 // Remove type. | 4035 // Remove type. |
4073 ReplaceCall(call, test_cids); | 4036 ReplaceCall(call, test_cids); |
4074 return; | 4037 return; |
4075 } | 4038 } |
4076 } else { | 4039 } else { |
4077 // TODO(srdjan): Use TestCidsInstr also for this case. | 4040 // TODO(srdjan): Use TestCidsInstr also for this case. |
4078 // One result only. | 4041 // One result only. |
4079 AddReceiverCheck(call); | 4042 AddReceiverCheck(call); |
4080 if (negate) { | 4043 if (negate) { |
4081 as_bool = Bool::Get(!as_bool.value()).raw(); | 4044 as_bool = Bool::Get(!as_bool.value()).raw(); |
4082 } | 4045 } |
4083 ConstantInstr* bool_const = flow_graph()->GetConstant(as_bool); | 4046 ConstantInstr* bool_const = flow_graph()->GetConstant(as_bool); |
4084 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 4047 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
4085 PushArgumentInstr* push = call->PushArgumentAt(i); | 4048 PushArgumentInstr* push = call->PushArgumentAt(i); |
4086 push->ReplaceUsesWith(push->value()->definition()); | 4049 push->ReplaceUsesWith(push->value()->definition()); |
4087 push->RemoveFromGraph(); | 4050 push->RemoveFromGraph(); |
4088 } | 4051 } |
4089 call->ReplaceUsesWith(bool_const); | 4052 call->ReplaceUsesWith(bool_const); |
4090 ASSERT(current_iterator()->Current() == call); | 4053 ASSERT(current_iterator()->Current() == call); |
4091 current_iterator()->RemoveCurrentFromGraph(); | 4054 current_iterator()->RemoveCurrentFromGraph(); |
4092 return; | 4055 return; |
4093 } | 4056 } |
4094 } | 4057 } |
4095 | 4058 |
4096 if (TypeCheckAsClassEquality(type)) { | 4059 if (TypeCheckAsClassEquality(type)) { |
4097 LoadClassIdInstr* left_cid = | 4060 LoadClassIdInstr* left_cid = new(I) LoadClassIdInstr(new(I) Value(left)); |
4098 new(isolate()) LoadClassIdInstr(new(isolate()) Value(left)); | |
4099 InsertBefore(call, | 4061 InsertBefore(call, |
4100 left_cid, | 4062 left_cid, |
4101 NULL, | 4063 NULL, |
4102 FlowGraph::kValue); | 4064 FlowGraph::kValue); |
4103 const intptr_t type_cid = Class::Handle(isolate(), type.type_class()).id(); | 4065 const intptr_t type_cid = Class::Handle(I, type.type_class()).id(); |
4104 ConstantInstr* cid = | 4066 ConstantInstr* cid = |
4105 flow_graph()->GetConstant(Smi::Handle(isolate(), Smi::New(type_cid))); | 4067 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(type_cid))); |
4106 | 4068 |
4107 StrictCompareInstr* check_cid = | 4069 StrictCompareInstr* check_cid = |
4108 new(isolate()) StrictCompareInstr( | 4070 new(I) StrictCompareInstr( |
4109 call->token_pos(), | 4071 call->token_pos(), |
4110 negate ? Token::kNE_STRICT : Token::kEQ_STRICT, | 4072 negate ? Token::kNE_STRICT : Token::kEQ_STRICT, |
4111 new(isolate()) Value(left_cid), | 4073 new(I) Value(left_cid), |
4112 new(isolate()) Value(cid), | 4074 new(I) Value(cid), |
4113 false); // No number check. | 4075 false); // No number check. |
4114 ReplaceCall(call, check_cid); | 4076 ReplaceCall(call, check_cid); |
4115 return; | 4077 return; |
4116 } | 4078 } |
4117 | 4079 |
4118 InstanceOfInstr* instance_of = | 4080 InstanceOfInstr* instance_of = |
4119 new(isolate()) InstanceOfInstr(call->token_pos(), | 4081 new(I) InstanceOfInstr(call->token_pos(), |
4120 new(isolate()) Value(left), | 4082 new(I) Value(left), |
4121 new(isolate()) Value(instantiator), | 4083 new(I) Value(instantiator), |
4122 new(isolate()) Value(type_args), | 4084 new(I) Value(type_args), |
4123 type, | 4085 type, |
4124 negate, | 4086 negate, |
4125 call->deopt_id()); | 4087 call->deopt_id()); |
4126 ReplaceCall(call, instance_of); | 4088 ReplaceCall(call, instance_of); |
4127 } | 4089 } |
4128 | 4090 |
4129 | 4091 |
4130 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). | 4092 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). |
4131 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { | 4093 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { |
4132 ASSERT(Token::IsTypeCastOperator(call->token_kind())); | 4094 ASSERT(Token::IsTypeCastOperator(call->token_kind())); |
4133 Definition* left = call->ArgumentAt(0); | 4095 Definition* left = call->ArgumentAt(0); |
4134 Definition* instantiator = call->ArgumentAt(1); | 4096 Definition* instantiator = call->ArgumentAt(1); |
4135 Definition* type_args = call->ArgumentAt(2); | 4097 Definition* type_args = call->ArgumentAt(2); |
4136 const AbstractType& type = | 4098 const AbstractType& type = |
4137 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); | 4099 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); |
4138 ASSERT(!type.IsMalformedOrMalbounded()); | 4100 ASSERT(!type.IsMalformedOrMalbounded()); |
4139 const ICData& unary_checks = | 4101 const ICData& unary_checks = |
4140 ICData::ZoneHandle(isolate(), call->ic_data()->AsUnaryClassChecks()); | 4102 ICData::ZoneHandle(I, call->ic_data()->AsUnaryClassChecks()); |
4141 if (FLAG_warn_on_javascript_compatibility && | 4103 if (FLAG_warn_on_javascript_compatibility && |
4142 !unary_checks.IssuedJSWarning() && | 4104 !unary_checks.IssuedJSWarning() && |
4143 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { | 4105 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { |
4144 // No warning was reported yet for this type check, either because it has | 4106 // No warning was reported yet for this type check, either because it has |
4145 // not been executed yet, or because no problematic combinations of instance | 4107 // not been executed yet, or because no problematic combinations of instance |
4146 // type and test type have been encountered so far. A warning may still be | 4108 // type and test type have been encountered so far. A warning may still be |
4147 // reported, so do not replace the instance call. | 4109 // reported, so do not replace the instance call. |
4148 return; | 4110 return; |
4149 } | 4111 } |
4150 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { | 4112 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { |
4151 ZoneGrowableArray<intptr_t>* results = | 4113 ZoneGrowableArray<intptr_t>* results = |
4152 new(isolate()) ZoneGrowableArray<intptr_t>( | 4114 new(I) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); |
4153 unary_checks.NumberOfChecks() * 2); | 4115 const Bool& as_bool = Bool::ZoneHandle(I, |
4154 const Bool& as_bool = Bool::ZoneHandle(isolate(), | |
4155 InstanceOfAsBool(unary_checks, type, results)); | 4116 InstanceOfAsBool(unary_checks, type, results)); |
4156 if (as_bool.raw() == Bool::True().raw()) { | 4117 if (as_bool.raw() == Bool::True().raw()) { |
4157 AddReceiverCheck(call); | 4118 AddReceiverCheck(call); |
4158 // Remove the original push arguments. | 4119 // Remove the original push arguments. |
4159 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 4120 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
4160 PushArgumentInstr* push = call->PushArgumentAt(i); | 4121 PushArgumentInstr* push = call->PushArgumentAt(i); |
4161 push->ReplaceUsesWith(push->value()->definition()); | 4122 push->ReplaceUsesWith(push->value()->definition()); |
4162 push->RemoveFromGraph(); | 4123 push->RemoveFromGraph(); |
4163 } | 4124 } |
4164 // Remove call, replace it with 'left'. | 4125 // Remove call, replace it with 'left'. |
4165 call->ReplaceUsesWith(left); | 4126 call->ReplaceUsesWith(left); |
4166 ASSERT(current_iterator()->Current() == call); | 4127 ASSERT(current_iterator()->Current() == call); |
4167 current_iterator()->RemoveCurrentFromGraph(); | 4128 current_iterator()->RemoveCurrentFromGraph(); |
4168 return; | 4129 return; |
4169 } | 4130 } |
4170 } | 4131 } |
4171 const String& dst_name = String::ZoneHandle(isolate(), | 4132 const String& dst_name = String::ZoneHandle(I, |
4172 Symbols::New(Exceptions::kCastErrorDstName)); | 4133 Symbols::New(Exceptions::kCastErrorDstName)); |
4173 AssertAssignableInstr* assert_as = | 4134 AssertAssignableInstr* assert_as = |
4174 new(isolate()) AssertAssignableInstr(call->token_pos(), | 4135 new(I) AssertAssignableInstr(call->token_pos(), |
4175 new(isolate()) Value(left), | 4136 new(I) Value(left), |
4176 new(isolate()) Value(instantiator), | 4137 new(I) Value(instantiator), |
4177 new(isolate()) Value(type_args), | 4138 new(I) Value(type_args), |
4178 type, | 4139 type, |
4179 dst_name); | 4140 dst_name); |
4180 // Newly inserted instructions that can deoptimize or throw an exception | 4141 // Newly inserted instructions that can deoptimize or throw an exception |
4181 // must have a deoptimization id that is valid for lookup in the unoptimized | 4142 // must have a deoptimization id that is valid for lookup in the unoptimized |
4182 // code. | 4143 // code. |
4183 assert_as->deopt_id_ = call->deopt_id(); | 4144 assert_as->deopt_id_ = call->deopt_id(); |
4184 ReplaceCall(call, assert_as); | 4145 ReplaceCall(call, assert_as); |
4185 } | 4146 } |
4186 | 4147 |
4187 | 4148 |
4188 // Tries to optimize instance call by replacing it with a faster instruction | 4149 // Tries to optimize instance call by replacing it with a faster instruction |
4189 // (e.g, binary op, field load, ..). | 4150 // (e.g, binary op, field load, ..). |
4190 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { | 4151 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
4191 if (!instr->HasICData() || (instr->ic_data()->NumberOfChecks() == 0)) { | 4152 if (!instr->HasICData() || (instr->ic_data()->NumberOfChecks() == 0)) { |
4192 return; | 4153 return; |
4193 } | 4154 } |
4194 | 4155 |
4195 const Token::Kind op_kind = instr->token_kind(); | 4156 const Token::Kind op_kind = instr->token_kind(); |
4196 // Type test is special as it always gets converted into inlined code. | 4157 // Type test is special as it always gets converted into inlined code. |
4197 if (Token::IsTypeTestOperator(op_kind)) { | 4158 if (Token::IsTypeTestOperator(op_kind)) { |
4198 ReplaceWithInstanceOf(instr); | 4159 ReplaceWithInstanceOf(instr); |
4199 return; | 4160 return; |
4200 } | 4161 } |
4201 | 4162 |
4202 if (Token::IsTypeCastOperator(op_kind)) { | 4163 if (Token::IsTypeCastOperator(op_kind)) { |
4203 ReplaceWithTypeCast(instr); | 4164 ReplaceWithTypeCast(instr); |
4204 return; | 4165 return; |
4205 } | 4166 } |
4206 | 4167 |
4207 const ICData& unary_checks = | 4168 const ICData& unary_checks = |
4208 ICData::ZoneHandle(isolate(), instr->ic_data()->AsUnaryClassChecks()); | 4169 ICData::ZoneHandle(I, instr->ic_data()->AsUnaryClassChecks()); |
4209 | 4170 |
4210 intptr_t max_checks = (op_kind == Token::kEQ) | 4171 intptr_t max_checks = (op_kind == Token::kEQ) |
4211 ? FLAG_max_equality_polymorphic_checks | 4172 ? FLAG_max_equality_polymorphic_checks |
4212 : FLAG_max_polymorphic_checks; | 4173 : FLAG_max_polymorphic_checks; |
4213 if ((unary_checks.NumberOfChecks() > max_checks) && | 4174 if ((unary_checks.NumberOfChecks() > max_checks) && |
4214 InstanceCallNeedsClassCheck(instr)) { | 4175 InstanceCallNeedsClassCheck(instr)) { |
4215 // Too many checks, it will be megamorphic which needs unary checks. | 4176 // Too many checks, it will be megamorphic which needs unary checks. |
4216 instr->set_ic_data(&unary_checks); | 4177 instr->set_ic_data(&unary_checks); |
4217 return; | 4178 return; |
4218 } | 4179 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4251 if (TryInlineInstanceMethod(instr)) { | 4212 if (TryInlineInstanceMethod(instr)) { |
4252 return; | 4213 return; |
4253 } | 4214 } |
4254 | 4215 |
4255 bool has_one_target = unary_checks.HasOneTarget(); | 4216 bool has_one_target = unary_checks.HasOneTarget(); |
4256 | 4217 |
4257 if (has_one_target) { | 4218 if (has_one_target) { |
4258 // Check if the single target is a polymorphic target, if it is, | 4219 // Check if the single target is a polymorphic target, if it is, |
4259 // we don't have one target. | 4220 // we don't have one target. |
4260 const Function& target = | 4221 const Function& target = |
4261 Function::Handle(isolate(), unary_checks.GetTargetAt(0)); | 4222 Function::Handle(I, unary_checks.GetTargetAt(0)); |
4262 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); | 4223 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); |
4263 has_one_target = !polymorphic_target; | 4224 has_one_target = !polymorphic_target; |
4264 } | 4225 } |
4265 | 4226 |
4266 if (has_one_target) { | 4227 if (has_one_target) { |
4267 const bool is_method_extraction = | 4228 const bool is_method_extraction = |
4268 Function::Handle(isolate(), | 4229 Function::Handle(I, unary_checks.GetTargetAt(0)).IsMethodExtractor(); |
4269 unary_checks.GetTargetAt(0)).IsMethodExtractor(); | |
4270 | 4230 |
4271 if ((is_method_extraction && !MethodExtractorNeedsClassCheck(instr)) || | 4231 if ((is_method_extraction && !MethodExtractorNeedsClassCheck(instr)) || |
4272 (!is_method_extraction && !InstanceCallNeedsClassCheck(instr))) { | 4232 (!is_method_extraction && !InstanceCallNeedsClassCheck(instr))) { |
4273 const bool call_with_checks = false; | 4233 const bool call_with_checks = false; |
4274 PolymorphicInstanceCallInstr* call = | 4234 PolymorphicInstanceCallInstr* call = |
4275 new(isolate()) PolymorphicInstanceCallInstr(instr, unary_checks, | 4235 new(I) PolymorphicInstanceCallInstr(instr, unary_checks, |
4276 call_with_checks); | 4236 call_with_checks); |
4277 instr->ReplaceWith(call, current_iterator()); | 4237 instr->ReplaceWith(call, current_iterator()); |
4278 return; | 4238 return; |
4279 } | 4239 } |
4280 } | 4240 } |
4281 | 4241 |
4282 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { | 4242 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { |
4283 bool call_with_checks; | 4243 bool call_with_checks; |
4284 if (has_one_target) { | 4244 if (has_one_target) { |
4285 // Type propagation has not run yet, we cannot eliminate the check. | 4245 // Type propagation has not run yet, we cannot eliminate the check. |
4286 AddReceiverCheck(instr); | 4246 AddReceiverCheck(instr); |
4287 // Call can still deoptimize, do not detach environment from instr. | 4247 // Call can still deoptimize, do not detach environment from instr. |
4288 call_with_checks = false; | 4248 call_with_checks = false; |
4289 } else { | 4249 } else { |
4290 call_with_checks = true; | 4250 call_with_checks = true; |
4291 } | 4251 } |
4292 PolymorphicInstanceCallInstr* call = | 4252 PolymorphicInstanceCallInstr* call = |
4293 new(isolate()) PolymorphicInstanceCallInstr(instr, unary_checks, | 4253 new(I) PolymorphicInstanceCallInstr(instr, unary_checks, |
4294 call_with_checks); | 4254 call_with_checks); |
4295 instr->ReplaceWith(call, current_iterator()); | 4255 instr->ReplaceWith(call, current_iterator()); |
4296 } | 4256 } |
4297 } | 4257 } |
4298 | 4258 |
4299 | 4259 |
4300 void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) { | 4260 void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) { |
4301 if (!CanUnboxDouble()) { | 4261 if (!CanUnboxDouble()) { |
4302 return; | 4262 return; |
4303 } | 4263 } |
4304 MethodRecognizer::Kind recognized_kind = | 4264 MethodRecognizer::Kind recognized_kind = |
4305 MethodRecognizer::RecognizeKind(call->function()); | 4265 MethodRecognizer::RecognizeKind(call->function()); |
4306 MathUnaryInstr::MathUnaryKind unary_kind; | 4266 MathUnaryInstr::MathUnaryKind unary_kind; |
4307 switch (recognized_kind) { | 4267 switch (recognized_kind) { |
4308 case MethodRecognizer::kMathSqrt: | 4268 case MethodRecognizer::kMathSqrt: |
4309 unary_kind = MathUnaryInstr::kSqrt; | 4269 unary_kind = MathUnaryInstr::kSqrt; |
4310 break; | 4270 break; |
4311 case MethodRecognizer::kMathSin: | 4271 case MethodRecognizer::kMathSin: |
4312 unary_kind = MathUnaryInstr::kSin; | 4272 unary_kind = MathUnaryInstr::kSin; |
4313 break; | 4273 break; |
4314 case MethodRecognizer::kMathCos: | 4274 case MethodRecognizer::kMathCos: |
4315 unary_kind = MathUnaryInstr::kCos; | 4275 unary_kind = MathUnaryInstr::kCos; |
4316 break; | 4276 break; |
4317 default: | 4277 default: |
4318 unary_kind = MathUnaryInstr::kIllegal; | 4278 unary_kind = MathUnaryInstr::kIllegal; |
4319 break; | 4279 break; |
4320 } | 4280 } |
4321 if (unary_kind != MathUnaryInstr::kIllegal) { | 4281 if (unary_kind != MathUnaryInstr::kIllegal) { |
4322 MathUnaryInstr* math_unary = | 4282 MathUnaryInstr* math_unary = |
4323 new(isolate()) MathUnaryInstr(unary_kind, | 4283 new(I) MathUnaryInstr(unary_kind, |
4324 new(isolate()) Value(call->ArgumentAt(0)), | 4284 new(I) Value(call->ArgumentAt(0)), |
4325 call->deopt_id()); | 4285 call->deopt_id()); |
4326 ReplaceCall(call, math_unary); | 4286 ReplaceCall(call, math_unary); |
4327 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) || | 4287 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) || |
4328 (recognized_kind == MethodRecognizer::kFloat32x4Splat) || | 4288 (recognized_kind == MethodRecognizer::kFloat32x4Splat) || |
4329 (recognized_kind == MethodRecognizer::kFloat32x4Constructor) || | 4289 (recognized_kind == MethodRecognizer::kFloat32x4Constructor) || |
4330 (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2)) { | 4290 (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2)) { |
4331 TryInlineFloat32x4Constructor(call, recognized_kind); | 4291 TryInlineFloat32x4Constructor(call, recognized_kind); |
4332 } else if ((recognized_kind == MethodRecognizer::kFloat64x2Constructor) || | 4292 } else if ((recognized_kind == MethodRecognizer::kFloat64x2Constructor) || |
4333 (recognized_kind == MethodRecognizer::kFloat64x2Zero) || | 4293 (recognized_kind == MethodRecognizer::kFloat64x2Zero) || |
4334 (recognized_kind == MethodRecognizer::kFloat64x2Splat) || | 4294 (recognized_kind == MethodRecognizer::kFloat64x2Splat) || |
4335 (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4)) { | 4295 (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4)) { |
(...skipping 18 matching lines...) Expand all Loading... |
4354 // being either doubles or smis. | 4314 // being either doubles or smis. |
4355 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { | 4315 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { |
4356 const ICData& ic_data = *call->ic_data(); | 4316 const ICData& ic_data = *call->ic_data(); |
4357 intptr_t result_cid = kIllegalCid; | 4317 intptr_t result_cid = kIllegalCid; |
4358 if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, kDoubleCid)) { | 4318 if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, kDoubleCid)) { |
4359 result_cid = kDoubleCid; | 4319 result_cid = kDoubleCid; |
4360 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { | 4320 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { |
4361 result_cid = kSmiCid; | 4321 result_cid = kSmiCid; |
4362 } | 4322 } |
4363 if (result_cid != kIllegalCid) { | 4323 if (result_cid != kIllegalCid) { |
4364 MathMinMaxInstr* min_max = new(isolate()) MathMinMaxInstr( | 4324 MathMinMaxInstr* min_max = new(I) MathMinMaxInstr( |
4365 recognized_kind, | 4325 recognized_kind, |
4366 new(isolate()) Value(call->ArgumentAt(0)), | 4326 new(I) Value(call->ArgumentAt(0)), |
4367 new(isolate()) Value(call->ArgumentAt(1)), | 4327 new(I) Value(call->ArgumentAt(1)), |
4368 call->deopt_id(), | 4328 call->deopt_id(), |
4369 result_cid); | 4329 result_cid); |
4370 const ICData& unary_checks = | 4330 const ICData& unary_checks = |
4371 ICData::ZoneHandle(isolate(), ic_data.AsUnaryClassChecks()); | 4331 ICData::ZoneHandle(I, ic_data.AsUnaryClassChecks()); |
4372 AddCheckClass(min_max->left()->definition(), | 4332 AddCheckClass(min_max->left()->definition(), |
4373 unary_checks, | 4333 unary_checks, |
4374 call->deopt_id(), | 4334 call->deopt_id(), |
4375 call->env(), | 4335 call->env(), |
4376 call); | 4336 call); |
4377 AddCheckClass(min_max->right()->definition(), | 4337 AddCheckClass(min_max->right()->definition(), |
4378 unary_checks, | 4338 unary_checks, |
4379 call->deopt_id(), | 4339 call->deopt_id(), |
4380 call->env(), | 4340 call->env(), |
4381 call); | 4341 call); |
4382 ReplaceCall(call, min_max); | 4342 ReplaceCall(call, min_max); |
4383 } | 4343 } |
4384 } | 4344 } |
4385 } else if (recognized_kind == MethodRecognizer::kMathDoublePow) { | 4345 } else if (recognized_kind == MethodRecognizer::kMathDoublePow) { |
4386 // We know that first argument is double, the second is num. | 4346 // We know that first argument is double, the second is num. |
4387 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble | 4347 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble |
4388 // instructions contain type checks and conversions to double. | 4348 // instructions contain type checks and conversions to double. |
4389 ZoneGrowableArray<Value*>* args = | 4349 ZoneGrowableArray<Value*>* args = |
4390 new(isolate()) ZoneGrowableArray<Value*>(call->ArgumentCount()); | 4350 new(I) ZoneGrowableArray<Value*>(call->ArgumentCount()); |
4391 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | 4351 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { |
4392 args->Add(new(isolate()) Value(call->ArgumentAt(i))); | 4352 args->Add(new(I) Value(call->ArgumentAt(i))); |
4393 } | 4353 } |
4394 InvokeMathCFunctionInstr* invoke = | 4354 InvokeMathCFunctionInstr* invoke = |
4395 new(isolate()) InvokeMathCFunctionInstr(args, | 4355 new(I) InvokeMathCFunctionInstr(args, |
4396 call->deopt_id(), | 4356 call->deopt_id(), |
4397 recognized_kind, | 4357 recognized_kind, |
4398 call->token_pos()); | 4358 call->token_pos()); |
4399 ReplaceCall(call, invoke); | 4359 ReplaceCall(call, invoke); |
4400 } else if (recognized_kind == MethodRecognizer::kObjectArrayConstructor) { | 4360 } else if (recognized_kind == MethodRecognizer::kObjectArrayConstructor) { |
4401 Value* type = new(isolate()) Value(call->ArgumentAt(0)); | 4361 Value* type = new(I) Value(call->ArgumentAt(0)); |
4402 Value* num_elements = new(isolate()) Value(call->ArgumentAt(1)); | 4362 Value* num_elements = new(I) Value(call->ArgumentAt(1)); |
4403 CreateArrayInstr* create_array = | 4363 CreateArrayInstr* create_array = |
4404 new(isolate()) CreateArrayInstr(call->token_pos(), type, num_elements); | 4364 new(I) CreateArrayInstr(call->token_pos(), type, num_elements); |
4405 ReplaceCall(call, create_array); | 4365 ReplaceCall(call, create_array); |
4406 } else if (Library::PrivateCoreLibName(Symbols::ClassId()).Equals( | 4366 } else if (Library::PrivateCoreLibName(Symbols::ClassId()).Equals( |
4407 String::Handle(isolate(), call->function().name()))) { | 4367 String::Handle(I, call->function().name()))) { |
4408 // Check for core library get:_classId. | 4368 // Check for core library get:_classId. |
4409 intptr_t cid = Class::Handle(isolate(), call->function().Owner()).id(); | 4369 intptr_t cid = Class::Handle(I, call->function().Owner()).id(); |
4410 // Currently only implemented for a subset of classes. | 4370 // Currently only implemented for a subset of classes. |
4411 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || | 4371 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || |
4412 (cid == kExternalOneByteStringCid) || | 4372 (cid == kExternalOneByteStringCid) || |
4413 (cid == kGrowableObjectArrayCid) || | 4373 (cid == kGrowableObjectArrayCid) || |
4414 (cid == kImmutableArrayCid) || (cid == kArrayCid)); | 4374 (cid == kImmutableArrayCid) || (cid == kArrayCid)); |
4415 ConstantInstr* cid_instr = | 4375 ConstantInstr* cid_instr = |
4416 new(isolate()) ConstantInstr(Smi::Handle(isolate(), Smi::New(cid))); | 4376 new(I) ConstantInstr(Smi::Handle(I, Smi::New(cid))); |
4417 ReplaceCall(call, cid_instr); | 4377 ReplaceCall(call, cid_instr); |
4418 } else if (call->function().IsFactory()) { | 4378 } else if (call->function().IsFactory()) { |
4419 const Class& function_class = | 4379 const Class& function_class = |
4420 Class::Handle(isolate(), call->function().Owner()); | 4380 Class::Handle(I, call->function().Owner()); |
4421 if ((function_class.library() == Library::CoreLibrary()) || | 4381 if ((function_class.library() == Library::CoreLibrary()) || |
4422 (function_class.library() == Library::TypedDataLibrary())) { | 4382 (function_class.library() == Library::TypedDataLibrary())) { |
4423 intptr_t cid = FactoryRecognizer::ResultCid(call->function()); | 4383 intptr_t cid = FactoryRecognizer::ResultCid(call->function()); |
4424 switch (cid) { | 4384 switch (cid) { |
4425 case kArrayCid: { | 4385 case kArrayCid: { |
4426 Value* type = new(isolate()) Value(call->ArgumentAt(0)); | 4386 Value* type = new(I) Value(call->ArgumentAt(0)); |
4427 Value* num_elements = new(isolate()) Value(call->ArgumentAt(1)); | 4387 Value* num_elements = new(I) Value(call->ArgumentAt(1)); |
4428 if (num_elements->BindsToConstant() && | 4388 if (num_elements->BindsToConstant() && |
4429 num_elements->BoundConstant().IsSmi()) { | 4389 num_elements->BoundConstant().IsSmi()) { |
4430 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); | 4390 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); |
4431 if (length >= 0 && length <= Array::kMaxElements) { | 4391 if (length >= 0 && length <= Array::kMaxElements) { |
4432 CreateArrayInstr* create_array = | 4392 CreateArrayInstr* create_array = |
4433 new(isolate()) CreateArrayInstr( | 4393 new(I) CreateArrayInstr( |
4434 call->token_pos(), type, num_elements); | 4394 call->token_pos(), type, num_elements); |
4435 ReplaceCall(call, create_array); | 4395 ReplaceCall(call, create_array); |
4436 } | 4396 } |
4437 } | 4397 } |
4438 } | 4398 } |
4439 default: | 4399 default: |
4440 break; | 4400 break; |
4441 } | 4401 } |
4442 } | 4402 } |
4443 } | 4403 } |
4444 } | 4404 } |
4445 | 4405 |
4446 | 4406 |
4447 void FlowGraphOptimizer::VisitStoreInstanceField( | 4407 void FlowGraphOptimizer::VisitStoreInstanceField( |
4448 StoreInstanceFieldInstr* instr) { | 4408 StoreInstanceFieldInstr* instr) { |
4449 if (instr->IsUnboxedStore()) { | 4409 if (instr->IsUnboxedStore()) { |
4450 ASSERT(instr->is_initialization_); | 4410 ASSERT(instr->is_initialization_); |
4451 // Determine if this field should be unboxed based on the usage of getter | 4411 // Determine if this field should be unboxed based on the usage of getter |
4452 // and setter functions: The heuristic requires that the setter has a | 4412 // and setter functions: The heuristic requires that the setter has a |
4453 // usage count of at least 1/kGetterSetterRatio of the getter usage count. | 4413 // usage count of at least 1/kGetterSetterRatio of the getter usage count. |
4454 // This is to avoid unboxing fields where the setter is never or rarely | 4414 // This is to avoid unboxing fields where the setter is never or rarely |
4455 // executed. | 4415 // executed. |
4456 const Field& field = Field::ZoneHandle(isolate(), instr->field().raw()); | 4416 const Field& field = Field::ZoneHandle(I, instr->field().raw()); |
4457 const String& field_name = String::Handle(isolate(), field.name()); | 4417 const String& field_name = String::Handle(I, field.name()); |
4458 class Class& owner = Class::Handle(isolate(), field.owner()); | 4418 class Class& owner = Class::Handle(I, field.owner()); |
4459 const Function& getter = | 4419 const Function& getter = |
4460 Function::Handle(isolate(), owner.LookupGetterFunction(field_name)); | 4420 Function::Handle(I, owner.LookupGetterFunction(field_name)); |
4461 const Function& setter = | 4421 const Function& setter = |
4462 Function::Handle(isolate(), owner.LookupSetterFunction(field_name)); | 4422 Function::Handle(I, owner.LookupSetterFunction(field_name)); |
4463 bool result = !getter.IsNull() | 4423 bool result = !getter.IsNull() |
4464 && !setter.IsNull() | 4424 && !setter.IsNull() |
4465 && (setter.usage_counter() > 0) | 4425 && (setter.usage_counter() > 0) |
4466 && (FLAG_getter_setter_ratio * setter.usage_counter() > | 4426 && (FLAG_getter_setter_ratio * setter.usage_counter() > |
4467 getter.usage_counter()); | 4427 getter.usage_counter()); |
4468 if (!result) { | 4428 if (!result) { |
4469 if (FLAG_trace_optimization) { | 4429 if (FLAG_trace_optimization) { |
4470 OS::Print("Disabling unboxing of %s\n", field.ToCString()); | 4430 OS::Print("Disabling unboxing of %s\n", field.ToCString()); |
4471 } | 4431 } |
4472 field.set_is_unboxing_candidate(false); | 4432 field.set_is_unboxing_candidate(false); |
(...skipping 18 matching lines...) Expand all Loading... |
4491 ASSERT(instr->HasICData()); | 4451 ASSERT(instr->HasICData()); |
4492 if (unary_ic_data.NumberOfChecks() == 0) { | 4452 if (unary_ic_data.NumberOfChecks() == 0) { |
4493 // No type feedback collected. | 4453 // No type feedback collected. |
4494 return false; | 4454 return false; |
4495 } | 4455 } |
4496 if (!unary_ic_data.HasOneTarget()) { | 4456 if (!unary_ic_data.HasOneTarget()) { |
4497 // Polymorphic sites are inlined like normal method calls by conventional | 4457 // Polymorphic sites are inlined like normal method calls by conventional |
4498 // inlining. | 4458 // inlining. |
4499 return false; | 4459 return false; |
4500 } | 4460 } |
4501 Function& target = Function::Handle(isolate(), Function::null()); | 4461 Function& target = Function::Handle(I); |
4502 intptr_t class_id; | 4462 intptr_t class_id; |
4503 unary_ic_data.GetOneClassCheckAt(0, &class_id, &target); | 4463 unary_ic_data.GetOneClassCheckAt(0, &class_id, &target); |
4504 if (target.kind() != RawFunction::kImplicitSetter) { | 4464 if (target.kind() != RawFunction::kImplicitSetter) { |
4505 // Non-implicit setter are inlined like normal method calls. | 4465 // Non-implicit setter are inlined like normal method calls. |
4506 return false; | 4466 return false; |
4507 } | 4467 } |
4508 // Inline implicit instance setter. | 4468 // Inline implicit instance setter. |
4509 const String& field_name = | 4469 const String& field_name = |
4510 String::Handle(isolate(), Field::NameFromSetter(instr->function_name())); | 4470 String::Handle(I, Field::NameFromSetter(instr->function_name())); |
4511 const Field& field = | 4471 const Field& field = |
4512 Field::ZoneHandle(isolate(), GetField(class_id, field_name)); | 4472 Field::ZoneHandle(I, GetField(class_id, field_name)); |
4513 ASSERT(!field.IsNull()); | 4473 ASSERT(!field.IsNull()); |
4514 | 4474 |
4515 if (InstanceCallNeedsClassCheck(instr)) { | 4475 if (InstanceCallNeedsClassCheck(instr)) { |
4516 AddReceiverCheck(instr); | 4476 AddReceiverCheck(instr); |
4517 } | 4477 } |
4518 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; | 4478 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; |
4519 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) { | 4479 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) { |
4520 InsertBefore(instr, | 4480 InsertBefore(instr, |
4521 new(isolate()) CheckSmiInstr( | 4481 new(I) CheckSmiInstr( |
4522 new(isolate()) Value(instr->ArgumentAt(1)), | 4482 new(I) Value(instr->ArgumentAt(1)), |
4523 instr->deopt_id(), | 4483 instr->deopt_id(), |
4524 instr->token_pos()), | 4484 instr->token_pos()), |
4525 instr->env(), | 4485 instr->env(), |
4526 FlowGraph::kEffect); | 4486 FlowGraph::kEffect); |
4527 needs_store_barrier = kNoStoreBarrier; | 4487 needs_store_barrier = kNoStoreBarrier; |
4528 } | 4488 } |
4529 | 4489 |
4530 if (field.guarded_cid() != kDynamicCid) { | 4490 if (field.guarded_cid() != kDynamicCid) { |
4531 InsertBefore(instr, | 4491 InsertBefore(instr, |
4532 new(isolate()) GuardFieldClassInstr( | 4492 new(I) GuardFieldClassInstr( |
4533 new(isolate()) Value(instr->ArgumentAt(1)), | 4493 new(I) Value(instr->ArgumentAt(1)), |
4534 field, | 4494 field, |
4535 instr->deopt_id()), | 4495 instr->deopt_id()), |
4536 instr->env(), | 4496 instr->env(), |
4537 FlowGraph::kEffect); | 4497 FlowGraph::kEffect); |
4538 } | 4498 } |
4539 | 4499 |
4540 if (field.needs_length_check()) { | 4500 if (field.needs_length_check()) { |
4541 InsertBefore(instr, | 4501 InsertBefore(instr, |
4542 new(isolate()) GuardFieldLengthInstr( | 4502 new(I) GuardFieldLengthInstr( |
4543 new(isolate()) Value(instr->ArgumentAt(1)), | 4503 new(I) Value(instr->ArgumentAt(1)), |
4544 field, | 4504 field, |
4545 instr->deopt_id()), | 4505 instr->deopt_id()), |
4546 instr->env(), | 4506 instr->env(), |
4547 FlowGraph::kEffect); | 4507 FlowGraph::kEffect); |
4548 } | 4508 } |
4549 | 4509 |
4550 // Field guard was detached. | 4510 // Field guard was detached. |
4551 StoreInstanceFieldInstr* store = new(isolate()) StoreInstanceFieldInstr( | 4511 StoreInstanceFieldInstr* store = new(I) StoreInstanceFieldInstr( |
4552 field, | 4512 field, |
4553 new(isolate()) Value(instr->ArgumentAt(0)), | 4513 new(I) Value(instr->ArgumentAt(0)), |
4554 new(isolate()) Value(instr->ArgumentAt(1)), | 4514 new(I) Value(instr->ArgumentAt(1)), |
4555 needs_store_barrier, | 4515 needs_store_barrier, |
4556 instr->token_pos()); | 4516 instr->token_pos()); |
4557 | 4517 |
4558 if (store->IsUnboxedStore()) { | 4518 if (store->IsUnboxedStore()) { |
4559 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | 4519 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
4560 } | 4520 } |
4561 | 4521 |
4562 // Discard the environment from the original instruction because the store | 4522 // Discard the environment from the original instruction because the store |
4563 // can't deoptimize. | 4523 // can't deoptimize. |
4564 instr->RemoveEnvironment(); | 4524 instr->RemoveEnvironment(); |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4798 | 4758 |
4799 | 4759 |
4800 // Given a boundary (right operand) and a comparison operation return | 4760 // Given a boundary (right operand) and a comparison operation return |
4801 // a symbolic range constraint for the left operand of the comparison assuming | 4761 // a symbolic range constraint for the left operand of the comparison assuming |
4802 // that it evaluated to true. | 4762 // that it evaluated to true. |
4803 // For example for the comparison a < b symbol a is constrained with range | 4763 // For example for the comparison a < b symbol a is constrained with range |
4804 // [Smi::kMinValue, b - 1]. | 4764 // [Smi::kMinValue, b - 1]. |
4805 Range* RangeAnalysis::ConstraintRange(Token::Kind op, Definition* boundary) { | 4765 Range* RangeAnalysis::ConstraintRange(Token::Kind op, Definition* boundary) { |
4806 switch (op) { | 4766 switch (op) { |
4807 case Token::kEQ: | 4767 case Token::kEQ: |
4808 return new(isolate()) Range(RangeBoundary::FromDefinition(boundary), | 4768 return new(I) Range(RangeBoundary::FromDefinition(boundary), |
4809 RangeBoundary::FromDefinition(boundary)); | 4769 RangeBoundary::FromDefinition(boundary)); |
4810 case Token::kNE: | 4770 case Token::kNE: |
4811 return Range::Unknown(); | 4771 return Range::Unknown(); |
4812 case Token::kLT: | 4772 case Token::kLT: |
4813 return new(isolate()) Range(RangeBoundary::MinSmi(), | 4773 return new(I) Range(RangeBoundary::MinSmi(), |
4814 RangeBoundary::FromDefinition(boundary, -1)); | 4774 RangeBoundary::FromDefinition(boundary, -1)); |
4815 case Token::kGT: | 4775 case Token::kGT: |
4816 return new(isolate()) Range(RangeBoundary::FromDefinition(boundary, 1), | 4776 return new(I) Range(RangeBoundary::FromDefinition(boundary, 1), |
4817 RangeBoundary::MaxSmi()); | 4777 RangeBoundary::MaxSmi()); |
4818 case Token::kLTE: | 4778 case Token::kLTE: |
4819 return new(isolate()) Range(RangeBoundary::MinSmi(), | 4779 return new(I) Range(RangeBoundary::MinSmi(), |
4820 RangeBoundary::FromDefinition(boundary)); | 4780 RangeBoundary::FromDefinition(boundary)); |
4821 case Token::kGTE: | 4781 case Token::kGTE: |
4822 return new(isolate()) Range(RangeBoundary::FromDefinition(boundary), | 4782 return new(I) Range(RangeBoundary::FromDefinition(boundary), |
4823 RangeBoundary::MaxSmi()); | 4783 RangeBoundary::MaxSmi()); |
4824 default: | 4784 default: |
4825 UNREACHABLE(); | 4785 UNREACHABLE(); |
4826 return Range::Unknown(); | 4786 return Range::Unknown(); |
4827 } | 4787 } |
4828 } | 4788 } |
4829 | 4789 |
4830 | 4790 |
4831 ConstraintInstr* RangeAnalysis::InsertConstraintFor(Definition* defn, | 4791 ConstraintInstr* RangeAnalysis::InsertConstraintFor(Definition* defn, |
4832 Range* constraint_range, | 4792 Range* constraint_range, |
4833 Instruction* after) { | 4793 Instruction* after) { |
4834 // No need to constrain constants. | 4794 // No need to constrain constants. |
4835 if (defn->IsConstant()) return NULL; | 4795 if (defn->IsConstant()) return NULL; |
4836 | 4796 |
4837 ConstraintInstr* constraint = new(isolate()) ConstraintInstr( | 4797 ConstraintInstr* constraint = new(I) ConstraintInstr( |
4838 new(isolate()) Value(defn), constraint_range); | 4798 new(I) Value(defn), constraint_range); |
4839 flow_graph_->InsertAfter(after, constraint, NULL, FlowGraph::kValue); | 4799 flow_graph_->InsertAfter(after, constraint, NULL, FlowGraph::kValue); |
4840 RenameDominatedUses(defn, constraint, constraint); | 4800 RenameDominatedUses(defn, constraint, constraint); |
4841 constraints_.Add(constraint); | 4801 constraints_.Add(constraint); |
4842 return constraint; | 4802 return constraint; |
4843 } | 4803 } |
4844 | 4804 |
4845 | 4805 |
4846 void RangeAnalysis::ConstrainValueAfterBranch(Definition* defn, Value* use) { | 4806 void RangeAnalysis::ConstrainValueAfterBranch(Definition* defn, Value* use) { |
4847 BranchInstr* branch = use->instruction()->AsBranch(); | 4807 BranchInstr* branch = use->instruction()->AsBranch(); |
4848 RelationalOpInstr* rel_op = branch->comparison()->AsRelationalOp(); | 4808 RelationalOpInstr* rel_op = branch->comparison()->AsRelationalOp(); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4903 } | 4863 } |
4904 } | 4864 } |
4905 } | 4865 } |
4906 | 4866 |
4907 | 4867 |
4908 void RangeAnalysis::ConstrainValueAfterCheckArrayBound( | 4868 void RangeAnalysis::ConstrainValueAfterCheckArrayBound( |
4909 Definition* defn, CheckArrayBoundInstr* check, intptr_t use_index) { | 4869 Definition* defn, CheckArrayBoundInstr* check, intptr_t use_index) { |
4910 Range* constraint_range = NULL; | 4870 Range* constraint_range = NULL; |
4911 if (use_index == CheckArrayBoundInstr::kIndexPos) { | 4871 if (use_index == CheckArrayBoundInstr::kIndexPos) { |
4912 Definition* length = check->length()->definition(); | 4872 Definition* length = check->length()->definition(); |
4913 constraint_range = new(isolate()) Range( | 4873 constraint_range = new(I) Range( |
4914 RangeBoundary::FromConstant(0), | 4874 RangeBoundary::FromConstant(0), |
4915 RangeBoundary::FromDefinition(length, -1)); | 4875 RangeBoundary::FromDefinition(length, -1)); |
4916 } else { | 4876 } else { |
4917 ASSERT(use_index == CheckArrayBoundInstr::kLengthPos); | 4877 ASSERT(use_index == CheckArrayBoundInstr::kLengthPos); |
4918 Definition* index = check->index()->definition(); | 4878 Definition* index = check->index()->definition(); |
4919 constraint_range = new(isolate()) Range( | 4879 constraint_range = new(I) Range( |
4920 RangeBoundary::FromDefinition(index, 1), | 4880 RangeBoundary::FromDefinition(index, 1), |
4921 RangeBoundary::MaxSmi()); | 4881 RangeBoundary::MaxSmi()); |
4922 } | 4882 } |
4923 InsertConstraintFor(defn, constraint_range, check); | 4883 InsertConstraintFor(defn, constraint_range, check); |
4924 } | 4884 } |
4925 | 4885 |
4926 | 4886 |
4927 void RangeAnalysis::InsertConstraints() { | 4887 void RangeAnalysis::InsertConstraints() { |
4928 for (intptr_t i = 0; i < smi_checks_.length(); i++) { | 4888 for (intptr_t i = 0; i < smi_checks_.length(); i++) { |
4929 CheckSmiInstr* check = smi_checks_[i]; | 4889 CheckSmiInstr* check = smi_checks_[i]; |
4930 InsertConstraintFor(check->value()->definition(), Range::Unknown(), check); | 4890 InsertConstraintFor(check->value()->definition(), Range::Unknown(), check); |
4931 } | 4891 } |
4932 | 4892 |
4933 for (intptr_t i = 0; i < smi_values_.length(); i++) { | 4893 for (intptr_t i = 0; i < smi_values_.length(); i++) { |
4934 InsertConstraintsFor(smi_values_[i]); | 4894 InsertConstraintsFor(smi_values_[i]); |
4935 } | 4895 } |
4936 | 4896 |
4937 for (intptr_t i = 0; i < constraints_.length(); i++) { | 4897 for (intptr_t i = 0; i < constraints_.length(); i++) { |
4938 InsertConstraintsFor(constraints_[i]); | 4898 InsertConstraintsFor(constraints_[i]); |
4939 } | 4899 } |
4940 } | 4900 } |
4941 | 4901 |
4942 | 4902 |
4943 void RangeAnalysis::ResetWorklist() { | 4903 void RangeAnalysis::ResetWorklist() { |
4944 if (marked_defns_ == NULL) { | 4904 if (marked_defns_ == NULL) { |
4945 marked_defns_ = new(isolate()) BitVector( | 4905 marked_defns_ = new(I) BitVector(flow_graph_->current_ssa_temp_index()); |
4946 flow_graph_->current_ssa_temp_index()); | |
4947 } else { | 4906 } else { |
4948 marked_defns_->Clear(); | 4907 marked_defns_->Clear(); |
4949 } | 4908 } |
4950 worklist_.Clear(); | 4909 worklist_.Clear(); |
4951 } | 4910 } |
4952 | 4911 |
4953 | 4912 |
4954 void RangeAnalysis::MarkDefinition(Definition* defn) { | 4913 void RangeAnalysis::MarkDefinition(Definition* defn) { |
4955 // Unwrap constrained value. | 4914 // Unwrap constrained value. |
4956 while (defn->IsConstraint()) { | 4915 while (defn->IsConstraint()) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5054 } | 5013 } |
5055 } | 5014 } |
5056 | 5015 |
5057 | 5016 |
5058 // We transitively discovered all dependencies of the given phi | 5017 // We transitively discovered all dependencies of the given phi |
5059 // and confirmed that it depends on a single value coming from outside of | 5018 // and confirmed that it depends on a single value coming from outside of |
5060 // the loop and some linear combinations of itself. | 5019 // the loop and some linear combinations of itself. |
5061 // Compute the range based on initial value and the direction of the growth. | 5020 // Compute the range based on initial value and the direction of the growth. |
5062 switch (direction) { | 5021 switch (direction) { |
5063 case kPositive: | 5022 case kPositive: |
5064 return new(isolate()) Range(RangeBoundary::FromDefinition(initial_value), | 5023 return new(I) Range(RangeBoundary::FromDefinition(initial_value), |
5065 RangeBoundary::MaxSmi()); | 5024 RangeBoundary::MaxSmi()); |
5066 | 5025 |
5067 case kNegative: | 5026 case kNegative: |
5068 return new(isolate()) Range(RangeBoundary::MinSmi(), | 5027 return new(I) Range(RangeBoundary::MinSmi(), |
5069 RangeBoundary::FromDefinition(initial_value)); | 5028 RangeBoundary::FromDefinition(initial_value)); |
5070 | 5029 |
5071 case kUnknown: | 5030 case kUnknown: |
5072 case kBoth: | 5031 case kBoth: |
5073 return Range::Unknown(); | 5032 return Range::Unknown(); |
5074 } | 5033 } |
5075 | 5034 |
5076 UNREACHABLE(); | 5035 UNREACHABLE(); |
5077 return NULL; | 5036 return NULL; |
5078 } | 5037 } |
5079 | 5038 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5119 } | 5078 } |
5120 | 5079 |
5121 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { | 5080 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { |
5122 InferRangesRecursive(block->dominated_blocks()[i]); | 5081 InferRangesRecursive(block->dominated_blocks()[i]); |
5123 } | 5082 } |
5124 } | 5083 } |
5125 | 5084 |
5126 | 5085 |
5127 void RangeAnalysis::InferRanges() { | 5086 void RangeAnalysis::InferRanges() { |
5128 // Initialize bitvector for quick filtering of smi values. | 5087 // Initialize bitvector for quick filtering of smi values. |
5129 smi_definitions_ = | 5088 smi_definitions_ = new(I) BitVector(flow_graph_->current_ssa_temp_index()); |
5130 new(isolate()) BitVector(flow_graph_->current_ssa_temp_index()); | |
5131 for (intptr_t i = 0; i < smi_values_.length(); i++) { | 5089 for (intptr_t i = 0; i < smi_values_.length(); i++) { |
5132 smi_definitions_->Add(smi_values_[i]->ssa_temp_index()); | 5090 smi_definitions_->Add(smi_values_[i]->ssa_temp_index()); |
5133 } | 5091 } |
5134 for (intptr_t i = 0; i < constraints_.length(); i++) { | 5092 for (intptr_t i = 0; i < constraints_.length(); i++) { |
5135 smi_definitions_->Add(constraints_[i]->ssa_temp_index()); | 5093 smi_definitions_->Add(constraints_[i]->ssa_temp_index()); |
5136 } | 5094 } |
5137 | 5095 |
5138 // Infer initial values of ranges. | 5096 // Infer initial values of ranges. |
5139 const GrowableArray<Definition*>& initial = | 5097 const GrowableArray<Definition*>& initial = |
5140 *flow_graph_->graph_entry()->initial_definitions(); | 5098 *flow_graph_->graph_entry()->initial_definitions(); |
(...skipping 1350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6491 kill_(graph_->preorder().length()), | 6449 kill_(graph_->preorder().length()), |
6492 exposed_values_(graph_->preorder().length()), | 6450 exposed_values_(graph_->preorder().length()), |
6493 out_values_(graph_->preorder().length()), | 6451 out_values_(graph_->preorder().length()), |
6494 phis_(5), | 6452 phis_(5), |
6495 worklist_(5), | 6453 worklist_(5), |
6496 in_worklist_(NULL), | 6454 in_worklist_(NULL), |
6497 forwarded_(false) { | 6455 forwarded_(false) { |
6498 const intptr_t num_blocks = graph_->preorder().length(); | 6456 const intptr_t num_blocks = graph_->preorder().length(); |
6499 for (intptr_t i = 0; i < num_blocks; i++) { | 6457 for (intptr_t i = 0; i < num_blocks; i++) { |
6500 out_.Add(NULL); | 6458 out_.Add(NULL); |
6501 gen_.Add(new(isolate()) BitVector(aliased_set_->max_place_id())); | 6459 gen_.Add(new(I) BitVector(aliased_set_->max_place_id())); |
6502 kill_.Add(new(isolate()) BitVector(aliased_set_->max_place_id())); | 6460 kill_.Add(new(I) BitVector(aliased_set_->max_place_id())); |
6503 in_.Add(new(isolate()) BitVector(aliased_set_->max_place_id())); | 6461 in_.Add(new(I) BitVector(aliased_set_->max_place_id())); |
6504 | 6462 |
6505 exposed_values_.Add(NULL); | 6463 exposed_values_.Add(NULL); |
6506 out_values_.Add(NULL); | 6464 out_values_.Add(NULL); |
6507 } | 6465 } |
6508 } | 6466 } |
6509 | 6467 |
6510 Isolate* isolate() const { return graph_->isolate(); } | 6468 Isolate* isolate() const { return graph_->isolate(); } |
6511 | 6469 |
6512 static bool OptimizeGraph(FlowGraph* graph) { | 6470 static bool OptimizeGraph(FlowGraph* graph) { |
6513 ASSERT(FLAG_load_cse); | 6471 ASSERT(FLAG_load_cse); |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6692 defn->ReplaceUsesWith(replacement); | 6650 defn->ReplaceUsesWith(replacement); |
6693 instr_it.RemoveCurrentFromGraph(); | 6651 instr_it.RemoveCurrentFromGraph(); |
6694 forwarded_ = true; | 6652 forwarded_ = true; |
6695 continue; | 6653 continue; |
6696 } else if (!kill->Contains(place_id)) { | 6654 } else if (!kill->Contains(place_id)) { |
6697 // This is an exposed load: it is the first representative of a | 6655 // This is an exposed load: it is the first representative of a |
6698 // given expression id and it is not killed on the path from | 6656 // given expression id and it is not killed on the path from |
6699 // the block entry. | 6657 // the block entry. |
6700 if (exposed_values == NULL) { | 6658 if (exposed_values == NULL) { |
6701 static const intptr_t kMaxExposedValuesInitialSize = 5; | 6659 static const intptr_t kMaxExposedValuesInitialSize = 5; |
6702 exposed_values = new(isolate()) ZoneGrowableArray<Definition*>( | 6660 exposed_values = new(I) ZoneGrowableArray<Definition*>( |
6703 Utils::Minimum(kMaxExposedValuesInitialSize, | 6661 Utils::Minimum(kMaxExposedValuesInitialSize, |
6704 aliased_set_->max_place_id())); | 6662 aliased_set_->max_place_id())); |
6705 } | 6663 } |
6706 | 6664 |
6707 exposed_values->Add(defn); | 6665 exposed_values->Add(defn); |
6708 } | 6666 } |
6709 | 6667 |
6710 gen->Add(place_id); | 6668 gen->Add(place_id); |
6711 | 6669 |
6712 if (out_values == NULL) out_values = CreateBlockOutValues(); | 6670 if (out_values == NULL) out_values = CreateBlockOutValues(); |
(...skipping 27 matching lines...) Expand all Loading... |
6740 | 6698 |
6741 out->Remove(to); | 6699 out->Remove(to); |
6742 } | 6700 } |
6743 | 6701 |
6744 out->AddAll(forwarded_loads); | 6702 out->AddAll(forwarded_loads); |
6745 } | 6703 } |
6746 | 6704 |
6747 // Compute OUT sets by propagating them iteratively until fix point | 6705 // Compute OUT sets by propagating them iteratively until fix point |
6748 // is reached. | 6706 // is reached. |
6749 void ComputeOutSets() { | 6707 void ComputeOutSets() { |
6750 BitVector* temp = new(isolate()) BitVector(aliased_set_->max_place_id()); | 6708 BitVector* temp = new(I) BitVector(aliased_set_->max_place_id()); |
6751 BitVector* forwarded_loads = | 6709 BitVector* forwarded_loads = new(I) BitVector(aliased_set_->max_place_id()); |
6752 new(isolate()) BitVector(aliased_set_->max_place_id()); | 6710 BitVector* temp_out = new(I) BitVector(aliased_set_->max_place_id()); |
6753 BitVector* temp_out = | |
6754 new(isolate()) BitVector(aliased_set_->max_place_id()); | |
6755 | 6711 |
6756 bool changed = true; | 6712 bool changed = true; |
6757 while (changed) { | 6713 while (changed) { |
6758 changed = false; | 6714 changed = false; |
6759 | 6715 |
6760 for (BlockIterator block_it = graph_->reverse_postorder_iterator(); | 6716 for (BlockIterator block_it = graph_->reverse_postorder_iterator(); |
6761 !block_it.Done(); | 6717 !block_it.Done(); |
6762 block_it.Advance()) { | 6718 block_it.Advance()) { |
6763 BlockEntryInstr* block = block_it.Current(); | 6719 BlockEntryInstr* block = block_it.Current(); |
6764 | 6720 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6796 if (!temp->Equals(*block_in) || (block_out == NULL)) { | 6752 if (!temp->Equals(*block_in) || (block_out == NULL)) { |
6797 // If IN set has changed propagate the change to OUT set. | 6753 // If IN set has changed propagate the change to OUT set. |
6798 block_in->CopyFrom(temp); | 6754 block_in->CopyFrom(temp); |
6799 | 6755 |
6800 temp->RemoveAll(block_kill); | 6756 temp->RemoveAll(block_kill); |
6801 temp->AddAll(block_gen); | 6757 temp->AddAll(block_gen); |
6802 | 6758 |
6803 if ((block_out == NULL) || !block_out->Equals(*temp)) { | 6759 if ((block_out == NULL) || !block_out->Equals(*temp)) { |
6804 if (block_out == NULL) { | 6760 if (block_out == NULL) { |
6805 block_out = out_[preorder_number] = | 6761 block_out = out_[preorder_number] = |
6806 new(isolate()) BitVector(aliased_set_->max_place_id()); | 6762 new(I) BitVector(aliased_set_->max_place_id()); |
6807 } | 6763 } |
6808 block_out->CopyFrom(temp); | 6764 block_out->CopyFrom(temp); |
6809 changed = true; | 6765 changed = true; |
6810 } | 6766 } |
6811 } | 6767 } |
6812 } | 6768 } |
6813 } | 6769 } |
6814 } | 6770 } |
6815 | 6771 |
6816 // Compute out_values mappings by propagating them in reverse postorder once | 6772 // Compute out_values mappings by propagating them in reverse postorder once |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6849 out_values_[preorder_number] = block_out_values = | 6805 out_values_[preorder_number] = block_out_values = |
6850 CreateBlockOutValues(); | 6806 CreateBlockOutValues(); |
6851 } | 6807 } |
6852 | 6808 |
6853 if ((*block_out_values)[place_id] == NULL) { | 6809 if ((*block_out_values)[place_id] == NULL) { |
6854 ASSERT(block->PredecessorCount() > 0); | 6810 ASSERT(block->PredecessorCount() > 0); |
6855 Definition* in_value = can_merge_eagerly ? | 6811 Definition* in_value = can_merge_eagerly ? |
6856 MergeIncomingValues(block, place_id) : NULL; | 6812 MergeIncomingValues(block, place_id) : NULL; |
6857 if ((in_value == NULL) && | 6813 if ((in_value == NULL) && |
6858 (in_[preorder_number]->Contains(place_id))) { | 6814 (in_[preorder_number]->Contains(place_id))) { |
6859 PhiInstr* phi = new(isolate()) PhiInstr(block->AsJoinEntry(), | 6815 PhiInstr* phi = new(I) PhiInstr(block->AsJoinEntry(), |
6860 block->PredecessorCount()); | 6816 block->PredecessorCount()); |
6861 phi->set_place_id(place_id); | 6817 phi->set_place_id(place_id); |
6862 pending_phis.Add(phi); | 6818 pending_phis.Add(phi); |
6863 in_value = phi; | 6819 in_value = phi; |
6864 } | 6820 } |
6865 (*block_out_values)[place_id] = in_value; | 6821 (*block_out_values)[place_id] = in_value; |
6866 } | 6822 } |
6867 } | 6823 } |
6868 | 6824 |
6869 // If the block has outgoing phi moves perform them. Use temporary list | 6825 // If the block has outgoing phi moves perform them. Use temporary list |
6870 // of values to ensure that cyclic moves are performed correctly. | 6826 // of values to ensure that cyclic moves are performed correctly. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6923 } | 6879 } |
6924 } | 6880 } |
6925 return true; | 6881 return true; |
6926 } | 6882 } |
6927 | 6883 |
6928 void MarkLoopInvariantLoads() { | 6884 void MarkLoopInvariantLoads() { |
6929 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = | 6885 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = |
6930 graph_->loop_headers(); | 6886 graph_->loop_headers(); |
6931 | 6887 |
6932 ZoneGrowableArray<BitVector*>* invariant_loads = | 6888 ZoneGrowableArray<BitVector*>* invariant_loads = |
6933 new(isolate()) ZoneGrowableArray<BitVector*>(loop_headers.length()); | 6889 new(I) ZoneGrowableArray<BitVector*>(loop_headers.length()); |
6934 | 6890 |
6935 for (intptr_t i = 0; i < loop_headers.length(); i++) { | 6891 for (intptr_t i = 0; i < loop_headers.length(); i++) { |
6936 BlockEntryInstr* header = loop_headers[i]; | 6892 BlockEntryInstr* header = loop_headers[i]; |
6937 BlockEntryInstr* pre_header = FindPreHeader(header); | 6893 BlockEntryInstr* pre_header = FindPreHeader(header); |
6938 if (pre_header == NULL) { | 6894 if (pre_header == NULL) { |
6939 invariant_loads->Add(NULL); | 6895 invariant_loads->Add(NULL); |
6940 continue; | 6896 continue; |
6941 } | 6897 } |
6942 | 6898 |
6943 BitVector* loop_gen = | 6899 BitVector* loop_gen = new(I) BitVector(aliased_set_->max_place_id()); |
6944 new(isolate()) BitVector(aliased_set_->max_place_id()); | |
6945 for (BitVector::Iterator loop_it(header->loop_info()); | 6900 for (BitVector::Iterator loop_it(header->loop_info()); |
6946 !loop_it.Done(); | 6901 !loop_it.Done(); |
6947 loop_it.Advance()) { | 6902 loop_it.Advance()) { |
6948 const intptr_t preorder_number = loop_it.Current(); | 6903 const intptr_t preorder_number = loop_it.Current(); |
6949 loop_gen->AddAll(gen_[preorder_number]); | 6904 loop_gen->AddAll(gen_[preorder_number]); |
6950 } | 6905 } |
6951 | 6906 |
6952 for (BitVector::Iterator loop_it(header->loop_info()); | 6907 for (BitVector::Iterator loop_it(header->loop_info()); |
6953 !loop_it.Done(); | 6908 !loop_it.Done(); |
6954 loop_it.Advance()) { | 6909 loop_it.Advance()) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6990 incoming = kDifferentValuesMarker; | 6945 incoming = kDifferentValuesMarker; |
6991 } | 6946 } |
6992 } | 6947 } |
6993 | 6948 |
6994 if (incoming != kDifferentValuesMarker) { | 6949 if (incoming != kDifferentValuesMarker) { |
6995 ASSERT(incoming != NULL); | 6950 ASSERT(incoming != NULL); |
6996 return incoming; | 6951 return incoming; |
6997 } | 6952 } |
6998 | 6953 |
6999 // Incoming values are different. Phi is required to merge. | 6954 // Incoming values are different. Phi is required to merge. |
7000 PhiInstr* phi = new(isolate()) PhiInstr( | 6955 PhiInstr* phi = new(I) PhiInstr( |
7001 block->AsJoinEntry(), block->PredecessorCount()); | 6956 block->AsJoinEntry(), block->PredecessorCount()); |
7002 phi->set_place_id(place_id); | 6957 phi->set_place_id(place_id); |
7003 FillPhiInputs(phi); | 6958 FillPhiInputs(phi); |
7004 return phi; | 6959 return phi; |
7005 } | 6960 } |
7006 | 6961 |
7007 void FillPhiInputs(PhiInstr* phi) { | 6962 void FillPhiInputs(PhiInstr* phi) { |
7008 BlockEntryInstr* block = phi->GetBlock(); | 6963 BlockEntryInstr* block = phi->GetBlock(); |
7009 const intptr_t place_id = phi->place_id(); | 6964 const intptr_t place_id = phi->place_id(); |
7010 | 6965 |
7011 for (intptr_t i = 0; i < block->PredecessorCount(); i++) { | 6966 for (intptr_t i = 0; i < block->PredecessorCount(); i++) { |
7012 BlockEntryInstr* pred = block->PredecessorAt(i); | 6967 BlockEntryInstr* pred = block->PredecessorAt(i); |
7013 ZoneGrowableArray<Definition*>* pred_out_values = | 6968 ZoneGrowableArray<Definition*>* pred_out_values = |
7014 out_values_[pred->preorder_number()]; | 6969 out_values_[pred->preorder_number()]; |
7015 ASSERT((*pred_out_values)[place_id] != NULL); | 6970 ASSERT((*pred_out_values)[place_id] != NULL); |
7016 | 6971 |
7017 // Sets of outgoing values are not linked into use lists so | 6972 // Sets of outgoing values are not linked into use lists so |
7018 // they might contain values that were replaced and removed | 6973 // they might contain values that were replaced and removed |
7019 // from the graph by this iteration. | 6974 // from the graph by this iteration. |
7020 // To prevent using them we additionally mark definitions themselves | 6975 // To prevent using them we additionally mark definitions themselves |
7021 // as replaced and store a pointer to the replacement. | 6976 // as replaced and store a pointer to the replacement. |
7022 Definition* replacement = (*pred_out_values)[place_id]->Replacement(); | 6977 Definition* replacement = (*pred_out_values)[place_id]->Replacement(); |
7023 Value* input = new(isolate()) Value(replacement); | 6978 Value* input = new(I) Value(replacement); |
7024 phi->SetInputAt(i, input); | 6979 phi->SetInputAt(i, input); |
7025 replacement->AddInputUse(input); | 6980 replacement->AddInputUse(input); |
7026 } | 6981 } |
7027 | 6982 |
7028 phi->set_ssa_temp_index(graph_->alloc_ssa_temp_index()); | 6983 phi->set_ssa_temp_index(graph_->alloc_ssa_temp_index()); |
7029 phis_.Add(phi); // Postpone phi insertion until after load forwarding. | 6984 phis_.Add(phi); // Postpone phi insertion until after load forwarding. |
7030 | 6985 |
7031 if (FLAG_trace_load_optimization) { | 6986 if (FLAG_trace_load_optimization) { |
7032 OS::Print("created pending phi %s for %s at B%" Pd "\n", | 6987 OS::Print("created pending phi %s for %s at B%" Pd "\n", |
7033 phi->ToCString(), | 6988 phi->ToCString(), |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7086 // Eliminate it as redundant if this is the case. | 7041 // Eliminate it as redundant if this is the case. |
7087 // When analyzing phi operands assumes that only generated during | 7042 // When analyzing phi operands assumes that only generated during |
7088 // this load phase can be redundant. They can be distinguished because | 7043 // this load phase can be redundant. They can be distinguished because |
7089 // they are not marked alive. | 7044 // they are not marked alive. |
7090 // TODO(vegorov): move this into a separate phase over all phis. | 7045 // TODO(vegorov): move this into a separate phase over all phis. |
7091 bool EliminateRedundantPhi(PhiInstr* phi) { | 7046 bool EliminateRedundantPhi(PhiInstr* phi) { |
7092 Definition* value = NULL; // Possible value of this phi. | 7047 Definition* value = NULL; // Possible value of this phi. |
7093 | 7048 |
7094 worklist_.Clear(); | 7049 worklist_.Clear(); |
7095 if (in_worklist_ == NULL) { | 7050 if (in_worklist_ == NULL) { |
7096 in_worklist_ = new(isolate()) BitVector(graph_->current_ssa_temp_index()); | 7051 in_worklist_ = new(I) BitVector(graph_->current_ssa_temp_index()); |
7097 } else { | 7052 } else { |
7098 in_worklist_->Clear(); | 7053 in_worklist_->Clear(); |
7099 } | 7054 } |
7100 | 7055 |
7101 worklist_.Add(phi); | 7056 worklist_.Add(phi); |
7102 in_worklist_->Add(phi->ssa_temp_index()); | 7057 in_worklist_->Add(phi->ssa_temp_index()); |
7103 | 7058 |
7104 for (intptr_t i = 0; i < worklist_.length(); i++) { | 7059 for (intptr_t i = 0; i < worklist_.length(); i++) { |
7105 PhiInstr* phi = worklist_[i]; | 7060 PhiInstr* phi = worklist_[i]; |
7106 | 7061 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7159 } | 7114 } |
7160 | 7115 |
7161 // Replace the given phi with another if they are equal. | 7116 // Replace the given phi with another if they are equal. |
7162 // Returns true if succeeds. | 7117 // Returns true if succeeds. |
7163 bool ReplacePhiWith(PhiInstr* phi, PhiInstr* replacement) { | 7118 bool ReplacePhiWith(PhiInstr* phi, PhiInstr* replacement) { |
7164 ASSERT(phi->InputCount() == replacement->InputCount()); | 7119 ASSERT(phi->InputCount() == replacement->InputCount()); |
7165 ASSERT(phi->block() == replacement->block()); | 7120 ASSERT(phi->block() == replacement->block()); |
7166 | 7121 |
7167 worklist_.Clear(); | 7122 worklist_.Clear(); |
7168 if (in_worklist_ == NULL) { | 7123 if (in_worklist_ == NULL) { |
7169 in_worklist_ = new(isolate()) BitVector(graph_->current_ssa_temp_index()); | 7124 in_worklist_ = new(I) BitVector(graph_->current_ssa_temp_index()); |
7170 } else { | 7125 } else { |
7171 in_worklist_->Clear(); | 7126 in_worklist_->Clear(); |
7172 } | 7127 } |
7173 | 7128 |
7174 // During the comparison worklist contains pairs of phis to be compared. | 7129 // During the comparison worklist contains pairs of phis to be compared. |
7175 AddPhiPairToWorklist(phi, replacement); | 7130 AddPhiPairToWorklist(phi, replacement); |
7176 | 7131 |
7177 // Process the worklist. It might grow during each comparison step. | 7132 // Process the worklist. It might grow during each comparison step. |
7178 for (intptr_t i = 0; i < worklist_.length(); i += 2) { | 7133 for (intptr_t i = 0; i < worklist_.length(); i += 2) { |
7179 PhiInstr* a = worklist_[i]; | 7134 PhiInstr* a = worklist_[i]; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7244 for (intptr_t i = 0; i < phis_.length(); i++) { | 7199 for (intptr_t i = 0; i < phis_.length(); i++) { |
7245 PhiInstr* phi = phis_[i]; | 7200 PhiInstr* phi = phis_[i]; |
7246 if ((phi != NULL) && (!phi->HasUses() || !EmitPhi(phi))) { | 7201 if ((phi != NULL) && (!phi->HasUses() || !EmitPhi(phi))) { |
7247 phi->UnuseAllInputs(); | 7202 phi->UnuseAllInputs(); |
7248 } | 7203 } |
7249 } | 7204 } |
7250 } | 7205 } |
7251 | 7206 |
7252 ZoneGrowableArray<Definition*>* CreateBlockOutValues() { | 7207 ZoneGrowableArray<Definition*>* CreateBlockOutValues() { |
7253 ZoneGrowableArray<Definition*>* out = | 7208 ZoneGrowableArray<Definition*>* out = |
7254 new(isolate()) ZoneGrowableArray<Definition*>( | 7209 new(I) ZoneGrowableArray<Definition*>(aliased_set_->max_place_id()); |
7255 aliased_set_->max_place_id()); | |
7256 for (intptr_t i = 0; i < aliased_set_->max_place_id(); i++) { | 7210 for (intptr_t i = 0; i < aliased_set_->max_place_id(); i++) { |
7257 out->Add(NULL); | 7211 out->Add(NULL); |
7258 } | 7212 } |
7259 return out; | 7213 return out; |
7260 } | 7214 } |
7261 | 7215 |
7262 FlowGraph* graph_; | 7216 FlowGraph* graph_; |
7263 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map_; | 7217 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map_; |
7264 | 7218 |
7265 // Mapping between field offsets in words and expression ids of loads from | 7219 // Mapping between field offsets in words and expression ids of loads from |
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7902 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) { } | 7856 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) { } |
7903 | 7857 |
7904 | 7858 |
7905 // -------------------------------------------------------------------------- | 7859 // -------------------------------------------------------------------------- |
7906 // Analysis of definitions. Compute the constant value. If it has changed | 7860 // Analysis of definitions. Compute the constant value. If it has changed |
7907 // and the definition has input uses, add the definition to the definition | 7861 // and the definition has input uses, add the definition to the definition |
7908 // worklist so that the used can be processed. | 7862 // worklist so that the used can be processed. |
7909 void ConstantPropagator::VisitPhi(PhiInstr* instr) { | 7863 void ConstantPropagator::VisitPhi(PhiInstr* instr) { |
7910 // Compute the join over all the reachable predecessor values. | 7864 // Compute the join over all the reachable predecessor values. |
7911 JoinEntryInstr* block = instr->block(); | 7865 JoinEntryInstr* block = instr->block(); |
7912 Object& value = Object::ZoneHandle(isolate(), Unknown()); | 7866 Object& value = Object::ZoneHandle(I, Unknown()); |
7913 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { | 7867 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { |
7914 if (reachable_->Contains( | 7868 if (reachable_->Contains( |
7915 block->PredecessorAt(pred_idx)->preorder_number())) { | 7869 block->PredecessorAt(pred_idx)->preorder_number())) { |
7916 Join(&value, | 7870 Join(&value, |
7917 instr->InputAt(pred_idx)->definition()->constant_value()); | 7871 instr->InputAt(pred_idx)->definition()->constant_value()); |
7918 } | 7872 } |
7919 } | 7873 } |
7920 SetValue(instr, value); | 7874 SetValue(instr, value); |
7921 } | 7875 } |
7922 | 7876 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8019 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { | 7973 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { |
8020 instr->comparison()->Accept(this); | 7974 instr->comparison()->Accept(this); |
8021 const Object& value = instr->comparison()->constant_value(); | 7975 const Object& value = instr->comparison()->constant_value(); |
8022 if (IsNonConstant(value)) { | 7976 if (IsNonConstant(value)) { |
8023 SetValue(instr, non_constant_); | 7977 SetValue(instr, non_constant_); |
8024 } else if (IsConstant(value)) { | 7978 } else if (IsConstant(value)) { |
8025 ASSERT(!value.IsNull()); | 7979 ASSERT(!value.IsNull()); |
8026 ASSERT(value.IsBool()); | 7980 ASSERT(value.IsBool()); |
8027 bool result = Bool::Cast(value).value(); | 7981 bool result = Bool::Cast(value).value(); |
8028 SetValue(instr, | 7982 SetValue(instr, |
8029 Smi::Handle(isolate(), Smi::New( | 7983 Smi::Handle(I, Smi::New( |
8030 result ? instr->if_true() : instr->if_false()))); | 7984 result ? instr->if_true() : instr->if_false()))); |
8031 } | 7985 } |
8032 } | 7986 } |
8033 | 7987 |
8034 | 7988 |
8035 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { | 7989 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { |
8036 const Object& left = instr->left()->definition()->constant_value(); | 7990 const Object& left = instr->left()->definition()->constant_value(); |
8037 const Object& right = instr->right()->definition()->constant_value(); | 7991 const Object& right = instr->right()->definition()->constant_value(); |
8038 | 7992 |
8039 if (instr->left()->definition() == instr->right()->definition()) { | 7993 if (instr->left()->definition() == instr->right()->definition()) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8095 | 8049 |
8096 void ConstantPropagator::VisitTestSmi(TestSmiInstr* instr) { | 8050 void ConstantPropagator::VisitTestSmi(TestSmiInstr* instr) { |
8097 const Object& left = instr->left()->definition()->constant_value(); | 8051 const Object& left = instr->left()->definition()->constant_value(); |
8098 const Object& right = instr->right()->definition()->constant_value(); | 8052 const Object& right = instr->right()->definition()->constant_value(); |
8099 if (IsNonConstant(left) || IsNonConstant(right)) { | 8053 if (IsNonConstant(left) || IsNonConstant(right)) { |
8100 SetValue(instr, non_constant_); | 8054 SetValue(instr, non_constant_); |
8101 } else if (IsConstant(left) && IsConstant(right)) { | 8055 } else if (IsConstant(left) && IsConstant(right)) { |
8102 if (left.IsInteger() && right.IsInteger()) { | 8056 if (left.IsInteger() && right.IsInteger()) { |
8103 const bool result = CompareIntegers( | 8057 const bool result = CompareIntegers( |
8104 instr->kind(), | 8058 instr->kind(), |
8105 Integer::Handle(isolate(), | 8059 Integer::Handle(I, Integer::Cast(left).BitOp(Token::kBIT_AND, |
8106 Integer::Cast(left).BitOp(Token::kBIT_AND, | 8060 Integer::Cast(right))), |
8107 Integer::Cast(right))), | 8061 Smi::Handle(I, Smi::New(0))); |
8108 Smi::Handle(isolate(), Smi::New(0))); | |
8109 SetValue(instr, result ? Bool::True() : Bool::False()); | 8062 SetValue(instr, result ? Bool::True() : Bool::False()); |
8110 } else { | 8063 } else { |
8111 SetValue(instr, non_constant_); | 8064 SetValue(instr, non_constant_); |
8112 } | 8065 } |
8113 } | 8066 } |
8114 } | 8067 } |
8115 | 8068 |
8116 | 8069 |
8117 void ConstantPropagator::VisitTestCids(TestCidsInstr* instr) { | 8070 void ConstantPropagator::VisitTestCids(TestCidsInstr* instr) { |
8118 SetValue(instr, non_constant_); | 8071 SetValue(instr, non_constant_); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8182 void ConstantPropagator::VisitStringFromCharCode( | 8135 void ConstantPropagator::VisitStringFromCharCode( |
8183 StringFromCharCodeInstr* instr) { | 8136 StringFromCharCodeInstr* instr) { |
8184 const Object& o = instr->char_code()->definition()->constant_value(); | 8137 const Object& o = instr->char_code()->definition()->constant_value(); |
8185 if (o.IsNull() || IsNonConstant(o)) { | 8138 if (o.IsNull() || IsNonConstant(o)) { |
8186 SetValue(instr, non_constant_); | 8139 SetValue(instr, non_constant_); |
8187 } else if (IsConstant(o)) { | 8140 } else if (IsConstant(o)) { |
8188 const intptr_t ch_code = Smi::Cast(o).Value(); | 8141 const intptr_t ch_code = Smi::Cast(o).Value(); |
8189 ASSERT(ch_code >= 0); | 8142 ASSERT(ch_code >= 0); |
8190 if (ch_code < Symbols::kMaxOneCharCodeSymbol) { | 8143 if (ch_code < Symbols::kMaxOneCharCodeSymbol) { |
8191 RawString** table = Symbols::PredefinedAddress(); | 8144 RawString** table = Symbols::PredefinedAddress(); |
8192 SetValue(instr, String::ZoneHandle(isolate(), table[ch_code])); | 8145 SetValue(instr, String::ZoneHandle(I, table[ch_code])); |
8193 } else { | 8146 } else { |
8194 SetValue(instr, non_constant_); | 8147 SetValue(instr, non_constant_); |
8195 } | 8148 } |
8196 } | 8149 } |
8197 } | 8150 } |
8198 | 8151 |
8199 | 8152 |
8200 void ConstantPropagator::VisitStringToCharCode(StringToCharCodeInstr* instr) { | 8153 void ConstantPropagator::VisitStringToCharCode(StringToCharCodeInstr* instr) { |
8201 const Object& o = instr->str()->definition()->constant_value(); | 8154 const Object& o = instr->str()->definition()->constant_value(); |
8202 if (o.IsNull() || IsNonConstant(o)) { | 8155 if (o.IsNull() || IsNonConstant(o)) { |
8203 SetValue(instr, non_constant_); | 8156 SetValue(instr, non_constant_); |
8204 } else if (IsConstant(o)) { | 8157 } else if (IsConstant(o)) { |
8205 const String& str = String::Cast(o); | 8158 const String& str = String::Cast(o); |
8206 const intptr_t result = (str.Length() == 1) ? str.CharAt(0) : -1; | 8159 const intptr_t result = (str.Length() == 1) ? str.CharAt(0) : -1; |
8207 SetValue(instr, Smi::ZoneHandle(isolate(), Smi::New(result))); | 8160 SetValue(instr, Smi::ZoneHandle(I, Smi::New(result))); |
8208 } | 8161 } |
8209 } | 8162 } |
8210 | 8163 |
8211 | 8164 |
8212 | 8165 |
8213 | 8166 |
8214 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) { | 8167 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) { |
8215 SetValue(instr, non_constant_); | 8168 SetValue(instr, non_constant_); |
8216 return; | 8169 return; |
8217 } | 8170 } |
8218 | 8171 |
8219 | 8172 |
8220 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { | 8173 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { |
8221 const Object& array_obj = instr->array()->definition()->constant_value(); | 8174 const Object& array_obj = instr->array()->definition()->constant_value(); |
8222 const Object& index_obj = instr->index()->definition()->constant_value(); | 8175 const Object& index_obj = instr->index()->definition()->constant_value(); |
8223 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) { | 8176 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) { |
8224 SetValue(instr, non_constant_); | 8177 SetValue(instr, non_constant_); |
8225 } else if (IsConstant(array_obj) && IsConstant(index_obj)) { | 8178 } else if (IsConstant(array_obj) && IsConstant(index_obj)) { |
8226 // Need index to be Smi and array to be either String or an immutable array. | 8179 // Need index to be Smi and array to be either String or an immutable array. |
8227 if (!index_obj.IsSmi()) { | 8180 if (!index_obj.IsSmi()) { |
8228 // Should not occur. | 8181 // Should not occur. |
8229 SetValue(instr, non_constant_); | 8182 SetValue(instr, non_constant_); |
8230 return; | 8183 return; |
8231 } | 8184 } |
8232 const intptr_t index = Smi::Cast(index_obj).Value(); | 8185 const intptr_t index = Smi::Cast(index_obj).Value(); |
8233 if (index >= 0) { | 8186 if (index >= 0) { |
8234 if (array_obj.IsString()) { | 8187 if (array_obj.IsString()) { |
8235 const String& str = String::Cast(array_obj); | 8188 const String& str = String::Cast(array_obj); |
8236 if (str.Length() > index) { | 8189 if (str.Length() > index) { |
8237 SetValue(instr, Smi::Handle(isolate(), Smi::New(str.CharAt(index)))); | 8190 SetValue(instr, Smi::Handle(I, Smi::New(str.CharAt(index)))); |
8238 return; | 8191 return; |
8239 } | 8192 } |
8240 } else if (array_obj.IsArray()) { | 8193 } else if (array_obj.IsArray()) { |
8241 const Array& a = Array::Cast(array_obj); | 8194 const Array& a = Array::Cast(array_obj); |
8242 if ((a.Length() > index) && a.IsImmutable()) { | 8195 if ((a.Length() > index) && a.IsImmutable()) { |
8243 Instance& result = Instance::Handle(isolate(), Instance::null()); | 8196 Instance& result = Instance::Handle(I); |
8244 result ^= a.At(index); | 8197 result ^= a.At(index); |
8245 SetValue(instr, result); | 8198 SetValue(instr, result); |
8246 return; | 8199 return; |
8247 } | 8200 } |
8248 } | 8201 } |
8249 } | 8202 } |
8250 SetValue(instr, non_constant_); | 8203 SetValue(instr, non_constant_); |
8251 } | 8204 } |
8252 } | 8205 } |
8253 | 8206 |
8254 | 8207 |
8255 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { | 8208 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { |
8256 SetValue(instr, instr->value()->definition()->constant_value()); | 8209 SetValue(instr, instr->value()->definition()->constant_value()); |
8257 } | 8210 } |
8258 | 8211 |
8259 | 8212 |
8260 void ConstantPropagator::VisitStoreInstanceField( | 8213 void ConstantPropagator::VisitStoreInstanceField( |
8261 StoreInstanceFieldInstr* instr) { | 8214 StoreInstanceFieldInstr* instr) { |
8262 SetValue(instr, instr->value()->definition()->constant_value()); | 8215 SetValue(instr, instr->value()->definition()->constant_value()); |
8263 } | 8216 } |
8264 | 8217 |
8265 | 8218 |
8266 void ConstantPropagator::VisitLoadStaticField(LoadStaticFieldInstr* instr) { | 8219 void ConstantPropagator::VisitLoadStaticField(LoadStaticFieldInstr* instr) { |
8267 const Field& field = instr->StaticField(); | 8220 const Field& field = instr->StaticField(); |
8268 ASSERT(field.is_static()); | 8221 ASSERT(field.is_static()); |
8269 if (field.is_final()) { | 8222 if (field.is_final()) { |
8270 Instance& obj = Instance::Handle(isolate(), field.value()); | 8223 Instance& obj = Instance::Handle(I, field.value()); |
8271 ASSERT(obj.raw() != Object::sentinel().raw()); | 8224 ASSERT(obj.raw() != Object::sentinel().raw()); |
8272 ASSERT(obj.raw() != Object::transition_sentinel().raw()); | 8225 ASSERT(obj.raw() != Object::transition_sentinel().raw()); |
8273 if (obj.IsSmi() || obj.IsOld()) { | 8226 if (obj.IsSmi() || obj.IsOld()) { |
8274 SetValue(instr, obj); | 8227 SetValue(instr, obj); |
8275 return; | 8228 return; |
8276 } | 8229 } |
8277 } | 8230 } |
8278 SetValue(instr, non_constant_); | 8231 SetValue(instr, non_constant_); |
8279 } | 8232 } |
8280 | 8233 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8335 | 8288 |
8336 | 8289 |
8337 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) { | 8290 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) { |
8338 SetValue(instr, non_constant_); | 8291 SetValue(instr, non_constant_); |
8339 } | 8292 } |
8340 | 8293 |
8341 | 8294 |
8342 void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) { | 8295 void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) { |
8343 intptr_t cid = instr->object()->Type()->ToCid(); | 8296 intptr_t cid = instr->object()->Type()->ToCid(); |
8344 if (cid != kDynamicCid) { | 8297 if (cid != kDynamicCid) { |
8345 SetValue(instr, Smi::ZoneHandle(isolate(), Smi::New(cid))); | 8298 SetValue(instr, Smi::ZoneHandle(I, Smi::New(cid))); |
8346 return; | 8299 return; |
8347 } | 8300 } |
8348 const Object& object = instr->object()->definition()->constant_value(); | 8301 const Object& object = instr->object()->definition()->constant_value(); |
8349 if (IsConstant(object)) { | 8302 if (IsConstant(object)) { |
8350 SetValue(instr, Smi::ZoneHandle(isolate(), Smi::New(object.GetClassId()))); | 8303 SetValue(instr, Smi::ZoneHandle(I, Smi::New(object.GetClassId()))); |
8351 return; | 8304 return; |
8352 } | 8305 } |
8353 SetValue(instr, non_constant_); | 8306 SetValue(instr, non_constant_); |
8354 } | 8307 } |
8355 | 8308 |
8356 | 8309 |
8357 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { | 8310 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { |
8358 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && | 8311 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && |
8359 (instr->instance()->definition()->IsCreateArray())) { | 8312 (instr->instance()->definition()->IsCreateArray())) { |
8360 Value* num_elements = | 8313 Value* num_elements = |
8361 instr->instance()->definition()->AsCreateArray()->num_elements(); | 8314 instr->instance()->definition()->AsCreateArray()->num_elements(); |
8362 if (num_elements->BindsToConstant() && | 8315 if (num_elements->BindsToConstant() && |
8363 num_elements->BoundConstant().IsSmi()) { | 8316 num_elements->BoundConstant().IsSmi()) { |
8364 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); | 8317 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); |
8365 const Object& result = Smi::ZoneHandle(isolate(), Smi::New(length)); | 8318 const Object& result = Smi::ZoneHandle(I, Smi::New(length)); |
8366 SetValue(instr, result); | 8319 SetValue(instr, result); |
8367 return; | 8320 return; |
8368 } | 8321 } |
8369 } | 8322 } |
8370 | 8323 |
8371 if (instr->IsImmutableLengthLoad()) { | 8324 if (instr->IsImmutableLengthLoad()) { |
8372 ConstantInstr* constant = instr->instance()->definition()->AsConstant(); | 8325 ConstantInstr* constant = instr->instance()->definition()->AsConstant(); |
8373 if (constant != NULL) { | 8326 if (constant != NULL) { |
8374 if (constant->value().IsString()) { | 8327 if (constant->value().IsString()) { |
8375 SetValue(instr, Smi::ZoneHandle(isolate(), | 8328 SetValue(instr, Smi::ZoneHandle(I, |
8376 Smi::New(String::Cast(constant->value()).Length()))); | 8329 Smi::New(String::Cast(constant->value()).Length()))); |
8377 return; | 8330 return; |
8378 } | 8331 } |
8379 if (constant->value().IsArray()) { | 8332 if (constant->value().IsArray()) { |
8380 SetValue(instr, Smi::ZoneHandle(isolate(), | 8333 SetValue(instr, Smi::ZoneHandle(I, |
8381 Smi::New(Array::Cast(constant->value()).Length()))); | 8334 Smi::New(Array::Cast(constant->value()).Length()))); |
8382 return; | 8335 return; |
8383 } | 8336 } |
8384 } | 8337 } |
8385 } | 8338 } |
8386 SetValue(instr, non_constant_); | 8339 SetValue(instr, non_constant_); |
8387 } | 8340 } |
8388 | 8341 |
8389 | 8342 |
8390 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) { | 8343 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) { |
8391 const Object& object = | 8344 const Object& object = |
8392 instr->instantiator()->definition()->constant_value(); | 8345 instr->instantiator()->definition()->constant_value(); |
8393 if (IsNonConstant(object)) { | 8346 if (IsNonConstant(object)) { |
8394 SetValue(instr, non_constant_); | 8347 SetValue(instr, non_constant_); |
8395 return; | 8348 return; |
8396 } | 8349 } |
8397 if (IsConstant(object)) { | 8350 if (IsConstant(object)) { |
8398 if (instr->type().IsTypeParameter()) { | 8351 if (instr->type().IsTypeParameter()) { |
8399 if (object.IsNull()) { | 8352 if (object.IsNull()) { |
8400 SetValue(instr, Type::ZoneHandle(isolate(), Type::DynamicType())); | 8353 SetValue(instr, Type::ZoneHandle(I, Type::DynamicType())); |
8401 return; | 8354 return; |
8402 } | 8355 } |
8403 // We could try to instantiate the type parameter and return it if no | 8356 // We could try to instantiate the type parameter and return it if no |
8404 // malformed error is reported. | 8357 // malformed error is reported. |
8405 } | 8358 } |
8406 SetValue(instr, non_constant_); | 8359 SetValue(instr, non_constant_); |
8407 } | 8360 } |
8408 } | 8361 } |
8409 | 8362 |
8410 | 8363 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8462 case Token::kMOD: | 8415 case Token::kMOD: |
8463 // Check right value for zero. | 8416 // Check right value for zero. |
8464 if (right_int.AsInt64Value() == 0) { | 8417 if (right_int.AsInt64Value() == 0) { |
8465 SetValue(instr, non_constant_); | 8418 SetValue(instr, non_constant_); |
8466 break; | 8419 break; |
8467 } | 8420 } |
8468 // Fall through. | 8421 // Fall through. |
8469 case Token::kADD: | 8422 case Token::kADD: |
8470 case Token::kSUB: | 8423 case Token::kSUB: |
8471 case Token::kMUL: { | 8424 case Token::kMUL: { |
8472 Instance& result = Integer::ZoneHandle(isolate(), | 8425 Instance& result = Integer::ZoneHandle(I, |
8473 left_int.ArithmeticOp(op_kind, right_int)); | 8426 left_int.ArithmeticOp(op_kind, right_int)); |
8474 result = result.CheckAndCanonicalize(NULL); | 8427 result = result.CheckAndCanonicalize(NULL); |
8475 ASSERT(!result.IsNull()); | 8428 ASSERT(!result.IsNull()); |
8476 SetValue(instr, result); | 8429 SetValue(instr, result); |
8477 break; | 8430 break; |
8478 } | 8431 } |
8479 case Token::kSHL: | 8432 case Token::kSHL: |
8480 case Token::kSHR: | 8433 case Token::kSHR: |
8481 if (left.IsSmi() && right.IsSmi()) { | 8434 if (left.IsSmi() && right.IsSmi()) { |
8482 Instance& result = Integer::ZoneHandle(isolate(), | 8435 Instance& result = Integer::ZoneHandle(I, |
8483 Smi::Cast(left_int).ShiftOp(op_kind, Smi::Cast(right_int))); | 8436 Smi::Cast(left_int).ShiftOp(op_kind, Smi::Cast(right_int))); |
8484 result = result.CheckAndCanonicalize(NULL); | 8437 result = result.CheckAndCanonicalize(NULL); |
8485 ASSERT(!result.IsNull()); | 8438 ASSERT(!result.IsNull()); |
8486 SetValue(instr, result); | 8439 SetValue(instr, result); |
8487 } else { | 8440 } else { |
8488 SetValue(instr, non_constant_); | 8441 SetValue(instr, non_constant_); |
8489 } | 8442 } |
8490 break; | 8443 break; |
8491 case Token::kBIT_AND: | 8444 case Token::kBIT_AND: |
8492 case Token::kBIT_OR: | 8445 case Token::kBIT_OR: |
8493 case Token::kBIT_XOR: { | 8446 case Token::kBIT_XOR: { |
8494 Instance& result = Integer::ZoneHandle(isolate(), | 8447 Instance& result = Integer::ZoneHandle(I, |
8495 left_int.BitOp(op_kind, right_int)); | 8448 left_int.BitOp(op_kind, right_int)); |
8496 result = result.CheckAndCanonicalize(NULL); | 8449 result = result.CheckAndCanonicalize(NULL); |
8497 ASSERT(!result.IsNull()); | 8450 ASSERT(!result.IsNull()); |
8498 SetValue(instr, result); | 8451 SetValue(instr, result); |
8499 break; | 8452 break; |
8500 } | 8453 } |
8501 case Token::kDIV: | 8454 case Token::kDIV: |
8502 SetValue(instr, non_constant_); | 8455 SetValue(instr, non_constant_); |
8503 break; | 8456 break; |
8504 default: | 8457 default: |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8563 } else if (IsConstant(value)) { | 8516 } else if (IsConstant(value)) { |
8564 // TODO(kmillikin): Handle unary operations. | 8517 // TODO(kmillikin): Handle unary operations. |
8565 SetValue(instr, non_constant_); | 8518 SetValue(instr, non_constant_); |
8566 } | 8519 } |
8567 } | 8520 } |
8568 | 8521 |
8569 | 8522 |
8570 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { | 8523 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { |
8571 const Object& value = instr->value()->definition()->constant_value(); | 8524 const Object& value = instr->value()->definition()->constant_value(); |
8572 if (IsConstant(value) && value.IsInteger()) { | 8525 if (IsConstant(value) && value.IsInteger()) { |
8573 SetValue(instr, Double::Handle(isolate(), | 8526 SetValue(instr, Double::Handle(I, |
8574 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); | 8527 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); |
8575 } else if (IsNonConstant(value)) { | 8528 } else if (IsNonConstant(value)) { |
8576 SetValue(instr, non_constant_); | 8529 SetValue(instr, non_constant_); |
8577 } | 8530 } |
8578 } | 8531 } |
8579 | 8532 |
8580 | 8533 |
8581 void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) { | 8534 void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) { |
8582 // TODO(kmillikin): Handle conversion. | 8535 // TODO(kmillikin): Handle conversion. |
8583 SetValue(instr, non_constant_); | 8536 SetValue(instr, non_constant_); |
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9026 current = current->next()->AsGoto()->successor(); | 8979 current = current->next()->AsGoto()->successor(); |
9027 } | 8980 } |
9028 return current; | 8981 return current; |
9029 } | 8982 } |
9030 | 8983 |
9031 | 8984 |
9032 void ConstantPropagator::EliminateRedundantBranches() { | 8985 void ConstantPropagator::EliminateRedundantBranches() { |
9033 // Canonicalize branches that have no side-effects and where true- and | 8986 // Canonicalize branches that have no side-effects and where true- and |
9034 // false-targets are the same. | 8987 // false-targets are the same. |
9035 bool changed = false; | 8988 bool changed = false; |
9036 BitVector* empty_blocks = | 8989 BitVector* empty_blocks = new(I) BitVector(graph_->preorder().length()); |
9037 new(graph_->isolate()) BitVector(graph_->preorder().length()); | |
9038 for (BlockIterator b = graph_->postorder_iterator(); | 8990 for (BlockIterator b = graph_->postorder_iterator(); |
9039 !b.Done(); | 8991 !b.Done(); |
9040 b.Advance()) { | 8992 b.Advance()) { |
9041 BlockEntryInstr* block = b.Current(); | 8993 BlockEntryInstr* block = b.Current(); |
9042 BranchInstr* branch = block->last_instruction()->AsBranch(); | 8994 BranchInstr* branch = block->last_instruction()->AsBranch(); |
9043 empty_blocks->Clear(); | 8995 empty_blocks->Clear(); |
9044 if ((branch != NULL) && branch->Effects().IsNone()) { | 8996 if ((branch != NULL) && branch->Effects().IsNone()) { |
9045 ASSERT(branch->previous() != NULL); // Not already eliminated. | 8997 ASSERT(branch->previous() != NULL); // Not already eliminated. |
9046 BlockEntryInstr* if_true = | 8998 BlockEntryInstr* if_true = |
9047 FindFirstNonEmptySuccessor(branch->true_successor(), empty_blocks); | 8999 FindFirstNonEmptySuccessor(branch->true_successor(), empty_blocks); |
9048 BlockEntryInstr* if_false = | 9000 BlockEntryInstr* if_false = |
9049 FindFirstNonEmptySuccessor(branch->false_successor(), empty_blocks); | 9001 FindFirstNonEmptySuccessor(branch->false_successor(), empty_blocks); |
9050 if (if_true == if_false) { | 9002 if (if_true == if_false) { |
9051 // Replace the branch with a jump to the common successor. | 9003 // Replace the branch with a jump to the common successor. |
9052 // Drop the comparison, which does not have side effects | 9004 // Drop the comparison, which does not have side effects |
9053 JoinEntryInstr* join = if_true->AsJoinEntry(); | 9005 JoinEntryInstr* join = if_true->AsJoinEntry(); |
9054 if (join->phis() == NULL) { | 9006 if (join->phis() == NULL) { |
9055 GotoInstr* jump = | 9007 GotoInstr* jump = new(I) GotoInstr(if_true->AsJoinEntry()); |
9056 new(graph_->isolate()) GotoInstr(if_true->AsJoinEntry()); | 9008 jump->InheritDeoptTarget(I, branch); |
9057 jump->InheritDeoptTarget(isolate(), branch); | |
9058 | 9009 |
9059 Instruction* previous = branch->previous(); | 9010 Instruction* previous = branch->previous(); |
9060 branch->set_previous(NULL); | 9011 branch->set_previous(NULL); |
9061 previous->LinkTo(jump); | 9012 previous->LinkTo(jump); |
9062 | 9013 |
9063 // Remove uses from branch and all the empty blocks that | 9014 // Remove uses from branch and all the empty blocks that |
9064 // are now unreachable. | 9015 // are now unreachable. |
9065 branch->UnuseAllInputs(); | 9016 branch->UnuseAllInputs(); |
9066 for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) { | 9017 for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) { |
9067 BlockEntryInstr* empty_block = graph_->preorder()[it.Current()]; | 9018 BlockEntryInstr* empty_block = graph_->preorder()[it.Current()]; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9192 if (branch != NULL) { | 9143 if (branch != NULL) { |
9193 TargetEntryInstr* if_true = branch->true_successor(); | 9144 TargetEntryInstr* if_true = branch->true_successor(); |
9194 TargetEntryInstr* if_false = branch->false_successor(); | 9145 TargetEntryInstr* if_false = branch->false_successor(); |
9195 JoinEntryInstr* join = NULL; | 9146 JoinEntryInstr* join = NULL; |
9196 Instruction* next = NULL; | 9147 Instruction* next = NULL; |
9197 | 9148 |
9198 if (!reachable_->Contains(if_true->preorder_number())) { | 9149 if (!reachable_->Contains(if_true->preorder_number())) { |
9199 ASSERT(reachable_->Contains(if_false->preorder_number())); | 9150 ASSERT(reachable_->Contains(if_false->preorder_number())); |
9200 ASSERT(if_false->parallel_move() == NULL); | 9151 ASSERT(if_false->parallel_move() == NULL); |
9201 ASSERT(if_false->loop_info() == NULL); | 9152 ASSERT(if_false->loop_info() == NULL); |
9202 join = new(isolate()) JoinEntryInstr(if_false->block_id(), | 9153 join = new(I) JoinEntryInstr(if_false->block_id(), |
9203 if_false->try_index()); | 9154 if_false->try_index()); |
9204 join->InheritDeoptTarget(isolate(), if_false); | 9155 join->InheritDeoptTarget(I, if_false); |
9205 if_false->UnuseAllInputs(); | 9156 if_false->UnuseAllInputs(); |
9206 next = if_false->next(); | 9157 next = if_false->next(); |
9207 } else if (!reachable_->Contains(if_false->preorder_number())) { | 9158 } else if (!reachable_->Contains(if_false->preorder_number())) { |
9208 ASSERT(if_true->parallel_move() == NULL); | 9159 ASSERT(if_true->parallel_move() == NULL); |
9209 ASSERT(if_true->loop_info() == NULL); | 9160 ASSERT(if_true->loop_info() == NULL); |
9210 join = new(isolate()) JoinEntryInstr(if_true->block_id(), | 9161 join = new(I) JoinEntryInstr(if_true->block_id(), |
9211 if_true->try_index()); | 9162 if_true->try_index()); |
9212 join->InheritDeoptTarget(isolate(), if_true); | 9163 join->InheritDeoptTarget(I, if_true); |
9213 if_true->UnuseAllInputs(); | 9164 if_true->UnuseAllInputs(); |
9214 next = if_true->next(); | 9165 next = if_true->next(); |
9215 } | 9166 } |
9216 | 9167 |
9217 if (join != NULL) { | 9168 if (join != NULL) { |
9218 // Replace the branch with a jump to the reachable successor. | 9169 // Replace the branch with a jump to the reachable successor. |
9219 // Drop the comparison, which does not have side effects as long | 9170 // Drop the comparison, which does not have side effects as long |
9220 // as it is a strict compare (the only one we can determine is | 9171 // as it is a strict compare (the only one we can determine is |
9221 // constant with the current analysis). | 9172 // constant with the current analysis). |
9222 GotoInstr* jump = new(isolate()) GotoInstr(join); | 9173 GotoInstr* jump = new(I) GotoInstr(join); |
9223 jump->InheritDeoptTarget(isolate(), branch); | 9174 jump->InheritDeoptTarget(I, branch); |
9224 | 9175 |
9225 Instruction* previous = branch->previous(); | 9176 Instruction* previous = branch->previous(); |
9226 branch->set_previous(NULL); | 9177 branch->set_previous(NULL); |
9227 previous->LinkTo(jump); | 9178 previous->LinkTo(jump); |
9228 | 9179 |
9229 // Replace the false target entry with the new join entry. We will | 9180 // Replace the false target entry with the new join entry. We will |
9230 // recompute the dominators after this pass. | 9181 // recompute the dominators after this pass. |
9231 join->LinkTo(next); | 9182 join->LinkTo(next); |
9232 branch->UnuseAllInputs(); | 9183 branch->UnuseAllInputs(); |
9233 } | 9184 } |
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9770 | 9721 |
9771 | 9722 |
9772 // Insert MaterializeObject instruction for the given allocation before | 9723 // Insert MaterializeObject instruction for the given allocation before |
9773 // the given instruction that can deoptimize. | 9724 // the given instruction that can deoptimize. |
9774 void AllocationSinking::CreateMaterializationAt( | 9725 void AllocationSinking::CreateMaterializationAt( |
9775 Instruction* exit, | 9726 Instruction* exit, |
9776 AllocateObjectInstr* alloc, | 9727 AllocateObjectInstr* alloc, |
9777 const Class& cls, | 9728 const Class& cls, |
9778 const ZoneGrowableArray<const Object*>& slots) { | 9729 const ZoneGrowableArray<const Object*>& slots) { |
9779 ZoneGrowableArray<Value*>* values = | 9730 ZoneGrowableArray<Value*>* values = |
9780 new(isolate()) ZoneGrowableArray<Value*>(slots.length()); | 9731 new(I) ZoneGrowableArray<Value*>(slots.length()); |
9781 | 9732 |
9782 // Insert load instruction for every field. | 9733 // Insert load instruction for every field. |
9783 for (intptr_t i = 0; i < slots.length(); i++) { | 9734 for (intptr_t i = 0; i < slots.length(); i++) { |
9784 LoadFieldInstr* load = slots[i]->IsField() | 9735 LoadFieldInstr* load = slots[i]->IsField() |
9785 ? new(isolate()) LoadFieldInstr( | 9736 ? new(I) LoadFieldInstr( |
9786 new(isolate()) Value(alloc), | 9737 new(I) Value(alloc), |
9787 &Field::Cast(*slots[i]), | 9738 &Field::Cast(*slots[i]), |
9788 AbstractType::ZoneHandle(isolate(), AbstractType::null()), | 9739 AbstractType::ZoneHandle(I), |
9789 alloc->token_pos()) | 9740 alloc->token_pos()) |
9790 : new(isolate()) LoadFieldInstr( | 9741 : new(I) LoadFieldInstr( |
9791 new(isolate()) Value(alloc), | 9742 new(I) Value(alloc), |
9792 Smi::Cast(*slots[i]).Value(), | 9743 Smi::Cast(*slots[i]).Value(), |
9793 AbstractType::ZoneHandle(isolate(), AbstractType::null()), | 9744 AbstractType::ZoneHandle(I), |
9794 alloc->token_pos()); | 9745 alloc->token_pos()); |
9795 flow_graph_->InsertBefore( | 9746 flow_graph_->InsertBefore( |
9796 exit, load, NULL, FlowGraph::kValue); | 9747 exit, load, NULL, FlowGraph::kValue); |
9797 values->Add(new(isolate()) Value(load)); | 9748 values->Add(new(I) Value(load)); |
9798 } | 9749 } |
9799 | 9750 |
9800 MaterializeObjectInstr* mat = | 9751 MaterializeObjectInstr* mat = |
9801 new(isolate()) MaterializeObjectInstr(cls, slots, values); | 9752 new(I) MaterializeObjectInstr(cls, slots, values); |
9802 flow_graph_->InsertBefore(exit, mat, NULL, FlowGraph::kValue); | 9753 flow_graph_->InsertBefore(exit, mat, NULL, FlowGraph::kValue); |
9803 | 9754 |
9804 // Replace all mentions of this allocation with a newly inserted | 9755 // Replace all mentions of this allocation with a newly inserted |
9805 // MaterializeObject instruction. | 9756 // MaterializeObject instruction. |
9806 // We must preserve the identity: all mentions are replaced by the same | 9757 // We must preserve the identity: all mentions are replaced by the same |
9807 // materialization. | 9758 // materialization. |
9808 for (Environment::DeepIterator env_it(exit->env()); | 9759 for (Environment::DeepIterator env_it(exit->env()); |
9809 !env_it.Done(); | 9760 !env_it.Done(); |
9810 env_it.Advance()) { | 9761 env_it.Advance()) { |
9811 Value* use = env_it.CurrentValue(); | 9762 Value* use = env_it.CurrentValue(); |
9812 if (use->definition() == alloc) { | 9763 if (use->definition() == alloc) { |
9813 use->RemoveFromUseList(); | 9764 use->RemoveFromUseList(); |
9814 use->set_definition(mat); | 9765 use->set_definition(mat); |
9815 mat->AddEnvUse(use); | 9766 mat->AddEnvUse(use); |
9816 } | 9767 } |
9817 } | 9768 } |
9818 | 9769 |
9819 // Record inserted materialization. | 9770 // Record inserted materialization. |
9820 materializations_.Add(mat); | 9771 materializations_.Add(mat); |
9821 } | 9772 } |
9822 | 9773 |
9823 | 9774 |
9824 void AllocationSinking::InsertMaterializations(AllocateObjectInstr* alloc) { | 9775 void AllocationSinking::InsertMaterializations(AllocateObjectInstr* alloc) { |
9825 // Collect all fields that are written for this instance. | 9776 // Collect all fields that are written for this instance. |
9826 ZoneGrowableArray<const Object*>* slots = | 9777 ZoneGrowableArray<const Object*>* slots = |
9827 new(isolate()) ZoneGrowableArray<const Object*>(5); | 9778 new(I) ZoneGrowableArray<const Object*>(5); |
9828 | 9779 |
9829 for (Value* use = alloc->input_use_list(); | 9780 for (Value* use = alloc->input_use_list(); |
9830 use != NULL; | 9781 use != NULL; |
9831 use = use->next_use()) { | 9782 use = use->next_use()) { |
9832 StoreInstanceFieldInstr* store = use->instruction()->AsStoreInstanceField(); | 9783 StoreInstanceFieldInstr* store = use->instruction()->AsStoreInstanceField(); |
9833 if (!store->field().IsNull()) { | 9784 if (!store->field().IsNull()) { |
9834 AddSlot(slots, store->field()); | 9785 AddSlot(slots, store->field()); |
9835 } else { | 9786 } else { |
9836 AddSlot(slots, Smi::ZoneHandle(isolate(), | 9787 AddSlot(slots, Smi::ZoneHandle(I, Smi::New(store->offset_in_bytes()))); |
9837 Smi::New(store->offset_in_bytes()))); | |
9838 } | 9788 } |
9839 } | 9789 } |
9840 | 9790 |
9841 if (alloc->ArgumentCount() > 0) { | 9791 if (alloc->ArgumentCount() > 0) { |
9842 ASSERT(alloc->ArgumentCount() == 1); | 9792 ASSERT(alloc->ArgumentCount() == 1); |
9843 intptr_t type_args_offset = alloc->cls().type_arguments_field_offset(); | 9793 intptr_t type_args_offset = alloc->cls().type_arguments_field_offset(); |
9844 AddSlot(slots, Smi::ZoneHandle(isolate(), Smi::New(type_args_offset))); | 9794 AddSlot(slots, Smi::ZoneHandle(I, Smi::New(type_args_offset))); |
9845 } | 9795 } |
9846 | 9796 |
9847 // Collect all instructions that mention this object in the environment. | 9797 // Collect all instructions that mention this object in the environment. |
9848 GrowableArray<Instruction*> exits(10); | 9798 GrowableArray<Instruction*> exits(10); |
9849 for (Value* use = alloc->env_use_list(); | 9799 for (Value* use = alloc->env_use_list(); |
9850 use != NULL; | 9800 use != NULL; |
9851 use = use->next_use()) { | 9801 use = use->next_use()) { |
9852 AddInstruction(&exits, use->instruction()); | 9802 AddInstruction(&exits, use->instruction()); |
9853 } | 9803 } |
9854 | 9804 |
9855 // Insert materializations at environment uses. | 9805 // Insert materializations at environment uses. |
9856 for (intptr_t i = 0; i < exits.length(); i++) { | 9806 for (intptr_t i = 0; i < exits.length(); i++) { |
9857 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); | 9807 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); |
9858 } | 9808 } |
9859 } | 9809 } |
9860 | 9810 |
9861 | 9811 |
9862 } // namespace dart | 9812 } // namespace dart |
OLD | NEW |