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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 } | 151 } |
152 } | 152 } |
153 | 153 |
154 for (intptr_t i = 0; i < class_ids.length(); i++) { | 154 for (intptr_t i = 0; i < class_ids.length(); i++) { |
155 if (class_ids[i] == kDynamicCid) { | 155 if (class_ids[i] == kDynamicCid) { |
156 // Not all cid-s known. | 156 // Not all cid-s known. |
157 return false; | 157 return false; |
158 } | 158 } |
159 } | 159 } |
160 | 160 |
161 const Array& args_desc_array = Array::Handle( | 161 const Array& args_desc_array = Array::Handle(isolate(), |
162 ArgumentsDescriptor::New(call->ArgumentCount(), call->argument_names())); | 162 ArgumentsDescriptor::New(call->ArgumentCount(), call->argument_names())); |
163 ArgumentsDescriptor args_desc(args_desc_array); | 163 ArgumentsDescriptor args_desc(args_desc_array); |
164 const Class& receiver_class = Class::Handle( | 164 const Class& receiver_class = Class::Handle(isolate(), |
165 Isolate::Current()->class_table()->At(class_ids[0])); | 165 isolate()->class_table()->At(class_ids[0])); |
166 const Function& function = Function::Handle( | 166 const Function& function = Function::Handle(isolate(), |
167 Resolver::ResolveDynamicForReceiverClass( | 167 Resolver::ResolveDynamicForReceiverClass( |
168 receiver_class, | 168 receiver_class, |
169 call->function_name(), | 169 call->function_name(), |
170 args_desc)); | 170 args_desc)); |
171 if (function.IsNull()) { | 171 if (function.IsNull()) { |
172 return false; | 172 return false; |
173 } | 173 } |
174 // Create new ICData, do not modify the one attached to the instruction | 174 // Create new ICData, do not modify the one attached to the instruction |
175 // since it is attached to the assembly instruction itself. | 175 // since it is attached to the assembly instruction itself. |
176 // TODO(srdjan): Prevent modification of ICData object that is | 176 // TODO(srdjan): Prevent modification of ICData object that is |
177 // referenced in assembly code. | 177 // referenced in assembly code. |
178 ICData& ic_data = ICData::ZoneHandle(ICData::New( | 178 ICData& ic_data = ICData::ZoneHandle(isolate(), ICData::New( |
179 flow_graph_->parsed_function().function(), | 179 flow_graph_->parsed_function().function(), |
180 call->function_name(), | 180 call->function_name(), |
181 args_desc_array, | 181 args_desc_array, |
182 call->deopt_id(), | 182 call->deopt_id(), |
183 class_ids.length())); | 183 class_ids.length())); |
184 if (class_ids.length() > 1) { | 184 if (class_ids.length() > 1) { |
185 ic_data.AddCheck(class_ids, function); | 185 ic_data.AddCheck(class_ids, function); |
186 } else { | 186 } else { |
187 ASSERT(class_ids.length() == 1); | 187 ASSERT(class_ids.length() == 1); |
188 ic_data.AddReceiverCheck(class_ids[0], function); | 188 ic_data.AddReceiverCheck(class_ids[0], function); |
189 } | 189 } |
190 call->set_ic_data(&ic_data); | 190 call->set_ic_data(&ic_data); |
191 return true; | 191 return true; |
192 } | 192 } |
193 | 193 |
194 | 194 |
195 static const ICData& TrySpecializeICData(const ICData& ic_data, intptr_t cid) { | 195 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data, |
| 196 intptr_t cid) { |
196 ASSERT(ic_data.NumArgsTested() == 1); | 197 ASSERT(ic_data.NumArgsTested() == 1); |
197 | 198 |
198 if ((ic_data.NumberOfChecks() == 1) && | 199 if ((ic_data.NumberOfChecks() == 1) && |
199 (ic_data.GetReceiverClassIdAt(0) == cid)) { | 200 (ic_data.GetReceiverClassIdAt(0) == cid)) { |
200 return ic_data; // Nothing to do | 201 return ic_data; // Nothing to do |
201 } | 202 } |
202 | 203 |
203 const Function& function = | 204 const Function& function = |
204 Function::Handle(ic_data.GetTargetForReceiverClassId(cid)); | 205 Function::Handle(isolate(), ic_data.GetTargetForReceiverClassId(cid)); |
205 // TODO(fschneider): Try looking up the function on the class if it is | 206 // TODO(fschneider): Try looking up the function on the class if it is |
206 // not found in the ICData. | 207 // not found in the ICData. |
207 if (!function.IsNull()) { | 208 if (!function.IsNull()) { |
208 const ICData& new_ic_data = ICData::ZoneHandle(ICData::New( | 209 const ICData& new_ic_data = ICData::ZoneHandle(isolate(), ICData::New( |
209 Function::Handle(ic_data.owner()), | 210 Function::Handle(isolate(), ic_data.owner()), |
210 String::Handle(ic_data.target_name()), | 211 String::Handle(isolate(), ic_data.target_name()), |
211 Object::empty_array(), // Dummy argument descriptor. | 212 Object::empty_array(), // Dummy argument descriptor. |
212 ic_data.deopt_id(), | 213 ic_data.deopt_id(), |
213 ic_data.NumArgsTested())); | 214 ic_data.NumArgsTested())); |
214 new_ic_data.SetDeoptReasons(ic_data.DeoptReasons()); | 215 new_ic_data.SetDeoptReasons(ic_data.DeoptReasons()); |
215 new_ic_data.AddReceiverCheck(cid, function); | 216 new_ic_data.AddReceiverCheck(cid, function); |
216 return new_ic_data; | 217 return new_ic_data; |
217 } | 218 } |
218 | 219 |
219 return ic_data; | 220 return ic_data; |
220 } | 221 } |
(...skipping 12 matching lines...) Expand all Loading... |
233 } | 234 } |
234 | 235 |
235 const ICData& ic_data = TrySpecializeICData(call->ic_data(), receiver_cid); | 236 const ICData& ic_data = TrySpecializeICData(call->ic_data(), receiver_cid); |
236 if (ic_data.raw() == call->ic_data().raw()) { | 237 if (ic_data.raw() == call->ic_data().raw()) { |
237 // No specialization. | 238 // No specialization. |
238 return; | 239 return; |
239 } | 240 } |
240 | 241 |
241 const bool with_checks = false; | 242 const bool with_checks = false; |
242 PolymorphicInstanceCallInstr* specialized = | 243 PolymorphicInstanceCallInstr* specialized = |
243 new PolymorphicInstanceCallInstr(call->instance_call(), | 244 new(isolate()) PolymorphicInstanceCallInstr(call->instance_call(), |
244 ic_data, | 245 ic_data, |
245 with_checks); | 246 with_checks); |
246 call->ReplaceWith(specialized, current_iterator()); | 247 call->ReplaceWith(specialized, current_iterator()); |
247 } | 248 } |
248 | 249 |
249 | 250 |
250 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) { | 251 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) { |
251 BinarySmiOpInstr* instr = d->AsBinarySmiOp(); | 252 BinarySmiOpInstr* instr = d->AsBinarySmiOp(); |
252 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) { | 253 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) { |
253 return instr; | 254 return instr; |
254 } | 255 } |
255 return NULL; | 256 return NULL; |
(...skipping 30 matching lines...) Expand all Loading... |
286 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) { | 287 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) { |
287 smi_shift_left = AsSmiShiftLeftInstruction(right_instr); | 288 smi_shift_left = AsSmiShiftLeftInstruction(right_instr); |
288 } | 289 } |
289 if (smi_shift_left == NULL) return; | 290 if (smi_shift_left == NULL) return; |
290 | 291 |
291 // Pattern recognized. | 292 // Pattern recognized. |
292 smi_shift_left->set_is_truncating(true); | 293 smi_shift_left->set_is_truncating(true); |
293 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); | 294 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); |
294 if (bit_and_instr->IsBinaryMintOp()) { | 295 if (bit_and_instr->IsBinaryMintOp()) { |
295 // Replace Mint op with Smi op. | 296 // Replace Mint op with Smi op. |
296 BinarySmiOpInstr* smi_op = new BinarySmiOpInstr( | 297 BinarySmiOpInstr* smi_op = new(isolate()) BinarySmiOpInstr( |
297 Token::kBIT_AND, | 298 Token::kBIT_AND, |
298 new Value(left_instr), | 299 new(isolate()) Value(left_instr), |
299 new Value(right_instr), | 300 new(isolate()) Value(right_instr), |
300 Isolate::kNoDeoptId, // BIT_AND cannot deoptimize. | 301 Isolate::kNoDeoptId, // BIT_AND cannot deoptimize. |
301 Scanner::kNoSourcePos); | 302 Scanner::kNoSourcePos); |
302 bit_and_instr->ReplaceWith(smi_op, current_iterator()); | 303 bit_and_instr->ReplaceWith(smi_op, current_iterator()); |
303 } | 304 } |
304 } | 305 } |
305 | 306 |
306 | 307 |
307 | 308 |
308 // Used by TryMergeDivMod. | 309 // Used by TryMergeDivMod. |
309 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction, | 310 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction, |
310 // and the using instruction. This is an intermediate step before merging. | 311 // and the using instruction. This is an intermediate step before merging. |
311 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr, | 312 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr, |
312 intptr_t ix, | 313 intptr_t ix, |
313 intptr_t cid) { | 314 intptr_t cid) { |
314 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(cid); | 315 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(cid); |
315 ConstantInstr* index_instr = | 316 ConstantInstr* index_instr = |
316 flow_graph()->GetConstant(Smi::Handle(Smi::New(ix))); | 317 flow_graph()->GetConstant(Smi::Handle(isolate(), Smi::New(ix))); |
317 LoadIndexedInstr* load = new LoadIndexedInstr(new Value(instr), | 318 LoadIndexedInstr* load = |
318 new Value(index_instr), | 319 new(isolate()) LoadIndexedInstr(new(isolate()) Value(instr), |
319 index_scale, | 320 new(isolate()) Value(index_instr), |
320 cid, | 321 index_scale, |
321 Isolate::kNoDeoptId, | 322 cid, |
322 instr->token_pos()); | 323 Isolate::kNoDeoptId, |
| 324 instr->token_pos()); |
323 instr->ReplaceUsesWith(load); | 325 instr->ReplaceUsesWith(load); |
324 flow_graph()->InsertAfter(instr, load, NULL, FlowGraph::kValue); | 326 flow_graph()->InsertAfter(instr, load, NULL, FlowGraph::kValue); |
325 } | 327 } |
326 | 328 |
327 | 329 |
328 void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr, | 330 void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr, |
329 intptr_t index, | 331 intptr_t index, |
330 Representation rep, | 332 Representation rep, |
331 intptr_t cid) { | 333 intptr_t cid) { |
332 ExtractNthOutputInstr* extract = new ExtractNthOutputInstr(new Value(instr), | 334 ExtractNthOutputInstr* extract = |
333 index, | 335 new(isolate()) ExtractNthOutputInstr(new(isolate()) Value(instr), |
334 rep, | 336 index, |
335 cid); | 337 rep, |
| 338 cid); |
336 instr->ReplaceUsesWith(extract); | 339 instr->ReplaceUsesWith(extract); |
337 flow_graph()->InsertAfter(instr, extract, NULL, FlowGraph::kValue); | 340 flow_graph()->InsertAfter(instr, extract, NULL, FlowGraph::kValue); |
338 } | 341 } |
339 | 342 |
340 | 343 |
341 // Dart: | 344 // Dart: |
342 // var x = d % 10; | 345 // var x = d % 10; |
343 // var y = d ~/ 10; | 346 // var y = d ~/ 10; |
344 // var z = x + y; | 347 // var z = x + y; |
345 // | 348 // |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 AppendExtractNthOutputForMerged( | 389 AppendExtractNthOutputForMerged( |
387 curr_instr, | 390 curr_instr, |
388 MergedMathInstr::OutputIndexOf(curr_instr->op_kind()), | 391 MergedMathInstr::OutputIndexOf(curr_instr->op_kind()), |
389 kTagged, kSmiCid); | 392 kTagged, kSmiCid); |
390 ASSERT(other_binop->HasUses()); | 393 ASSERT(other_binop->HasUses()); |
391 AppendExtractNthOutputForMerged( | 394 AppendExtractNthOutputForMerged( |
392 other_binop, | 395 other_binop, |
393 MergedMathInstr::OutputIndexOf(other_binop->op_kind()), | 396 MergedMathInstr::OutputIndexOf(other_binop->op_kind()), |
394 kTagged, kSmiCid); | 397 kTagged, kSmiCid); |
395 | 398 |
396 ZoneGrowableArray<Value*>* args = new ZoneGrowableArray<Value*>(2); | 399 ZoneGrowableArray<Value*>* args = |
397 args->Add(new Value(curr_instr->left()->definition())); | 400 new(isolate()) ZoneGrowableArray<Value*>(2); |
398 args->Add(new Value(curr_instr->right()->definition())); | 401 args->Add(new(isolate()) Value(curr_instr->left()->definition())); |
| 402 args->Add(new(isolate()) Value(curr_instr->right()->definition())); |
399 | 403 |
400 // Replace with TruncDivMod. | 404 // Replace with TruncDivMod. |
401 MergedMathInstr* div_mod = new MergedMathInstr( | 405 MergedMathInstr* div_mod = new(isolate()) MergedMathInstr( |
402 args, | 406 args, |
403 curr_instr->deopt_id(), | 407 curr_instr->deopt_id(), |
404 MergedMathInstr::kTruncDivMod); | 408 MergedMathInstr::kTruncDivMod); |
405 curr_instr->ReplaceWith(div_mod, current_iterator()); | 409 curr_instr->ReplaceWith(div_mod, current_iterator()); |
406 other_binop->ReplaceUsesWith(div_mod); | 410 other_binop->ReplaceUsesWith(div_mod); |
407 other_binop->RemoveFromGraph(); | 411 other_binop->RemoveFromGraph(); |
408 // Only one merge possible. Because canonicalization happens later, | 412 // Only one merge possible. Because canonicalization happens later, |
409 // more candidates are possible. | 413 // more candidates are possible. |
410 // TODO(srdjan): Allow merging of trunc-div/mod into truncDivMod. | 414 // TODO(srdjan): Allow merging of trunc-div/mod into truncDivMod. |
411 break; | 415 break; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 (*merge_candidates)[k] = NULL; // Clear it. | 450 (*merge_candidates)[k] = NULL; // Clear it. |
447 ASSERT(curr_instr->HasUses()); | 451 ASSERT(curr_instr->HasUses()); |
448 AppendExtractNthOutputForMerged(curr_instr, | 452 AppendExtractNthOutputForMerged(curr_instr, |
449 MergedMathInstr::OutputIndexOf(kind), | 453 MergedMathInstr::OutputIndexOf(kind), |
450 kUnboxedDouble, kDoubleCid); | 454 kUnboxedDouble, kDoubleCid); |
451 ASSERT(other_op->HasUses()); | 455 ASSERT(other_op->HasUses()); |
452 AppendExtractNthOutputForMerged( | 456 AppendExtractNthOutputForMerged( |
453 other_op, | 457 other_op, |
454 MergedMathInstr::OutputIndexOf(other_kind), | 458 MergedMathInstr::OutputIndexOf(other_kind), |
455 kUnboxedDouble, kDoubleCid); | 459 kUnboxedDouble, kDoubleCid); |
456 ZoneGrowableArray<Value*>* args = new ZoneGrowableArray<Value*>(1); | 460 ZoneGrowableArray<Value*>* args = |
457 args->Add(new Value(curr_instr->value()->definition())); | 461 new(isolate()) ZoneGrowableArray<Value*>(1); |
| 462 args->Add(new(isolate()) Value(curr_instr->value()->definition())); |
458 // Replace with SinCos. | 463 // Replace with SinCos. |
459 MergedMathInstr* sin_cos = | 464 MergedMathInstr* sin_cos = |
460 new MergedMathInstr(args, curr_instr->DeoptimizationTarget(), | 465 new(isolate()) MergedMathInstr(args, |
461 MergedMathInstr::kSinCos); | 466 curr_instr->DeoptimizationTarget(), |
| 467 MergedMathInstr::kSinCos); |
462 curr_instr->ReplaceWith(sin_cos, current_iterator()); | 468 curr_instr->ReplaceWith(sin_cos, current_iterator()); |
463 other_op->ReplaceUsesWith(sin_cos); | 469 other_op->ReplaceUsesWith(sin_cos); |
464 other_op->RemoveFromGraph(); | 470 other_op->RemoveFromGraph(); |
465 // Only one merge possible. Because canonicalization happens later, | 471 // Only one merge possible. Because canonicalization happens later, |
466 // more candidates are possible. | 472 // more candidates are possible. |
467 // TODO(srdjan): Allow merging of sin/cos into sincos. | 473 // TODO(srdjan): Allow merging of sin/cos into sincos. |
468 break; | 474 break; |
469 } | 475 } |
470 } | 476 } |
471 } | 477 } |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 } else { | 604 } else { |
599 deopt_target = insert_before = use->instruction(); | 605 deopt_target = insert_before = use->instruction(); |
600 } | 606 } |
601 | 607 |
602 Definition* converted = NULL; | 608 Definition* converted = NULL; |
603 if ((from == kTagged) && (to == kUnboxedMint)) { | 609 if ((from == kTagged) && (to == kUnboxedMint)) { |
604 ASSERT((deopt_target != NULL) || | 610 ASSERT((deopt_target != NULL) || |
605 (use->Type()->ToCid() == kUnboxedMint)); | 611 (use->Type()->ToCid() == kUnboxedMint)); |
606 const intptr_t deopt_id = (deopt_target != NULL) ? | 612 const intptr_t deopt_id = (deopt_target != NULL) ? |
607 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 613 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
608 converted = new UnboxIntegerInstr(use->CopyWithType(), deopt_id); | 614 converted = new(isolate()) UnboxIntegerInstr(use->CopyWithType(), deopt_id); |
609 | 615 |
610 } else if ((from == kUnboxedMint) && (to == kTagged)) { | 616 } else if ((from == kUnboxedMint) && (to == kTagged)) { |
611 converted = new BoxIntegerInstr(use->CopyWithType()); | 617 converted = new(isolate()) BoxIntegerInstr(use->CopyWithType()); |
612 | 618 |
613 } else if (from == kUnboxedMint && to == kUnboxedDouble) { | 619 } else if (from == kUnboxedMint && to == kUnboxedDouble) { |
614 ASSERT(CanUnboxDouble()); | 620 ASSERT(CanUnboxDouble()); |
615 // Convert by boxing/unboxing. | 621 // Convert by boxing/unboxing. |
616 // TODO(fschneider): Implement direct unboxed mint-to-double conversion. | 622 // TODO(fschneider): Implement direct unboxed mint-to-double conversion. |
617 BoxIntegerInstr* boxed = new BoxIntegerInstr(use->CopyWithType()); | 623 BoxIntegerInstr* boxed = |
| 624 new(isolate()) BoxIntegerInstr(use->CopyWithType()); |
618 use->BindTo(boxed); | 625 use->BindTo(boxed); |
619 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); | 626 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); |
620 | 627 |
621 const intptr_t deopt_id = (deopt_target != NULL) ? | 628 const intptr_t deopt_id = (deopt_target != NULL) ? |
622 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 629 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
623 converted = new UnboxDoubleInstr(new Value(boxed), deopt_id); | 630 converted = new(isolate()) UnboxDoubleInstr( |
| 631 new(isolate()) Value(boxed), deopt_id); |
624 | 632 |
625 } else if ((from == kUnboxedDouble) && (to == kTagged)) { | 633 } else if ((from == kUnboxedDouble) && (to == kTagged)) { |
626 ASSERT(CanUnboxDouble()); | 634 ASSERT(CanUnboxDouble()); |
627 converted = new BoxDoubleInstr(use->CopyWithType()); | 635 converted = new(isolate()) BoxDoubleInstr(use->CopyWithType()); |
628 | 636 |
629 } else if ((from == kTagged) && (to == kUnboxedDouble)) { | 637 } else if ((from == kTagged) && (to == kUnboxedDouble)) { |
630 ASSERT(CanUnboxDouble()); | 638 ASSERT(CanUnboxDouble()); |
631 ASSERT((deopt_target != NULL) || | 639 ASSERT((deopt_target != NULL) || |
632 (use->Type()->ToCid() == kDoubleCid)); | 640 (use->Type()->ToCid() == kDoubleCid)); |
633 const intptr_t deopt_id = (deopt_target != NULL) ? | 641 const intptr_t deopt_id = (deopt_target != NULL) ? |
634 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 642 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
635 ConstantInstr* constant = use->definition()->AsConstant(); | 643 ConstantInstr* constant = use->definition()->AsConstant(); |
636 if ((constant != NULL) && constant->value().IsSmi()) { | 644 if ((constant != NULL) && constant->value().IsSmi()) { |
637 const double dbl_val = Smi::Cast(constant->value()).AsDoubleValue(); | 645 const double dbl_val = Smi::Cast(constant->value()).AsDoubleValue(); |
638 const Double& dbl_obj = | 646 const Double& dbl_obj = |
639 Double::ZoneHandle(Double::New(dbl_val, Heap::kOld)); | 647 Double::ZoneHandle(isolate(), Double::New(dbl_val, Heap::kOld)); |
640 ConstantInstr* double_const = flow_graph()->GetConstant(dbl_obj); | 648 ConstantInstr* double_const = flow_graph()->GetConstant(dbl_obj); |
641 converted = new UnboxDoubleInstr(new Value(double_const), deopt_id); | 649 converted = new(isolate()) UnboxDoubleInstr( |
| 650 new(isolate()) Value(double_const), deopt_id); |
642 } else { | 651 } else { |
643 converted = new UnboxDoubleInstr(use->CopyWithType(), deopt_id); | 652 converted = new(isolate()) UnboxDoubleInstr( |
| 653 use->CopyWithType(), deopt_id); |
644 } | 654 } |
645 } else if ((from == kTagged) && (to == kUnboxedFloat32x4)) { | 655 } else if ((from == kTagged) && (to == kUnboxedFloat32x4)) { |
646 ASSERT((deopt_target != NULL) || | 656 ASSERT((deopt_target != NULL) || |
647 (use->Type()->ToCid() == kFloat32x4Cid)); | 657 (use->Type()->ToCid() == kFloat32x4Cid)); |
648 const intptr_t deopt_id = (deopt_target != NULL) ? | 658 const intptr_t deopt_id = (deopt_target != NULL) ? |
649 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 659 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
650 converted = new UnboxFloat32x4Instr(use->CopyWithType(), deopt_id); | 660 converted = new(isolate()) UnboxFloat32x4Instr( |
| 661 use->CopyWithType(), deopt_id); |
651 } else if ((from == kUnboxedFloat32x4) && (to == kTagged)) { | 662 } else if ((from == kUnboxedFloat32x4) && (to == kTagged)) { |
652 converted = new BoxFloat32x4Instr(use->CopyWithType()); | 663 converted = new(isolate()) BoxFloat32x4Instr(use->CopyWithType()); |
653 } else if ((from == kTagged) && (to == kUnboxedInt32x4)) { | 664 } else if ((from == kTagged) && (to == kUnboxedInt32x4)) { |
654 ASSERT((deopt_target != NULL) || (use->Type()->ToCid() == kInt32x4Cid)); | 665 ASSERT((deopt_target != NULL) || (use->Type()->ToCid() == kInt32x4Cid)); |
655 const intptr_t deopt_id = (deopt_target != NULL) ? | 666 const intptr_t deopt_id = (deopt_target != NULL) ? |
656 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 667 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
657 converted = new UnboxInt32x4Instr(use->CopyWithType(), deopt_id); | 668 converted = new(isolate()) UnboxInt32x4Instr(use->CopyWithType(), deopt_id); |
658 } else if ((from == kUnboxedInt32x4) && (to == kTagged)) { | 669 } else if ((from == kUnboxedInt32x4) && (to == kTagged)) { |
659 converted = new BoxInt32x4Instr(use->CopyWithType()); | 670 converted = new(isolate()) BoxInt32x4Instr(use->CopyWithType()); |
660 } else if ((from == kTagged) && (to == kUnboxedFloat64x2)) { | 671 } else if ((from == kTagged) && (to == kUnboxedFloat64x2)) { |
661 ASSERT((deopt_target != NULL) || (use->Type()->ToCid() == kFloat64x2Cid)); | 672 ASSERT((deopt_target != NULL) || (use->Type()->ToCid() == kFloat64x2Cid)); |
662 const intptr_t deopt_id = (deopt_target != NULL) ? | 673 const intptr_t deopt_id = (deopt_target != NULL) ? |
663 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 674 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
664 converted = new UnboxFloat64x2Instr(use->CopyWithType(), deopt_id); | 675 converted = new(isolate()) UnboxFloat64x2Instr( |
| 676 use->CopyWithType(), deopt_id); |
665 } else if ((from == kUnboxedFloat64x2) && (to == kTagged)) { | 677 } else if ((from == kUnboxedFloat64x2) && (to == kTagged)) { |
666 converted = new BoxFloat64x2Instr(use->CopyWithType()); | 678 converted = new(isolate()) BoxFloat64x2Instr(use->CopyWithType()); |
667 } else { | 679 } else { |
668 // We have failed to find a suitable conversion instruction. | 680 // We have failed to find a suitable conversion instruction. |
669 // Insert two "dummy" conversion instructions with the correct | 681 // Insert two "dummy" conversion instructions with the correct |
670 // "from" and "to" representation. The inserted instructions will | 682 // "from" and "to" representation. The inserted instructions will |
671 // trigger a deoptimization if executed. See #12417 for a discussion. | 683 // trigger a deoptimization if executed. See #12417 for a discussion. |
672 const intptr_t deopt_id = (deopt_target != NULL) ? | 684 const intptr_t deopt_id = (deopt_target != NULL) ? |
673 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 685 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
674 ASSERT(from != kTagged); | 686 ASSERT(from != kTagged); |
675 ASSERT(to != kTagged); | 687 ASSERT(to != kTagged); |
676 Definition* boxed = NULL; | 688 Definition* boxed = NULL; |
677 if (from == kUnboxedDouble) { | 689 if (from == kUnboxedDouble) { |
678 boxed = new BoxDoubleInstr(use->CopyWithType()); | 690 boxed = new(isolate()) BoxDoubleInstr(use->CopyWithType()); |
679 } else if (from == kUnboxedInt32x4) { | 691 } else if (from == kUnboxedInt32x4) { |
680 boxed = new BoxInt32x4Instr(use->CopyWithType()); | 692 boxed = new(isolate()) BoxInt32x4Instr(use->CopyWithType()); |
681 } else if (from == kUnboxedFloat32x4) { | 693 } else if (from == kUnboxedFloat32x4) { |
682 boxed = new BoxFloat32x4Instr(use->CopyWithType()); | 694 boxed = new(isolate()) BoxFloat32x4Instr(use->CopyWithType()); |
683 } else if (from == kUnboxedMint) { | 695 } else if (from == kUnboxedMint) { |
684 boxed = new BoxIntegerInstr(use->CopyWithType()); | 696 boxed = new(isolate()) BoxIntegerInstr(use->CopyWithType()); |
685 } else if (from == kUnboxedFloat64x2) { | 697 } else if (from == kUnboxedFloat64x2) { |
686 boxed = new BoxFloat64x2Instr(use->CopyWithType()); | 698 boxed = new(isolate()) BoxFloat64x2Instr(use->CopyWithType()); |
687 } else { | 699 } else { |
688 UNIMPLEMENTED(); | 700 UNIMPLEMENTED(); |
689 } | 701 } |
690 use->BindTo(boxed); | 702 use->BindTo(boxed); |
691 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); | 703 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); |
692 Value* to_value = new Value(boxed); | 704 Value* to_value = new(isolate()) Value(boxed); |
693 if (to == kUnboxedDouble) { | 705 if (to == kUnboxedDouble) { |
694 converted = new UnboxDoubleInstr(to_value, deopt_id); | 706 converted = new(isolate()) UnboxDoubleInstr(to_value, deopt_id); |
695 } else if (to == kUnboxedInt32x4) { | 707 } else if (to == kUnboxedInt32x4) { |
696 converted = new UnboxInt32x4Instr(to_value, deopt_id); | 708 converted = new(isolate()) UnboxInt32x4Instr(to_value, deopt_id); |
697 } else if (to == kUnboxedFloat32x4) { | 709 } else if (to == kUnboxedFloat32x4) { |
698 converted = new UnboxFloat32x4Instr(to_value, deopt_id); | 710 converted = new(isolate()) UnboxFloat32x4Instr(to_value, deopt_id); |
699 } else if (to == kUnboxedMint) { | 711 } else if (to == kUnboxedMint) { |
700 converted = new UnboxIntegerInstr(to_value, deopt_id); | 712 converted = new(isolate()) UnboxIntegerInstr(to_value, deopt_id); |
701 } else if (to == kUnboxedFloat64x2) { | 713 } else if (to == kUnboxedFloat64x2) { |
702 converted = new UnboxFloat64x2Instr(to_value, deopt_id); | 714 converted = new(isolate()) UnboxFloat64x2Instr(to_value, deopt_id); |
703 } else { | 715 } else { |
704 UNIMPLEMENTED(); | 716 UNIMPLEMENTED(); |
705 } | 717 } |
706 } | 718 } |
707 ASSERT(converted != NULL); | 719 ASSERT(converted != NULL); |
708 InsertBefore(insert_before, converted, use->instruction()->env(), | 720 InsertBefore(insert_before, converted, use->instruction()->env(), |
709 FlowGraph::kValue); | 721 FlowGraph::kValue); |
710 if (is_environment_use) { | 722 if (is_environment_use) { |
711 use->BindToEnvironment(converted); | 723 use->BindToEnvironment(converted); |
712 } else { | 724 } else { |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
973 call->ReplaceWith(replacement, current_iterator()); | 985 call->ReplaceWith(replacement, current_iterator()); |
974 } | 986 } |
975 | 987 |
976 | 988 |
977 void FlowGraphOptimizer::AddCheckSmi(Definition* to_check, | 989 void FlowGraphOptimizer::AddCheckSmi(Definition* to_check, |
978 intptr_t deopt_id, | 990 intptr_t deopt_id, |
979 Environment* deopt_environment, | 991 Environment* deopt_environment, |
980 Instruction* insert_before) { | 992 Instruction* insert_before) { |
981 if (to_check->Type()->ToCid() != kSmiCid) { | 993 if (to_check->Type()->ToCid() != kSmiCid) { |
982 InsertBefore(insert_before, | 994 InsertBefore(insert_before, |
983 new CheckSmiInstr(new Value(to_check), | 995 new(isolate()) CheckSmiInstr(new(isolate()) Value(to_check), |
984 deopt_id, | 996 deopt_id, |
985 insert_before->token_pos()), | 997 insert_before->token_pos()), |
986 deopt_environment, | 998 deopt_environment, |
987 FlowGraph::kEffect); | 999 FlowGraph::kEffect); |
988 } | 1000 } |
989 } | 1001 } |
990 | 1002 |
991 | 1003 |
992 Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check, | 1004 Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check, |
993 const ICData& unary_checks, | 1005 const ICData& unary_checks, |
994 intptr_t deopt_id, | 1006 intptr_t deopt_id, |
995 intptr_t token_pos) { | 1007 intptr_t token_pos) { |
996 if ((unary_checks.NumberOfChecks() == 1) && | 1008 if ((unary_checks.NumberOfChecks() == 1) && |
997 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) { | 1009 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) { |
998 return new CheckSmiInstr(new Value(to_check), | 1010 return new(isolate()) CheckSmiInstr(new(isolate()) Value(to_check), |
999 deopt_id, | 1011 deopt_id, |
1000 token_pos); | 1012 token_pos); |
1001 } | 1013 } |
1002 return new CheckClassInstr( | 1014 return new(isolate()) CheckClassInstr( |
1003 new Value(to_check), deopt_id, unary_checks, token_pos); | 1015 new(isolate()) Value(to_check), deopt_id, unary_checks, token_pos); |
1004 } | 1016 } |
1005 | 1017 |
1006 | 1018 |
1007 void FlowGraphOptimizer::AddCheckClass(Definition* to_check, | 1019 void FlowGraphOptimizer::AddCheckClass(Definition* to_check, |
1008 const ICData& unary_checks, | 1020 const ICData& unary_checks, |
1009 intptr_t deopt_id, | 1021 intptr_t deopt_id, |
1010 Environment* deopt_environment, | 1022 Environment* deopt_environment, |
1011 Instruction* insert_before) { | 1023 Instruction* insert_before) { |
1012 // Type propagation has not run yet, we cannot eliminate the check. | 1024 // Type propagation has not run yet, we cannot eliminate the check. |
1013 Instruction* check = GetCheckClass( | 1025 Instruction* check = GetCheckClass( |
1014 to_check, unary_checks, deopt_id, insert_before->token_pos()); | 1026 to_check, unary_checks, deopt_id, insert_before->token_pos()); |
1015 InsertBefore(insert_before, check, deopt_environment, FlowGraph::kEffect); | 1027 InsertBefore(insert_before, check, deopt_environment, FlowGraph::kEffect); |
1016 } | 1028 } |
1017 | 1029 |
1018 | 1030 |
1019 void FlowGraphOptimizer::AddReceiverCheck(InstanceCallInstr* call) { | 1031 void FlowGraphOptimizer::AddReceiverCheck(InstanceCallInstr* call) { |
1020 AddCheckClass(call->ArgumentAt(0), | 1032 AddCheckClass(call->ArgumentAt(0), |
1021 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()), | 1033 ICData::ZoneHandle(isolate(), |
| 1034 call->ic_data()->AsUnaryClassChecks()), |
1022 call->deopt_id(), | 1035 call->deopt_id(), |
1023 call->env(), | 1036 call->env(), |
1024 call); | 1037 call); |
1025 } | 1038 } |
1026 | 1039 |
1027 | 1040 |
1028 static bool ArgIsAlways(intptr_t cid, | 1041 static bool ArgIsAlways(intptr_t cid, |
1029 const ICData& ic_data, | 1042 const ICData& ic_data, |
1030 intptr_t arg_number) { | 1043 intptr_t arg_number) { |
1031 ASSERT(ic_data.NumArgsTested() > arg_number); | 1044 ASSERT(ic_data.NumArgsTested() > arg_number); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1117 default: | 1130 default: |
1118 break; | 1131 break; |
1119 } | 1132 } |
1120 return kIllegalCid; | 1133 return kIllegalCid; |
1121 } | 1134 } |
1122 | 1135 |
1123 | 1136 |
1124 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { | 1137 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { |
1125 // Check for monomorphic IC data. | 1138 // Check for monomorphic IC data. |
1126 if (!call->HasICData()) return false; | 1139 if (!call->HasICData()) return false; |
1127 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); | 1140 const ICData& ic_data = ICData::Handle(isolate(), |
| 1141 call->ic_data()->AsUnaryClassChecks()); |
1128 if (ic_data.NumberOfChecks() != 1) return false; | 1142 if (ic_data.NumberOfChecks() != 1) return false; |
1129 ASSERT(ic_data.HasOneTarget()); | 1143 ASSERT(ic_data.HasOneTarget()); |
1130 | 1144 |
1131 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); | 1145 const Function& target = Function::Handle(isolate(), ic_data.GetTargetAt(0)); |
1132 TargetEntryInstr* entry; | 1146 TargetEntryInstr* entry; |
1133 Definition* last; | 1147 Definition* last; |
1134 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), | 1148 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), |
1135 target, | 1149 target, |
1136 call, | 1150 call, |
1137 call->ArgumentAt(0), | 1151 call->ArgumentAt(0), |
1138 call->token_pos(), | 1152 call->token_pos(), |
1139 *call->ic_data(), | 1153 *call->ic_data(), |
1140 &entry, &last)) { | 1154 &entry, &last)) { |
1141 return false; | 1155 return false; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1174 const ICData& value_check, | 1188 const ICData& value_check, |
1175 TargetEntryInstr** entry, | 1189 TargetEntryInstr** entry, |
1176 Definition** last) { | 1190 Definition** last) { |
1177 intptr_t array_cid = MethodKindToCid(kind); | 1191 intptr_t array_cid = MethodKindToCid(kind); |
1178 ASSERT(array_cid != kIllegalCid); | 1192 ASSERT(array_cid != kIllegalCid); |
1179 | 1193 |
1180 Definition* array = receiver; | 1194 Definition* array = receiver; |
1181 Definition* index = call->ArgumentAt(1); | 1195 Definition* index = call->ArgumentAt(1); |
1182 Definition* stored_value = call->ArgumentAt(2); | 1196 Definition* stored_value = call->ArgumentAt(2); |
1183 | 1197 |
1184 *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(), | 1198 *entry = new(isolate()) TargetEntryInstr(flow_graph()->allocate_block_id(), |
1185 call->GetBlock()->try_index()); | 1199 call->GetBlock()->try_index()); |
1186 (*entry)->InheritDeoptTarget(call); | 1200 (*entry)->InheritDeoptTarget(isolate(), call); |
1187 Instruction* cursor = *entry; | 1201 Instruction* cursor = *entry; |
1188 if (FLAG_enable_type_checks) { | 1202 if (FLAG_enable_type_checks) { |
1189 // Only type check for the value. A type check for the index is not | 1203 // Only type check for the value. A type check for the index is not |
1190 // needed here because we insert a deoptimizing smi-check for the case | 1204 // needed here because we insert a deoptimizing smi-check for the case |
1191 // the index is not a smi. | 1205 // the index is not a smi. |
1192 const AbstractType& value_type = | 1206 const AbstractType& value_type = |
1193 AbstractType::ZoneHandle(target.ParameterTypeAt(2)); | 1207 AbstractType::ZoneHandle(isolate(), target.ParameterTypeAt(2)); |
1194 Definition* instantiator = NULL; | 1208 Definition* instantiator = NULL; |
1195 Definition* type_args = NULL; | 1209 Definition* type_args = NULL; |
1196 switch (array_cid) { | 1210 switch (array_cid) { |
1197 case kArrayCid: | 1211 case kArrayCid: |
1198 case kGrowableObjectArrayCid: { | 1212 case kGrowableObjectArrayCid: { |
1199 const Class& instantiator_class = Class::Handle(target.Owner()); | 1213 const Class& instantiator_class = |
| 1214 Class::Handle(isolate(), target.Owner()); |
1200 intptr_t type_arguments_field_offset = | 1215 intptr_t type_arguments_field_offset = |
1201 instantiator_class.type_arguments_field_offset(); | 1216 instantiator_class.type_arguments_field_offset(); |
1202 LoadFieldInstr* load_type_args = | 1217 LoadFieldInstr* load_type_args = |
1203 new LoadFieldInstr(new Value(array), | 1218 new(isolate()) LoadFieldInstr( |
1204 type_arguments_field_offset, | 1219 new(isolate()) Value(array), |
1205 Type::ZoneHandle(), // No type. | 1220 type_arguments_field_offset, |
1206 call->token_pos()); | 1221 Type::ZoneHandle(isolate(), Type::null()), // No type. |
| 1222 call->token_pos()); |
1207 cursor = flow_graph()->AppendTo(cursor, | 1223 cursor = flow_graph()->AppendTo(cursor, |
1208 load_type_args, | 1224 load_type_args, |
1209 NULL, | 1225 NULL, |
1210 FlowGraph::kValue); | 1226 FlowGraph::kValue); |
1211 | 1227 |
1212 instantiator = array; | 1228 instantiator = array; |
1213 type_args = load_type_args; | 1229 type_args = load_type_args; |
1214 break; | 1230 break; |
1215 } | 1231 } |
1216 case kTypedDataInt8ArrayCid: | 1232 case kTypedDataInt8ArrayCid: |
(...skipping 28 matching lines...) Expand all Loading... |
1245 ASSERT((array_cid != kTypedDataFloat64x2ArrayCid) || | 1261 ASSERT((array_cid != kTypedDataFloat64x2ArrayCid) || |
1246 value_type.IsFloat64x2Type()); | 1262 value_type.IsFloat64x2Type()); |
1247 ASSERT(value_type.IsInstantiated()); | 1263 ASSERT(value_type.IsInstantiated()); |
1248 break; | 1264 break; |
1249 } | 1265 } |
1250 default: | 1266 default: |
1251 // TODO(fschneider): Add support for other array types. | 1267 // TODO(fschneider): Add support for other array types. |
1252 UNREACHABLE(); | 1268 UNREACHABLE(); |
1253 } | 1269 } |
1254 AssertAssignableInstr* assert_value = | 1270 AssertAssignableInstr* assert_value = |
1255 new AssertAssignableInstr(token_pos, | 1271 new(isolate()) AssertAssignableInstr(token_pos, |
1256 new Value(stored_value), | 1272 new(isolate()) Value(stored_value), |
1257 new Value(instantiator), | 1273 new(isolate()) Value(instantiator), |
1258 new Value(type_args), | 1274 new(isolate()) Value(type_args), |
1259 value_type, | 1275 value_type, |
1260 Symbols::Value()); | 1276 Symbols::Value()); |
1261 // Newly inserted instructions that can deoptimize or throw an exception | 1277 // Newly inserted instructions that can deoptimize or throw an exception |
1262 // must have a deoptimization id that is valid for lookup in the unoptimized | 1278 // must have a deoptimization id that is valid for lookup in the unoptimized |
1263 // code. | 1279 // code. |
1264 assert_value->deopt_id_ = call->deopt_id(); | 1280 assert_value->deopt_id_ = call->deopt_id(); |
1265 cursor = flow_graph()->AppendTo(cursor, | 1281 cursor = flow_graph()->AppendTo(cursor, |
1266 assert_value, | 1282 assert_value, |
1267 call->env(), | 1283 call->env(), |
1268 FlowGraph::kValue); | 1284 FlowGraph::kValue); |
1269 } | 1285 } |
1270 | 1286 |
(...skipping 16 matching lines...) Expand all Loading... |
1287 Instruction* check = GetCheckClass( | 1303 Instruction* check = GetCheckClass( |
1288 stored_value, value_check, call->deopt_id(), call->token_pos()); | 1304 stored_value, value_check, call->deopt_id(), call->token_pos()); |
1289 cursor = flow_graph()->AppendTo(cursor, | 1305 cursor = flow_graph()->AppendTo(cursor, |
1290 check, | 1306 check, |
1291 call->env(), | 1307 call->env(), |
1292 FlowGraph::kEffect); | 1308 FlowGraph::kEffect); |
1293 } | 1309 } |
1294 | 1310 |
1295 if (array_cid == kTypedDataFloat32ArrayCid) { | 1311 if (array_cid == kTypedDataFloat32ArrayCid) { |
1296 stored_value = | 1312 stored_value = |
1297 new DoubleToFloatInstr(new Value(stored_value), call->deopt_id()); | 1313 new(isolate()) DoubleToFloatInstr( |
| 1314 new(isolate()) Value(stored_value), call->deopt_id()); |
1298 cursor = flow_graph()->AppendTo(cursor, | 1315 cursor = flow_graph()->AppendTo(cursor, |
1299 stored_value, | 1316 stored_value, |
1300 NULL, | 1317 NULL, |
1301 FlowGraph::kValue); | 1318 FlowGraph::kValue); |
1302 } | 1319 } |
1303 | 1320 |
1304 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); | 1321 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); |
1305 *last = new StoreIndexedInstr(new Value(array), | 1322 *last = new(isolate()) StoreIndexedInstr(new(isolate()) Value(array), |
1306 new Value(index), | 1323 new(isolate()) Value(index), |
1307 new Value(stored_value), | 1324 new(isolate()) Value(stored_value), |
1308 needs_store_barrier, | 1325 needs_store_barrier, |
1309 index_scale, | 1326 index_scale, |
1310 array_cid, | 1327 array_cid, |
1311 call->deopt_id(), | 1328 call->deopt_id(), |
1312 call->token_pos()); | 1329 call->token_pos()); |
1313 flow_graph()->AppendTo(cursor, | 1330 flow_graph()->AppendTo(cursor, |
1314 *last, | 1331 *last, |
1315 call->env(), | 1332 call->env(), |
1316 FlowGraph::kEffect); | 1333 FlowGraph::kEffect); |
1317 return true; | 1334 return true; |
1318 } | 1335 } |
1319 | 1336 |
1320 | 1337 |
1321 bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid, | 1338 bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid, |
1322 const Function& target, | 1339 const Function& target, |
1323 Instruction* call, | 1340 Instruction* call, |
1324 Definition* receiver, | 1341 Definition* receiver, |
1325 intptr_t token_pos, | 1342 intptr_t token_pos, |
1326 const ICData& ic_data, | 1343 const ICData& ic_data, |
1327 TargetEntryInstr** entry, | 1344 TargetEntryInstr** entry, |
1328 Definition** last) { | 1345 Definition** last) { |
1329 ICData& value_check = ICData::ZoneHandle(); | 1346 ICData& value_check = ICData::ZoneHandle(isolate(), ICData::null()); |
1330 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target); | 1347 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target); |
1331 switch (kind) { | 1348 switch (kind) { |
1332 // Recognized [] operators. | 1349 // Recognized [] operators. |
1333 case MethodRecognizer::kImmutableArrayGetIndexed: | 1350 case MethodRecognizer::kImmutableArrayGetIndexed: |
1334 case MethodRecognizer::kObjectArrayGetIndexed: | 1351 case MethodRecognizer::kObjectArrayGetIndexed: |
1335 case MethodRecognizer::kGrowableArrayGetIndexed: | 1352 case MethodRecognizer::kGrowableArrayGetIndexed: |
1336 case MethodRecognizer::kInt8ArrayGetIndexed: | 1353 case MethodRecognizer::kInt8ArrayGetIndexed: |
1337 case MethodRecognizer::kUint8ArrayGetIndexed: | 1354 case MethodRecognizer::kUint8ArrayGetIndexed: |
1338 case MethodRecognizer::kUint8ClampedArrayGetIndexed: | 1355 case MethodRecognizer::kUint8ClampedArrayGetIndexed: |
1339 case MethodRecognizer::kExternalUint8ArrayGetIndexed: | 1356 case MethodRecognizer::kExternalUint8ArrayGetIndexed: |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1555 } | 1572 } |
1556 } | 1573 } |
1557 | 1574 |
1558 | 1575 |
1559 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, | 1576 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, |
1560 intptr_t array_cid, | 1577 intptr_t array_cid, |
1561 Definition** array, | 1578 Definition** array, |
1562 Definition* index, | 1579 Definition* index, |
1563 Instruction** cursor) { | 1580 Instruction** cursor) { |
1564 // Insert index smi check. | 1581 // Insert index smi check. |
1565 *cursor = flow_graph()->AppendTo(*cursor, | 1582 *cursor = flow_graph()->AppendTo( |
1566 new CheckSmiInstr(new Value(index), | 1583 *cursor, |
1567 call->deopt_id(), | 1584 new(isolate()) CheckSmiInstr(new(isolate()) Value(index), |
1568 call->token_pos()), | 1585 call->deopt_id(), |
1569 call->env(), | 1586 call->token_pos()), |
1570 FlowGraph::kEffect); | 1587 call->env(), |
| 1588 FlowGraph::kEffect); |
1571 | 1589 |
1572 // Insert array length load and bounds check. | 1590 // Insert array length load and bounds check. |
1573 LoadFieldInstr* length = | 1591 LoadFieldInstr* length = |
1574 new LoadFieldInstr(new Value(*array), | 1592 new(isolate()) LoadFieldInstr( |
1575 CheckArrayBoundInstr::LengthOffsetFor(array_cid), | 1593 new(isolate()) Value(*array), |
1576 Type::ZoneHandle(Type::SmiType()), | 1594 CheckArrayBoundInstr::LengthOffsetFor(array_cid), |
1577 call->token_pos()); | 1595 Type::ZoneHandle(isolate(), Type::SmiType()), |
| 1596 call->token_pos()); |
1578 length->set_is_immutable( | 1597 length->set_is_immutable( |
1579 CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid)); | 1598 CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid)); |
1580 length->set_result_cid(kSmiCid); | 1599 length->set_result_cid(kSmiCid); |
1581 length->set_recognized_kind( | 1600 length->set_recognized_kind( |
1582 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); | 1601 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); |
1583 *cursor = flow_graph()->AppendTo(*cursor, | 1602 *cursor = flow_graph()->AppendTo(*cursor, |
1584 length, | 1603 length, |
1585 NULL, | 1604 NULL, |
1586 FlowGraph::kValue); | 1605 FlowGraph::kValue); |
1587 | 1606 |
1588 *cursor = flow_graph()->AppendTo(*cursor, | 1607 *cursor = flow_graph()->AppendTo(*cursor, |
1589 new CheckArrayBoundInstr( | 1608 new(isolate()) CheckArrayBoundInstr( |
1590 new Value(length), | 1609 new(isolate()) Value(length), |
1591 new Value(index), | 1610 new(isolate()) Value(index), |
1592 call->deopt_id()), | 1611 call->deopt_id()), |
1593 call->env(), | 1612 call->env(), |
1594 FlowGraph::kEffect); | 1613 FlowGraph::kEffect); |
1595 | 1614 |
1596 if (array_cid == kGrowableObjectArrayCid) { | 1615 if (array_cid == kGrowableObjectArrayCid) { |
1597 // Insert data elements load. | 1616 // Insert data elements load. |
1598 LoadFieldInstr* elements = | 1617 LoadFieldInstr* elements = |
1599 new LoadFieldInstr(new Value(*array), | 1618 new(isolate()) LoadFieldInstr( |
1600 GrowableObjectArray::data_offset(), | 1619 new(isolate()) Value(*array), |
1601 Type::ZoneHandle(Type::DynamicType()), | 1620 GrowableObjectArray::data_offset(), |
1602 call->token_pos()); | 1621 Type::ZoneHandle(isolate(), Type::DynamicType()), |
| 1622 call->token_pos()); |
1603 elements->set_result_cid(kArrayCid); | 1623 elements->set_result_cid(kArrayCid); |
1604 *cursor = flow_graph()->AppendTo(*cursor, | 1624 *cursor = flow_graph()->AppendTo(*cursor, |
1605 elements, | 1625 elements, |
1606 NULL, | 1626 NULL, |
1607 FlowGraph::kValue); | 1627 FlowGraph::kValue); |
1608 // Load from the data from backing store which is a fixed-length array. | 1628 // Load from the data from backing store which is a fixed-length array. |
1609 *array = elements; | 1629 *array = elements; |
1610 array_cid = kArrayCid; | 1630 array_cid = kArrayCid; |
1611 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { | 1631 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
1612 LoadUntaggedInstr* elements = | 1632 LoadUntaggedInstr* elements = |
1613 new LoadUntaggedInstr(new Value(*array), | 1633 new(isolate()) LoadUntaggedInstr(new(isolate()) Value(*array), |
1614 ExternalTypedData::data_offset()); | 1634 ExternalTypedData::data_offset()); |
1615 *cursor = flow_graph()->AppendTo(*cursor, | 1635 *cursor = flow_graph()->AppendTo(*cursor, |
1616 elements, | 1636 elements, |
1617 NULL, | 1637 NULL, |
1618 FlowGraph::kValue); | 1638 FlowGraph::kValue); |
1619 *array = elements; | 1639 *array = elements; |
1620 } | 1640 } |
1621 return array_cid; | 1641 return array_cid; |
1622 } | 1642 } |
1623 | 1643 |
1624 bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind, | 1644 bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind, |
1625 Instruction* call, | 1645 Instruction* call, |
1626 Definition* receiver, | 1646 Definition* receiver, |
1627 const ICData& ic_data, | 1647 const ICData& ic_data, |
1628 TargetEntryInstr** entry, | 1648 TargetEntryInstr** entry, |
1629 Definition** last) { | 1649 Definition** last) { |
1630 intptr_t array_cid = MethodKindToCid(kind); | 1650 intptr_t array_cid = MethodKindToCid(kind); |
1631 ASSERT(array_cid != kIllegalCid); | 1651 ASSERT(array_cid != kIllegalCid); |
1632 | 1652 |
1633 Definition* array = receiver; | 1653 Definition* array = receiver; |
1634 Definition* index = call->ArgumentAt(1); | 1654 Definition* index = call->ArgumentAt(1); |
1635 *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(), | 1655 *entry = new(isolate()) TargetEntryInstr(flow_graph()->allocate_block_id(), |
1636 call->GetBlock()->try_index()); | 1656 call->GetBlock()->try_index()); |
1637 (*entry)->InheritDeoptTarget(call); | 1657 (*entry)->InheritDeoptTarget(isolate(), call); |
1638 Instruction* cursor = *entry; | 1658 Instruction* cursor = *entry; |
1639 | 1659 |
1640 array_cid = PrepareInlineIndexedOp(call, | 1660 array_cid = PrepareInlineIndexedOp(call, |
1641 array_cid, | 1661 array_cid, |
1642 &array, | 1662 &array, |
1643 index, | 1663 index, |
1644 &cursor); | 1664 &cursor); |
1645 | 1665 |
1646 intptr_t deopt_id = Isolate::kNoDeoptId; | 1666 intptr_t deopt_id = Isolate::kNoDeoptId; |
1647 if ((array_cid == kTypedDataInt32ArrayCid) || | 1667 if ((array_cid == kTypedDataInt32ArrayCid) || |
1648 (array_cid == kTypedDataUint32ArrayCid)) { | 1668 (array_cid == kTypedDataUint32ArrayCid)) { |
1649 // Set deopt_id if we can optimistically assume that the result is Smi. | 1669 // Set deopt_id if we can optimistically assume that the result is Smi. |
1650 // Assume mixed Mint/Smi if this instruction caused deoptimization once. | 1670 // Assume mixed Mint/Smi if this instruction caused deoptimization once. |
1651 deopt_id = ic_data.HasDeoptReasons() ? | 1671 deopt_id = ic_data.HasDeoptReasons() ? |
1652 Isolate::kNoDeoptId : call->deopt_id(); | 1672 Isolate::kNoDeoptId : call->deopt_id(); |
1653 } | 1673 } |
1654 | 1674 |
1655 // Array load and return. | 1675 // Array load and return. |
1656 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); | 1676 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); |
1657 *last = new LoadIndexedInstr(new Value(array), | 1677 *last = new(isolate()) LoadIndexedInstr(new(isolate()) Value(array), |
1658 new Value(index), | 1678 new(isolate()) Value(index), |
1659 index_scale, | 1679 index_scale, |
1660 array_cid, | 1680 array_cid, |
1661 deopt_id, | 1681 deopt_id, |
1662 call->token_pos()); | 1682 call->token_pos()); |
1663 cursor = flow_graph()->AppendTo( | 1683 cursor = flow_graph()->AppendTo( |
1664 cursor, | 1684 cursor, |
1665 *last, | 1685 *last, |
1666 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 1686 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
1667 FlowGraph::kValue); | 1687 FlowGraph::kValue); |
1668 | 1688 |
1669 if (array_cid == kTypedDataFloat32ArrayCid) { | 1689 if (array_cid == kTypedDataFloat32ArrayCid) { |
1670 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); | 1690 *last = new(isolate()) FloatToDoubleInstr( |
| 1691 new(isolate()) Value(*last), deopt_id); |
1671 flow_graph()->AppendTo(cursor, | 1692 flow_graph()->AppendTo(cursor, |
1672 *last, | 1693 *last, |
1673 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 1694 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
1674 FlowGraph::kValue); | 1695 FlowGraph::kValue); |
1675 } | 1696 } |
1676 return true; | 1697 return true; |
1677 } | 1698 } |
1678 | 1699 |
1679 | 1700 |
1680 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { | 1701 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { |
1681 // Check for monomorphic IC data. | 1702 // Check for monomorphic IC data. |
1682 if (!call->HasICData()) return false; | 1703 if (!call->HasICData()) return false; |
1683 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); | 1704 const ICData& ic_data = |
| 1705 ICData::Handle(isolate(), call->ic_data()->AsUnaryClassChecks()); |
1684 if (ic_data.NumberOfChecks() != 1) return false; | 1706 if (ic_data.NumberOfChecks() != 1) return false; |
1685 ASSERT(ic_data.HasOneTarget()); | 1707 ASSERT(ic_data.HasOneTarget()); |
1686 | 1708 |
1687 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); | 1709 const Function& target = Function::Handle(isolate(), ic_data.GetTargetAt(0)); |
1688 TargetEntryInstr* entry; | 1710 TargetEntryInstr* entry; |
1689 Definition* last; | 1711 Definition* last; |
1690 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), | 1712 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), |
1691 target, | 1713 target, |
1692 call, | 1714 call, |
1693 call->ArgumentAt(0), | 1715 call->ArgumentAt(0), |
1694 call->token_pos(), | 1716 call->token_pos(), |
1695 *call->ic_data(), | 1717 *call->ic_data(), |
1696 &entry, &last)) { | 1718 &entry, &last)) { |
1697 return false; | 1719 return false; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1756 left = right; | 1778 left = right; |
1757 right = temp; | 1779 right = temp; |
1758 } | 1780 } |
1759 if (IsLengthOneString(left)) { | 1781 if (IsLengthOneString(left)) { |
1760 // Optimize if left is a string with length one (either constant or | 1782 // Optimize if left is a string with length one (either constant or |
1761 // result of string-from-char-code. | 1783 // result of string-from-char-code. |
1762 if (left->IsConstant()) { | 1784 if (left->IsConstant()) { |
1763 ConstantInstr* left_const = left->AsConstant(); | 1785 ConstantInstr* left_const = left->AsConstant(); |
1764 const String& str = String::Cast(left_const->value()); | 1786 const String& str = String::Cast(left_const->value()); |
1765 ASSERT(str.Length() == 1); | 1787 ASSERT(str.Length() == 1); |
1766 ConstantInstr* char_code_left = | 1788 ConstantInstr* char_code_left = flow_graph()->GetConstant( |
1767 flow_graph()->GetConstant(Smi::ZoneHandle(Smi::New(str.CharAt(0)))); | 1789 Smi::ZoneHandle(isolate(), Smi::New(str.CharAt(0)))); |
1768 left_val = new Value(char_code_left); | 1790 left_val = new(isolate()) Value(char_code_left); |
1769 } else if (left->IsStringFromCharCode()) { | 1791 } else if (left->IsStringFromCharCode()) { |
1770 // Use input of string-from-charcode as left value. | 1792 // Use input of string-from-charcode as left value. |
1771 StringFromCharCodeInstr* instr = left->AsStringFromCharCode(); | 1793 StringFromCharCodeInstr* instr = left->AsStringFromCharCode(); |
1772 left_val = new Value(instr->char_code()->definition()); | 1794 left_val = new(isolate()) Value(instr->char_code()->definition()); |
1773 to_remove_left = instr; | 1795 to_remove_left = instr; |
1774 } else { | 1796 } else { |
1775 // IsLengthOneString(left) should have been false. | 1797 // IsLengthOneString(left) should have been false. |
1776 UNREACHABLE(); | 1798 UNREACHABLE(); |
1777 } | 1799 } |
1778 | 1800 |
1779 Definition* to_remove_right = NULL; | 1801 Definition* to_remove_right = NULL; |
1780 Value* right_val = NULL; | 1802 Value* right_val = NULL; |
1781 if (right->IsStringFromCharCode()) { | 1803 if (right->IsStringFromCharCode()) { |
1782 // Skip string-from-char-code, and use its input as right value. | 1804 // Skip string-from-char-code, and use its input as right value. |
1783 StringFromCharCodeInstr* right_instr = right->AsStringFromCharCode(); | 1805 StringFromCharCodeInstr* right_instr = right->AsStringFromCharCode(); |
1784 right_val = new Value(right_instr->char_code()->definition()); | 1806 right_val = new(isolate()) Value(right_instr->char_code()->definition()); |
1785 to_remove_right = right_instr; | 1807 to_remove_right = right_instr; |
1786 } else { | 1808 } else { |
1787 const ICData& unary_checks_1 = | 1809 const ICData& unary_checks_1 = |
1788 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(1)); | 1810 ICData::ZoneHandle(isolate(), |
| 1811 call->ic_data()->AsUnaryClassChecksForArgNr(1)); |
1789 AddCheckClass(right, | 1812 AddCheckClass(right, |
1790 unary_checks_1, | 1813 unary_checks_1, |
1791 call->deopt_id(), | 1814 call->deopt_id(), |
1792 call->env(), | 1815 call->env(), |
1793 call); | 1816 call); |
1794 // String-to-char-code instructions returns -1 (illegal charcode) if | 1817 // String-to-char-code instructions returns -1 (illegal charcode) if |
1795 // string is not of length one. | 1818 // string is not of length one. |
1796 StringToCharCodeInstr* char_code_right = | 1819 StringToCharCodeInstr* char_code_right = |
1797 new StringToCharCodeInstr(new Value(right), kOneByteStringCid); | 1820 new(isolate()) StringToCharCodeInstr( |
| 1821 new(isolate()) Value(right), kOneByteStringCid); |
1798 InsertBefore(call, char_code_right, call->env(), FlowGraph::kValue); | 1822 InsertBefore(call, char_code_right, call->env(), FlowGraph::kValue); |
1799 right_val = new Value(char_code_right); | 1823 right_val = new(isolate()) Value(char_code_right); |
1800 } | 1824 } |
1801 | 1825 |
1802 // Comparing char-codes instead of strings. | 1826 // Comparing char-codes instead of strings. |
1803 EqualityCompareInstr* comp = | 1827 EqualityCompareInstr* comp = |
1804 new EqualityCompareInstr(call->token_pos(), | 1828 new(isolate()) EqualityCompareInstr(call->token_pos(), |
1805 op_kind, | 1829 op_kind, |
1806 left_val, | 1830 left_val, |
1807 right_val, | 1831 right_val, |
1808 kSmiCid, | 1832 kSmiCid, |
1809 call->deopt_id()); | 1833 call->deopt_id()); |
1810 ReplaceCall(call, comp); | 1834 ReplaceCall(call, comp); |
1811 | 1835 |
1812 // Remove dead instructions. | 1836 // Remove dead instructions. |
1813 if ((to_remove_left != NULL) && | 1837 if ((to_remove_left != NULL) && |
1814 (to_remove_left->input_use_list() == NULL)) { | 1838 (to_remove_left->input_use_list() == NULL)) { |
1815 to_remove_left->ReplaceUsesWith(flow_graph()->constant_null()); | 1839 to_remove_left->ReplaceUsesWith(flow_graph()->constant_null()); |
1816 to_remove_left->RemoveFromGraph(); | 1840 to_remove_left->RemoveFromGraph(); |
1817 } | 1841 } |
1818 if ((to_remove_right != NULL) && | 1842 if ((to_remove_right != NULL) && |
1819 (to_remove_right->input_use_list() == NULL)) { | 1843 (to_remove_right->input_use_list() == NULL)) { |
(...skipping 19 matching lines...) Expand all Loading... |
1839 | 1863 |
1840 intptr_t cid = kIllegalCid; | 1864 intptr_t cid = kIllegalCid; |
1841 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { | 1865 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { |
1842 if (TryStringLengthOneEquality(call, op_kind)) { | 1866 if (TryStringLengthOneEquality(call, op_kind)) { |
1843 return true; | 1867 return true; |
1844 } else { | 1868 } else { |
1845 return false; | 1869 return false; |
1846 } | 1870 } |
1847 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1871 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
1848 InsertBefore(call, | 1872 InsertBefore(call, |
1849 new CheckSmiInstr(new Value(left), | 1873 new(isolate()) CheckSmiInstr(new(isolate()) Value(left), |
1850 call->deopt_id(), | 1874 call->deopt_id(), |
1851 call->token_pos()), | 1875 call->token_pos()), |
1852 call->env(), | 1876 call->env(), |
1853 FlowGraph::kEffect); | 1877 FlowGraph::kEffect); |
1854 InsertBefore(call, | 1878 InsertBefore(call, |
1855 new CheckSmiInstr(new Value(right), | 1879 new(isolate()) CheckSmiInstr(new(isolate()) Value(right), |
1856 call->deopt_id(), | 1880 call->deopt_id(), |
1857 call->token_pos()), | 1881 call->token_pos()), |
1858 call->env(), | 1882 call->env(), |
1859 FlowGraph::kEffect); | 1883 FlowGraph::kEffect); |
1860 cid = kSmiCid; | 1884 cid = kSmiCid; |
1861 } else if (HasTwoMintOrSmi(ic_data) && | 1885 } else if (HasTwoMintOrSmi(ic_data) && |
1862 FlowGraphCompiler::SupportsUnboxedMints()) { | 1886 FlowGraphCompiler::SupportsUnboxedMints()) { |
1863 cid = kMintCid; | 1887 cid = kMintCid; |
1864 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) { | 1888 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) { |
1865 // Use double comparison. | 1889 // Use double comparison. |
1866 if (SmiFitsInDouble()) { | 1890 if (SmiFitsInDouble()) { |
1867 cid = kDoubleCid; | 1891 cid = kDoubleCid; |
1868 } else { | 1892 } else { |
1869 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { | 1893 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { |
1870 // We cannot use double comparison on two smis. Need polymorphic | 1894 // We cannot use double comparison on two smis. Need polymorphic |
1871 // call. | 1895 // call. |
1872 return false; | 1896 return false; |
1873 } else { | 1897 } else { |
1874 InsertBefore(call, | 1898 InsertBefore(call, |
1875 new CheckEitherNonSmiInstr(new Value(left), | 1899 new(isolate()) CheckEitherNonSmiInstr( |
1876 new Value(right), | 1900 new(isolate()) Value(left), |
1877 call->deopt_id()), | 1901 new(isolate()) Value(right), |
| 1902 call->deopt_id()), |
1878 call->env(), | 1903 call->env(), |
1879 FlowGraph::kEffect); | 1904 FlowGraph::kEffect); |
1880 cid = kDoubleCid; | 1905 cid = kDoubleCid; |
1881 } | 1906 } |
1882 } | 1907 } |
1883 } else { | 1908 } else { |
1884 // Check if ICDData contains checks with Smi/Null combinations. In that case | 1909 // Check if ICDData contains checks with Smi/Null combinations. In that case |
1885 // we can still emit the optimized Smi equality operation but need to add | 1910 // we can still emit the optimized Smi equality operation but need to add |
1886 // checks for null or Smi. | 1911 // checks for null or Smi. |
1887 GrowableArray<intptr_t> smi_or_null(2); | 1912 GrowableArray<intptr_t> smi_or_null(2); |
1888 smi_or_null.Add(kSmiCid); | 1913 smi_or_null.Add(kSmiCid); |
1889 smi_or_null.Add(kNullCid); | 1914 smi_or_null.Add(kNullCid); |
1890 if (ICDataHasOnlyReceiverArgumentClassIds(ic_data, | 1915 if (ICDataHasOnlyReceiverArgumentClassIds(ic_data, |
1891 smi_or_null, | 1916 smi_or_null, |
1892 smi_or_null)) { | 1917 smi_or_null)) { |
1893 const ICData& unary_checks_0 = | 1918 const ICData& unary_checks_0 = |
1894 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); | 1919 ICData::ZoneHandle(isolate(), |
| 1920 call->ic_data()->AsUnaryClassChecks()); |
1895 AddCheckClass(left, | 1921 AddCheckClass(left, |
1896 unary_checks_0, | 1922 unary_checks_0, |
1897 call->deopt_id(), | 1923 call->deopt_id(), |
1898 call->env(), | 1924 call->env(), |
1899 call); | 1925 call); |
1900 | 1926 |
1901 const ICData& unary_checks_1 = | 1927 const ICData& unary_checks_1 = |
1902 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(1)); | 1928 ICData::ZoneHandle(isolate(), |
| 1929 call->ic_data()->AsUnaryClassChecksForArgNr(1)); |
1903 AddCheckClass(right, | 1930 AddCheckClass(right, |
1904 unary_checks_1, | 1931 unary_checks_1, |
1905 call->deopt_id(), | 1932 call->deopt_id(), |
1906 call->env(), | 1933 call->env(), |
1907 call); | 1934 call); |
1908 cid = kSmiCid; | 1935 cid = kSmiCid; |
1909 } else { | 1936 } else { |
1910 // Shortcut for equality with null. | 1937 // Shortcut for equality with null. |
1911 ConstantInstr* right_const = right->AsConstant(); | 1938 ConstantInstr* right_const = right->AsConstant(); |
1912 ConstantInstr* left_const = left->AsConstant(); | 1939 ConstantInstr* left_const = left->AsConstant(); |
1913 if ((right_const != NULL && right_const->value().IsNull()) || | 1940 if ((right_const != NULL && right_const->value().IsNull()) || |
1914 (left_const != NULL && left_const->value().IsNull())) { | 1941 (left_const != NULL && left_const->value().IsNull())) { |
1915 StrictCompareInstr* comp = | 1942 StrictCompareInstr* comp = |
1916 new StrictCompareInstr(call->token_pos(), | 1943 new(isolate()) StrictCompareInstr(call->token_pos(), |
1917 Token::kEQ_STRICT, | 1944 Token::kEQ_STRICT, |
1918 new Value(left), | 1945 new(isolate()) Value(left), |
1919 new Value(right), | 1946 new(isolate()) Value(right), |
1920 false); // No number check. | 1947 false); // No number check. |
1921 ReplaceCall(call, comp); | 1948 ReplaceCall(call, comp); |
1922 return true; | 1949 return true; |
1923 } | 1950 } |
1924 return false; | 1951 return false; |
1925 } | 1952 } |
1926 } | 1953 } |
1927 ASSERT(cid != kIllegalCid); | 1954 ASSERT(cid != kIllegalCid); |
1928 EqualityCompareInstr* comp = new EqualityCompareInstr(call->token_pos(), | 1955 EqualityCompareInstr* comp = new(isolate()) EqualityCompareInstr( |
1929 op_kind, | 1956 call->token_pos(), |
1930 new Value(left), | 1957 op_kind, |
1931 new Value(right), | 1958 new(isolate()) Value(left), |
1932 cid, | 1959 new(isolate()) Value(right), |
1933 call->deopt_id()); | 1960 cid, |
| 1961 call->deopt_id()); |
1934 ReplaceCall(call, comp); | 1962 ReplaceCall(call, comp); |
1935 return true; | 1963 return true; |
1936 } | 1964 } |
1937 | 1965 |
1938 | 1966 |
1939 bool FlowGraphOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call, | 1967 bool FlowGraphOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call, |
1940 Token::Kind op_kind) { | 1968 Token::Kind op_kind) { |
1941 const ICData& ic_data = *call->ic_data(); | 1969 const ICData& ic_data = *call->ic_data(); |
1942 ASSERT(ic_data.NumArgsTested() == 2); | 1970 ASSERT(ic_data.NumArgsTested() == 2); |
1943 | 1971 |
1944 ASSERT(call->ArgumentCount() == 2); | 1972 ASSERT(call->ArgumentCount() == 2); |
1945 Definition* left = call->ArgumentAt(0); | 1973 Definition* left = call->ArgumentAt(0); |
1946 Definition* right = call->ArgumentAt(1); | 1974 Definition* right = call->ArgumentAt(1); |
1947 | 1975 |
1948 intptr_t cid = kIllegalCid; | 1976 intptr_t cid = kIllegalCid; |
1949 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1977 if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
1950 InsertBefore(call, | 1978 InsertBefore(call, |
1951 new CheckSmiInstr(new Value(left), | 1979 new(isolate()) CheckSmiInstr(new(isolate()) Value(left), |
1952 call->deopt_id(), | 1980 call->deopt_id(), |
1953 call->token_pos()), | 1981 call->token_pos()), |
1954 call->env(), | 1982 call->env(), |
1955 FlowGraph::kEffect); | 1983 FlowGraph::kEffect); |
1956 InsertBefore(call, | 1984 InsertBefore(call, |
1957 new CheckSmiInstr(new Value(right), | 1985 new(isolate()) CheckSmiInstr(new(isolate()) Value(right), |
1958 call->deopt_id(), | 1986 call->deopt_id(), |
1959 call->token_pos()), | 1987 call->token_pos()), |
1960 call->env(), | 1988 call->env(), |
1961 FlowGraph::kEffect); | 1989 FlowGraph::kEffect); |
1962 cid = kSmiCid; | 1990 cid = kSmiCid; |
1963 } else if (HasTwoMintOrSmi(ic_data) && | 1991 } else if (HasTwoMintOrSmi(ic_data) && |
1964 FlowGraphCompiler::SupportsUnboxedMints()) { | 1992 FlowGraphCompiler::SupportsUnboxedMints()) { |
1965 cid = kMintCid; | 1993 cid = kMintCid; |
1966 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) { | 1994 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) { |
1967 // Use double comparison. | 1995 // Use double comparison. |
1968 if (SmiFitsInDouble()) { | 1996 if (SmiFitsInDouble()) { |
1969 cid = kDoubleCid; | 1997 cid = kDoubleCid; |
1970 } else { | 1998 } else { |
1971 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { | 1999 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { |
1972 // We cannot use double comparison on two smis. Need polymorphic | 2000 // We cannot use double comparison on two smis. Need polymorphic |
1973 // call. | 2001 // call. |
1974 return false; | 2002 return false; |
1975 } else { | 2003 } else { |
1976 InsertBefore(call, | 2004 InsertBefore(call, |
1977 new CheckEitherNonSmiInstr(new Value(left), | 2005 new(isolate()) CheckEitherNonSmiInstr( |
1978 new Value(right), | 2006 new(isolate()) Value(left), |
1979 call->deopt_id()), | 2007 new(isolate()) Value(right), |
| 2008 call->deopt_id()), |
1980 call->env(), | 2009 call->env(), |
1981 FlowGraph::kEffect); | 2010 FlowGraph::kEffect); |
1982 cid = kDoubleCid; | 2011 cid = kDoubleCid; |
1983 } | 2012 } |
1984 } | 2013 } |
1985 } else { | 2014 } else { |
1986 return false; | 2015 return false; |
1987 } | 2016 } |
1988 ASSERT(cid != kIllegalCid); | 2017 ASSERT(cid != kIllegalCid); |
1989 RelationalOpInstr* comp = new RelationalOpInstr(call->token_pos(), | 2018 RelationalOpInstr* comp = new(isolate()) RelationalOpInstr( |
1990 op_kind, | 2019 call->token_pos(), |
1991 new Value(left), | 2020 op_kind, |
1992 new Value(right), | 2021 new(isolate()) Value(left), |
1993 cid, | 2022 new(isolate()) Value(right), |
1994 call->deopt_id()); | 2023 cid, |
| 2024 call->deopt_id()); |
1995 ReplaceCall(call, comp); | 2025 ReplaceCall(call, comp); |
1996 return true; | 2026 return true; |
1997 } | 2027 } |
1998 | 2028 |
1999 | 2029 |
2000 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, | 2030 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, |
2001 Token::Kind op_kind) { | 2031 Token::Kind op_kind) { |
2002 intptr_t operands_type = kIllegalCid; | 2032 intptr_t operands_type = kIllegalCid; |
2003 ASSERT(call->HasICData()); | 2033 ASSERT(call->HasICData()); |
2004 const ICData& ic_data = *call->ic_data(); | 2034 const ICData& ic_data = *call->ic_data(); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2077 // Left shift may overflow from smi into mint or big ints. | 2107 // Left shift may overflow from smi into mint or big ints. |
2078 // Don't generate smi code if the IC data is marked because | 2108 // Don't generate smi code if the IC data is marked because |
2079 // of an overflow. | 2109 // of an overflow. |
2080 if (ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { | 2110 if (ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { |
2081 return false; | 2111 return false; |
2082 } | 2112 } |
2083 operands_type = ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp) | 2113 operands_type = ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp) |
2084 ? kMintCid | 2114 ? kMintCid |
2085 : kSmiCid; | 2115 : kSmiCid; |
2086 } else if (HasTwoMintOrSmi(ic_data) && | 2116 } else if (HasTwoMintOrSmi(ic_data) && |
2087 HasOnlyOneSmi(ICData::Handle( | 2117 HasOnlyOneSmi(ICData::Handle(isolate(), |
2088 ic_data.AsUnaryClassChecksForArgNr(1)))) { | 2118 ic_data.AsUnaryClassChecksForArgNr(1)))) { |
2089 // Don't generate mint code if the IC data is marked because of an | 2119 // Don't generate mint code if the IC data is marked because of an |
2090 // overflow. | 2120 // overflow. |
2091 if (ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { | 2121 if (ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { |
2092 return false; | 2122 return false; |
2093 } | 2123 } |
2094 // Check for smi/mint << smi or smi/mint >> smi. | 2124 // Check for smi/mint << smi or smi/mint >> smi. |
2095 operands_type = kMintCid; | 2125 operands_type = kMintCid; |
2096 } else { | 2126 } else { |
2097 return false; | 2127 return false; |
(...skipping 19 matching lines...) Expand all Loading... |
2117 Definition* right = call->ArgumentAt(1); | 2147 Definition* right = call->ArgumentAt(1); |
2118 if (operands_type == kDoubleCid) { | 2148 if (operands_type == kDoubleCid) { |
2119 if (!CanUnboxDouble()) { | 2149 if (!CanUnboxDouble()) { |
2120 return false; | 2150 return false; |
2121 } | 2151 } |
2122 // Check that either left or right are not a smi. Result of a | 2152 // Check that either left or right are not a smi. Result of a |
2123 // binary operation with two smis is a smi not a double, except '/' which | 2153 // binary operation with two smis is a smi not a double, except '/' which |
2124 // returns a double for two smis. | 2154 // returns a double for two smis. |
2125 if (op_kind != Token::kDIV) { | 2155 if (op_kind != Token::kDIV) { |
2126 InsertBefore(call, | 2156 InsertBefore(call, |
2127 new CheckEitherNonSmiInstr(new Value(left), | 2157 new(isolate()) CheckEitherNonSmiInstr( |
2128 new Value(right), | 2158 new(isolate()) Value(left), |
2129 call->deopt_id()), | 2159 new(isolate()) Value(right), |
| 2160 call->deopt_id()), |
2130 call->env(), | 2161 call->env(), |
2131 FlowGraph::kEffect); | 2162 FlowGraph::kEffect); |
2132 } | 2163 } |
2133 | 2164 |
2134 BinaryDoubleOpInstr* double_bin_op = | 2165 BinaryDoubleOpInstr* double_bin_op = |
2135 new BinaryDoubleOpInstr(op_kind, new Value(left), new Value(right), | 2166 new(isolate()) BinaryDoubleOpInstr(op_kind, |
2136 call->deopt_id(), call->token_pos()); | 2167 new(isolate()) Value(left), |
| 2168 new(isolate()) Value(right), |
| 2169 call->deopt_id(), call->token_pos()); |
2137 ReplaceCall(call, double_bin_op); | 2170 ReplaceCall(call, double_bin_op); |
2138 } else if (operands_type == kMintCid) { | 2171 } else if (operands_type == kMintCid) { |
2139 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; | 2172 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; |
2140 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { | 2173 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { |
2141 ShiftMintOpInstr* shift_op = | 2174 ShiftMintOpInstr* shift_op = |
2142 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right), | 2175 new(isolate()) ShiftMintOpInstr( |
2143 call->deopt_id()); | 2176 op_kind, new(isolate()) Value(left), new(isolate()) Value(right), |
| 2177 call->deopt_id()); |
2144 ReplaceCall(call, shift_op); | 2178 ReplaceCall(call, shift_op); |
2145 } else { | 2179 } else { |
2146 BinaryMintOpInstr* bin_op = | 2180 BinaryMintOpInstr* bin_op = |
2147 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), | 2181 new(isolate()) BinaryMintOpInstr( |
2148 call->deopt_id()); | 2182 op_kind, new(isolate()) Value(left), new(isolate()) Value(right), |
| 2183 call->deopt_id()); |
2149 ReplaceCall(call, bin_op); | 2184 ReplaceCall(call, bin_op); |
2150 } | 2185 } |
2151 } else if (operands_type == kFloat32x4Cid) { | 2186 } else if (operands_type == kFloat32x4Cid) { |
2152 return InlineFloat32x4BinaryOp(call, op_kind); | 2187 return InlineFloat32x4BinaryOp(call, op_kind); |
2153 } else if (operands_type == kInt32x4Cid) { | 2188 } else if (operands_type == kInt32x4Cid) { |
2154 return InlineInt32x4BinaryOp(call, op_kind); | 2189 return InlineInt32x4BinaryOp(call, op_kind); |
2155 } else if (operands_type == kFloat64x2Cid) { | 2190 } else if (operands_type == kFloat64x2Cid) { |
2156 return InlineFloat64x2BinaryOp(call, op_kind); | 2191 return InlineFloat64x2BinaryOp(call, op_kind); |
2157 } else if (op_kind == Token::kMOD) { | 2192 } else if (op_kind == Token::kMOD) { |
2158 ASSERT(operands_type == kSmiCid); | 2193 ASSERT(operands_type == kSmiCid); |
2159 if (right->IsConstant()) { | 2194 if (right->IsConstant()) { |
2160 const Object& obj = right->AsConstant()->value(); | 2195 const Object& obj = right->AsConstant()->value(); |
2161 if (obj.IsSmi() && Utils::IsPowerOfTwo(Smi::Cast(obj).Value())) { | 2196 if (obj.IsSmi() && Utils::IsPowerOfTwo(Smi::Cast(obj).Value())) { |
2162 // Insert smi check and attach a copy of the original environment | 2197 // Insert smi check and attach a copy of the original environment |
2163 // because the smi operation can still deoptimize. | 2198 // because the smi operation can still deoptimize. |
2164 InsertBefore(call, | 2199 InsertBefore(call, |
2165 new CheckSmiInstr(new Value(left), | 2200 new(isolate()) CheckSmiInstr(new(isolate()) Value(left), |
2166 call->deopt_id(), | 2201 call->deopt_id(), |
2167 call->token_pos()), | 2202 call->token_pos()), |
2168 call->env(), | 2203 call->env(), |
2169 FlowGraph::kEffect); | 2204 FlowGraph::kEffect); |
2170 ConstantInstr* constant = | 2205 ConstantInstr* constant = |
2171 flow_graph()->GetConstant(Smi::Handle( | 2206 flow_graph()->GetConstant(Smi::Handle(isolate(), |
2172 Smi::New(Smi::Cast(obj).Value() - 1))); | 2207 Smi::New(Smi::Cast(obj).Value() - 1))); |
2173 BinarySmiOpInstr* bin_op = | 2208 BinarySmiOpInstr* bin_op = |
2174 new BinarySmiOpInstr(Token::kBIT_AND, | 2209 new(isolate()) BinarySmiOpInstr(Token::kBIT_AND, |
2175 new Value(left), | 2210 new(isolate()) Value(left), |
2176 new Value(constant), | 2211 new(isolate()) Value(constant), |
2177 call->deopt_id(), | 2212 call->deopt_id(), |
2178 call->token_pos()); | 2213 call->token_pos()); |
2179 ReplaceCall(call, bin_op); | 2214 ReplaceCall(call, bin_op); |
2180 return true; | 2215 return true; |
2181 } | 2216 } |
2182 } | 2217 } |
2183 // Insert two smi checks and attach a copy of the original | 2218 // Insert two smi checks and attach a copy of the original |
2184 // environment because the smi operation can still deoptimize. | 2219 // environment because the smi operation can still deoptimize. |
2185 AddCheckSmi(left, call->deopt_id(), call->env(), call); | 2220 AddCheckSmi(left, call->deopt_id(), call->env(), call); |
2186 AddCheckSmi(right, call->deopt_id(), call->env(), call); | 2221 AddCheckSmi(right, call->deopt_id(), call->env(), call); |
2187 BinarySmiOpInstr* bin_op = | 2222 BinarySmiOpInstr* bin_op = |
2188 new BinarySmiOpInstr(op_kind, new Value(left), new Value(right), | 2223 new(isolate()) BinarySmiOpInstr(op_kind, |
2189 call->deopt_id(), call->token_pos()); | 2224 new(isolate()) Value(left), |
| 2225 new(isolate()) Value(right), |
| 2226 call->deopt_id(), call->token_pos()); |
2190 ReplaceCall(call, bin_op); | 2227 ReplaceCall(call, bin_op); |
2191 } else { | 2228 } else { |
2192 ASSERT(operands_type == kSmiCid); | 2229 ASSERT(operands_type == kSmiCid); |
2193 // Insert two smi checks and attach a copy of the original | 2230 // Insert two smi checks and attach a copy of the original |
2194 // environment because the smi operation can still deoptimize. | 2231 // environment because the smi operation can still deoptimize. |
2195 AddCheckSmi(left, call->deopt_id(), call->env(), call); | 2232 AddCheckSmi(left, call->deopt_id(), call->env(), call); |
2196 AddCheckSmi(right, call->deopt_id(), call->env(), call); | 2233 AddCheckSmi(right, call->deopt_id(), call->env(), call); |
2197 if (left->IsConstant() && | 2234 if (left->IsConstant() && |
2198 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { | 2235 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { |
2199 // Constant should be on the right side. | 2236 // Constant should be on the right side. |
2200 Definition* temp = left; | 2237 Definition* temp = left; |
2201 left = right; | 2238 left = right; |
2202 right = temp; | 2239 right = temp; |
2203 } | 2240 } |
2204 BinarySmiOpInstr* bin_op = | 2241 BinarySmiOpInstr* bin_op = |
2205 new BinarySmiOpInstr(op_kind, new Value(left), new Value(right), | 2242 new(isolate()) BinarySmiOpInstr( |
2206 call->deopt_id(), call->token_pos()); | 2243 op_kind, new(isolate()) Value(left), new(isolate()) Value(right), |
| 2244 call->deopt_id(), call->token_pos()); |
2207 ReplaceCall(call, bin_op); | 2245 ReplaceCall(call, bin_op); |
2208 } | 2246 } |
2209 return true; | 2247 return true; |
2210 } | 2248 } |
2211 | 2249 |
2212 | 2250 |
2213 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, | 2251 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, |
2214 Token::Kind op_kind) { | 2252 Token::Kind op_kind) { |
2215 ASSERT(call->ArgumentCount() == 1); | 2253 ASSERT(call->ArgumentCount() == 1); |
2216 Definition* input = call->ArgumentAt(0); | 2254 Definition* input = call->ArgumentAt(0); |
2217 Definition* unary_op = NULL; | 2255 Definition* unary_op = NULL; |
2218 if (HasOnlyOneSmi(*call->ic_data())) { | 2256 if (HasOnlyOneSmi(*call->ic_data())) { |
2219 InsertBefore(call, | 2257 InsertBefore(call, |
2220 new CheckSmiInstr(new Value(input), | 2258 new(isolate()) CheckSmiInstr(new(isolate()) Value(input), |
2221 call->deopt_id(), | 2259 call->deopt_id(), |
2222 call->token_pos()), | 2260 call->token_pos()), |
2223 call->env(), | 2261 call->env(), |
2224 FlowGraph::kEffect); | 2262 FlowGraph::kEffect); |
2225 unary_op = new UnarySmiOpInstr(op_kind, new Value(input), call->deopt_id()); | 2263 unary_op = new(isolate()) UnarySmiOpInstr( |
| 2264 op_kind, new(isolate()) Value(input), call->deopt_id()); |
2226 } else if ((op_kind == Token::kBIT_NOT) && | 2265 } else if ((op_kind == Token::kBIT_NOT) && |
2227 HasOnlySmiOrMint(*call->ic_data()) && | 2266 HasOnlySmiOrMint(*call->ic_data()) && |
2228 FlowGraphCompiler::SupportsUnboxedMints()) { | 2267 FlowGraphCompiler::SupportsUnboxedMints()) { |
2229 unary_op = new UnaryMintOpInstr( | 2268 unary_op = new(isolate()) UnaryMintOpInstr( |
2230 op_kind, new Value(input), call->deopt_id()); | 2269 op_kind, new(isolate()) Value(input), call->deopt_id()); |
2231 } else if (HasOnlyOneDouble(*call->ic_data()) && | 2270 } else if (HasOnlyOneDouble(*call->ic_data()) && |
2232 (op_kind == Token::kNEGATE) && | 2271 (op_kind == Token::kNEGATE) && |
2233 CanUnboxDouble()) { | 2272 CanUnboxDouble()) { |
2234 AddReceiverCheck(call); | 2273 AddReceiverCheck(call); |
2235 unary_op = new UnaryDoubleOpInstr( | 2274 unary_op = new(isolate()) UnaryDoubleOpInstr( |
2236 Token::kNEGATE, new Value(input), call->deopt_id()); | 2275 Token::kNEGATE, new(isolate()) Value(input), call->deopt_id()); |
2237 } else { | 2276 } else { |
2238 return false; | 2277 return false; |
2239 } | 2278 } |
2240 ASSERT(unary_op != NULL); | 2279 ASSERT(unary_op != NULL); |
2241 ReplaceCall(call, unary_op); | 2280 ReplaceCall(call, unary_op); |
2242 return true; | 2281 return true; |
2243 } | 2282 } |
2244 | 2283 |
2245 | 2284 |
2246 // Using field class | 2285 // Using field class |
(...skipping 16 matching lines...) Expand all Loading... |
2263 // callee functions, then no class check is needed. | 2302 // callee functions, then no class check is needed. |
2264 bool FlowGraphOptimizer::InstanceCallNeedsClassCheck( | 2303 bool FlowGraphOptimizer::InstanceCallNeedsClassCheck( |
2265 InstanceCallInstr* call) const { | 2304 InstanceCallInstr* call) const { |
2266 if (!FLAG_use_cha) return true; | 2305 if (!FLAG_use_cha) return true; |
2267 Definition* callee_receiver = call->ArgumentAt(0); | 2306 Definition* callee_receiver = call->ArgumentAt(0); |
2268 ASSERT(callee_receiver != NULL); | 2307 ASSERT(callee_receiver != NULL); |
2269 const Function& function = flow_graph_->parsed_function().function(); | 2308 const Function& function = flow_graph_->parsed_function().function(); |
2270 if (function.IsDynamicFunction() && | 2309 if (function.IsDynamicFunction() && |
2271 callee_receiver->IsParameter() && | 2310 callee_receiver->IsParameter() && |
2272 (callee_receiver->AsParameter()->index() == 0)) { | 2311 (callee_receiver->AsParameter()->index() == 0)) { |
2273 return CHA::HasOverride(Class::Handle(function.Owner()), | 2312 return CHA::HasOverride(Class::Handle(isolate(), function.Owner()), |
2274 call->function_name()); | 2313 call->function_name()); |
2275 } | 2314 } |
2276 return true; | 2315 return true; |
2277 } | 2316 } |
2278 | 2317 |
2279 | 2318 |
2280 bool FlowGraphOptimizer::MethodExtractorNeedsClassCheck( | 2319 bool FlowGraphOptimizer::MethodExtractorNeedsClassCheck( |
2281 InstanceCallInstr* call) const { | 2320 InstanceCallInstr* call) const { |
2282 if (!FLAG_use_cha) return true; | 2321 if (!FLAG_use_cha) return true; |
2283 Definition* callee_receiver = call->ArgumentAt(0); | 2322 Definition* callee_receiver = call->ArgumentAt(0); |
2284 ASSERT(callee_receiver != NULL); | 2323 ASSERT(callee_receiver != NULL); |
2285 const Function& function = flow_graph_->parsed_function().function(); | 2324 const Function& function = flow_graph_->parsed_function().function(); |
2286 if (function.IsDynamicFunction() && | 2325 if (function.IsDynamicFunction() && |
2287 callee_receiver->IsParameter() && | 2326 callee_receiver->IsParameter() && |
2288 (callee_receiver->AsParameter()->index() == 0)) { | 2327 (callee_receiver->AsParameter()->index() == 0)) { |
2289 const String& field_name = | 2328 const String& field_name = |
2290 String::Handle(Field::NameFromGetter(call->function_name())); | 2329 String::Handle(isolate(), Field::NameFromGetter(call->function_name())); |
2291 return CHA::HasOverride(Class::Handle(function.Owner()), field_name); | 2330 return CHA::HasOverride(Class::Handle(isolate(), function.Owner()), |
| 2331 field_name); |
2292 } | 2332 } |
2293 return true; | 2333 return true; |
2294 } | 2334 } |
2295 | 2335 |
2296 | 2336 |
2297 void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { | 2337 void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { |
2298 ASSERT(call->HasICData()); | 2338 ASSERT(call->HasICData()); |
2299 const ICData& ic_data = *call->ic_data(); | 2339 const ICData& ic_data = *call->ic_data(); |
2300 ASSERT(ic_data.HasOneTarget()); | 2340 ASSERT(ic_data.HasOneTarget()); |
2301 Function& target = Function::Handle(); | 2341 Function& target = Function::Handle(isolate(), Function::null()); |
2302 GrowableArray<intptr_t> class_ids; | 2342 GrowableArray<intptr_t> class_ids; |
2303 ic_data.GetCheckAt(0, &class_ids, &target); | 2343 ic_data.GetCheckAt(0, &class_ids, &target); |
2304 ASSERT(class_ids.length() == 1); | 2344 ASSERT(class_ids.length() == 1); |
2305 // Inline implicit instance getter. | 2345 // Inline implicit instance getter. |
2306 const String& field_name = | 2346 const String& field_name = |
2307 String::Handle(Field::NameFromGetter(call->function_name())); | 2347 String::Handle(isolate(), Field::NameFromGetter(call->function_name())); |
2308 const Field& field = Field::ZoneHandle(GetField(class_ids[0], field_name)); | 2348 const Field& field = |
| 2349 Field::ZoneHandle(isolate(), GetField(class_ids[0], field_name)); |
2309 ASSERT(!field.IsNull()); | 2350 ASSERT(!field.IsNull()); |
2310 | 2351 |
2311 if (InstanceCallNeedsClassCheck(call)) { | 2352 if (InstanceCallNeedsClassCheck(call)) { |
2312 AddReceiverCheck(call); | 2353 AddReceiverCheck(call); |
2313 } | 2354 } |
2314 LoadFieldInstr* load = new LoadFieldInstr( | 2355 LoadFieldInstr* load = new(isolate()) LoadFieldInstr( |
2315 new Value(call->ArgumentAt(0)), | 2356 new(isolate()) Value(call->ArgumentAt(0)), |
2316 &field, | 2357 &field, |
2317 AbstractType::ZoneHandle(field.type()), | 2358 AbstractType::ZoneHandle(isolate(), field.type()), |
2318 call->token_pos()); | 2359 call->token_pos()); |
2319 load->set_is_immutable(field.is_final()); | 2360 load->set_is_immutable(field.is_final()); |
2320 if (field.guarded_cid() != kIllegalCid) { | 2361 if (field.guarded_cid() != kIllegalCid) { |
2321 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { | 2362 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { |
2322 load->set_result_cid(field.guarded_cid()); | 2363 load->set_result_cid(field.guarded_cid()); |
2323 } | 2364 } |
2324 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | 2365 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
2325 } | 2366 } |
2326 | 2367 |
2327 // Discard the environment from the original instruction because the load | 2368 // Discard the environment from the original instruction because the load |
2328 // can't deoptimize. | 2369 // can't deoptimize. |
2329 call->RemoveEnvironment(); | 2370 call->RemoveEnvironment(); |
2330 ReplaceCall(call, load); | 2371 ReplaceCall(call, load); |
2331 | 2372 |
2332 if (load->result_cid() != kDynamicCid) { | 2373 if (load->result_cid() != kDynamicCid) { |
2333 // Reset value types if guarded_cid was used. | 2374 // Reset value types if guarded_cid was used. |
2334 for (Value::Iterator it(load->input_use_list()); | 2375 for (Value::Iterator it(load->input_use_list()); |
2335 !it.Done(); | 2376 !it.Done(); |
2336 it.Advance()) { | 2377 it.Advance()) { |
2337 it.Current()->SetReachingType(NULL); | 2378 it.Current()->SetReachingType(NULL); |
2338 } | 2379 } |
2339 } | 2380 } |
2340 } | 2381 } |
2341 | 2382 |
2342 | 2383 |
2343 static LoadFieldInstr* BuildLoadStringLength(Definition* str) { | 2384 LoadFieldInstr* FlowGraphOptimizer::BuildLoadStringLength(Definition* str) { |
2344 // Treat length loads as mutable (i.e. affected by side effects) to avoid | 2385 // Treat length loads as mutable (i.e. affected by side effects) to avoid |
2345 // hoisting them since we can't hoist the preceding class-check. This | 2386 // hoisting them since we can't hoist the preceding class-check. This |
2346 // is because of externalization of strings that affects their class-id. | 2387 // is because of externalization of strings that affects their class-id. |
2347 LoadFieldInstr* load = new LoadFieldInstr( | 2388 LoadFieldInstr* load = new(isolate()) LoadFieldInstr( |
2348 new Value(str), | 2389 new(isolate()) Value(str), |
2349 String::length_offset(), | 2390 String::length_offset(), |
2350 Type::ZoneHandle(Type::SmiType()), | 2391 Type::ZoneHandle(isolate(), Type::SmiType()), |
2351 str->token_pos()); | 2392 str->token_pos()); |
2352 load->set_result_cid(kSmiCid); | 2393 load->set_result_cid(kSmiCid); |
2353 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); | 2394 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); |
2354 return load; | 2395 return load; |
2355 } | 2396 } |
2356 | 2397 |
2357 | 2398 |
2358 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, | 2399 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, |
2359 MethodRecognizer::Kind getter) { | 2400 MethodRecognizer::Kind getter) { |
2360 if (!ShouldInlineSimd()) { | 2401 if (!ShouldInlineSimd()) { |
2361 return false; | 2402 return false; |
2362 } | 2403 } |
2363 AddCheckClass(call->ArgumentAt(0), | 2404 AddCheckClass(call->ArgumentAt(0), |
2364 ICData::ZoneHandle( | 2405 ICData::ZoneHandle( |
2365 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 2406 isolate(), call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
2366 call->deopt_id(), | 2407 call->deopt_id(), |
2367 call->env(), | 2408 call->env(), |
2368 call); | 2409 call); |
2369 intptr_t mask = 0; | 2410 intptr_t mask = 0; |
2370 if ((getter == MethodRecognizer::kFloat32x4Shuffle) || | 2411 if ((getter == MethodRecognizer::kFloat32x4Shuffle) || |
2371 (getter == MethodRecognizer::kFloat32x4ShuffleMix)) { | 2412 (getter == MethodRecognizer::kFloat32x4ShuffleMix)) { |
2372 // Extract shuffle mask. | 2413 // Extract shuffle mask. |
2373 Definition* mask_definition = NULL; | 2414 Definition* mask_definition = NULL; |
2374 if (getter == MethodRecognizer::kFloat32x4Shuffle) { | 2415 if (getter == MethodRecognizer::kFloat32x4Shuffle) { |
2375 ASSERT(call->ArgumentCount() == 2); | 2416 ASSERT(call->ArgumentCount() == 2); |
(...skipping 13 matching lines...) Expand all Loading... |
2389 return false; | 2430 return false; |
2390 } | 2431 } |
2391 ASSERT(constant_mask.IsSmi()); | 2432 ASSERT(constant_mask.IsSmi()); |
2392 mask = Smi::Cast(constant_mask).Value(); | 2433 mask = Smi::Cast(constant_mask).Value(); |
2393 if ((mask < 0) || (mask > 255)) { | 2434 if ((mask < 0) || (mask > 255)) { |
2394 // Not a valid mask. | 2435 // Not a valid mask. |
2395 return false; | 2436 return false; |
2396 } | 2437 } |
2397 } | 2438 } |
2398 if (getter == MethodRecognizer::kFloat32x4GetSignMask) { | 2439 if (getter == MethodRecognizer::kFloat32x4GetSignMask) { |
2399 Simd32x4GetSignMaskInstr* instr = new Simd32x4GetSignMaskInstr( | 2440 Simd32x4GetSignMaskInstr* instr = new(isolate()) Simd32x4GetSignMaskInstr( |
2400 getter, | 2441 getter, |
2401 new Value(call->ArgumentAt(0)), | 2442 new(isolate()) Value(call->ArgumentAt(0)), |
2402 call->deopt_id()); | 2443 call->deopt_id()); |
2403 ReplaceCall(call, instr); | 2444 ReplaceCall(call, instr); |
2404 return true; | 2445 return true; |
2405 } else if (getter == MethodRecognizer::kFloat32x4ShuffleMix) { | 2446 } else if (getter == MethodRecognizer::kFloat32x4ShuffleMix) { |
2406 Simd32x4ShuffleMixInstr* instr = new Simd32x4ShuffleMixInstr( | 2447 Simd32x4ShuffleMixInstr* instr = new(isolate()) Simd32x4ShuffleMixInstr( |
2407 getter, | 2448 getter, |
2408 new Value(call->ArgumentAt(0)), | 2449 new(isolate()) Value(call->ArgumentAt(0)), |
2409 new Value(call->ArgumentAt(1)), | 2450 new(isolate()) Value(call->ArgumentAt(1)), |
2410 mask, | 2451 mask, |
2411 call->deopt_id()); | 2452 call->deopt_id()); |
2412 ReplaceCall(call, instr); | 2453 ReplaceCall(call, instr); |
2413 return true; | 2454 return true; |
2414 } else { | 2455 } else { |
2415 ASSERT((getter == MethodRecognizer::kFloat32x4Shuffle) || | 2456 ASSERT((getter == MethodRecognizer::kFloat32x4Shuffle) || |
2416 (getter == MethodRecognizer::kFloat32x4ShuffleX) || | 2457 (getter == MethodRecognizer::kFloat32x4ShuffleX) || |
2417 (getter == MethodRecognizer::kFloat32x4ShuffleY) || | 2458 (getter == MethodRecognizer::kFloat32x4ShuffleY) || |
2418 (getter == MethodRecognizer::kFloat32x4ShuffleZ) || | 2459 (getter == MethodRecognizer::kFloat32x4ShuffleZ) || |
2419 (getter == MethodRecognizer::kFloat32x4ShuffleW)); | 2460 (getter == MethodRecognizer::kFloat32x4ShuffleW)); |
2420 Simd32x4ShuffleInstr* instr = new Simd32x4ShuffleInstr( | 2461 Simd32x4ShuffleInstr* instr = new(isolate()) Simd32x4ShuffleInstr( |
2421 getter, | 2462 getter, |
2422 new Value(call->ArgumentAt(0)), | 2463 new(isolate()) Value(call->ArgumentAt(0)), |
2423 mask, | 2464 mask, |
2424 call->deopt_id()); | 2465 call->deopt_id()); |
2425 ReplaceCall(call, instr); | 2466 ReplaceCall(call, instr); |
2426 return true; | 2467 return true; |
2427 } | 2468 } |
2428 UNREACHABLE(); | 2469 UNREACHABLE(); |
2429 return false; | 2470 return false; |
2430 } | 2471 } |
2431 | 2472 |
2432 | 2473 |
2433 bool FlowGraphOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call, | 2474 bool FlowGraphOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call, |
2434 MethodRecognizer::Kind getter) { | 2475 MethodRecognizer::Kind getter) { |
2435 if (!ShouldInlineSimd()) { | 2476 if (!ShouldInlineSimd()) { |
2436 return false; | 2477 return false; |
2437 } | 2478 } |
2438 AddCheckClass(call->ArgumentAt(0), | 2479 AddCheckClass(call->ArgumentAt(0), |
2439 ICData::ZoneHandle( | 2480 ICData::ZoneHandle( |
2440 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 2481 isolate(), call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
2441 call->deopt_id(), | 2482 call->deopt_id(), |
2442 call->env(), | 2483 call->env(), |
2443 call); | 2484 call); |
2444 if ((getter == MethodRecognizer::kFloat64x2GetX) || | 2485 if ((getter == MethodRecognizer::kFloat64x2GetX) || |
2445 (getter == MethodRecognizer::kFloat64x2GetY)) { | 2486 (getter == MethodRecognizer::kFloat64x2GetY)) { |
2446 Simd64x2ShuffleInstr* instr = new Simd64x2ShuffleInstr( | 2487 Simd64x2ShuffleInstr* instr = new(isolate()) Simd64x2ShuffleInstr( |
2447 getter, | 2488 getter, |
2448 new Value(call->ArgumentAt(0)), | 2489 new(isolate()) Value(call->ArgumentAt(0)), |
2449 0, | 2490 0, |
2450 call->deopt_id()); | 2491 call->deopt_id()); |
2451 ReplaceCall(call, instr); | 2492 ReplaceCall(call, instr); |
2452 return true; | 2493 return true; |
2453 } | 2494 } |
2454 UNREACHABLE(); | 2495 UNREACHABLE(); |
2455 return false; | 2496 return false; |
2456 } | 2497 } |
2457 | 2498 |
2458 | 2499 |
2459 bool FlowGraphOptimizer::InlineInt32x4Getter(InstanceCallInstr* call, | 2500 bool FlowGraphOptimizer::InlineInt32x4Getter(InstanceCallInstr* call, |
2460 MethodRecognizer::Kind getter) { | 2501 MethodRecognizer::Kind getter) { |
2461 if (!ShouldInlineSimd()) { | 2502 if (!ShouldInlineSimd()) { |
2462 return false; | 2503 return false; |
2463 } | 2504 } |
2464 AddCheckClass(call->ArgumentAt(0), | 2505 AddCheckClass(call->ArgumentAt(0), |
2465 ICData::ZoneHandle( | 2506 ICData::ZoneHandle( |
2466 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 2507 isolate(), call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
2467 call->deopt_id(), | 2508 call->deopt_id(), |
2468 call->env(), | 2509 call->env(), |
2469 call); | 2510 call); |
2470 intptr_t mask = 0; | 2511 intptr_t mask = 0; |
2471 if ((getter == MethodRecognizer::kInt32x4Shuffle) || | 2512 if ((getter == MethodRecognizer::kInt32x4Shuffle) || |
2472 (getter == MethodRecognizer::kInt32x4ShuffleMix)) { | 2513 (getter == MethodRecognizer::kInt32x4ShuffleMix)) { |
2473 // Extract shuffle mask. | 2514 // Extract shuffle mask. |
2474 Definition* mask_definition = NULL; | 2515 Definition* mask_definition = NULL; |
2475 if (getter == MethodRecognizer::kInt32x4Shuffle) { | 2516 if (getter == MethodRecognizer::kInt32x4Shuffle) { |
2476 ASSERT(call->ArgumentCount() == 2); | 2517 ASSERT(call->ArgumentCount() == 2); |
(...skipping 13 matching lines...) Expand all Loading... |
2490 return false; | 2531 return false; |
2491 } | 2532 } |
2492 ASSERT(constant_mask.IsSmi()); | 2533 ASSERT(constant_mask.IsSmi()); |
2493 mask = Smi::Cast(constant_mask).Value(); | 2534 mask = Smi::Cast(constant_mask).Value(); |
2494 if ((mask < 0) || (mask > 255)) { | 2535 if ((mask < 0) || (mask > 255)) { |
2495 // Not a valid mask. | 2536 // Not a valid mask. |
2496 return false; | 2537 return false; |
2497 } | 2538 } |
2498 } | 2539 } |
2499 if (getter == MethodRecognizer::kInt32x4GetSignMask) { | 2540 if (getter == MethodRecognizer::kInt32x4GetSignMask) { |
2500 Simd32x4GetSignMaskInstr* instr = new Simd32x4GetSignMaskInstr( | 2541 Simd32x4GetSignMaskInstr* instr = new(isolate()) Simd32x4GetSignMaskInstr( |
2501 getter, | 2542 getter, |
2502 new Value(call->ArgumentAt(0)), | 2543 new(isolate()) Value(call->ArgumentAt(0)), |
2503 call->deopt_id()); | 2544 call->deopt_id()); |
2504 ReplaceCall(call, instr); | 2545 ReplaceCall(call, instr); |
2505 return true; | 2546 return true; |
2506 } else if (getter == MethodRecognizer::kInt32x4ShuffleMix) { | 2547 } else if (getter == MethodRecognizer::kInt32x4ShuffleMix) { |
2507 Simd32x4ShuffleMixInstr* instr = new Simd32x4ShuffleMixInstr( | 2548 Simd32x4ShuffleMixInstr* instr = new(isolate()) Simd32x4ShuffleMixInstr( |
2508 getter, | 2549 getter, |
2509 new Value(call->ArgumentAt(0)), | 2550 new(isolate()) Value(call->ArgumentAt(0)), |
2510 new Value(call->ArgumentAt(1)), | 2551 new(isolate()) Value(call->ArgumentAt(1)), |
2511 mask, | 2552 mask, |
2512 call->deopt_id()); | 2553 call->deopt_id()); |
2513 ReplaceCall(call, instr); | 2554 ReplaceCall(call, instr); |
2514 return true; | 2555 return true; |
2515 } else if (getter == MethodRecognizer::kInt32x4Shuffle) { | 2556 } else if (getter == MethodRecognizer::kInt32x4Shuffle) { |
2516 Simd32x4ShuffleInstr* instr = new Simd32x4ShuffleInstr( | 2557 Simd32x4ShuffleInstr* instr = new(isolate()) Simd32x4ShuffleInstr( |
2517 getter, | 2558 getter, |
2518 new Value(call->ArgumentAt(0)), | 2559 new(isolate()) Value(call->ArgumentAt(0)), |
2519 mask, | 2560 mask, |
2520 call->deopt_id()); | 2561 call->deopt_id()); |
2521 ReplaceCall(call, instr); | 2562 ReplaceCall(call, instr); |
2522 return true; | 2563 return true; |
2523 } else { | 2564 } else { |
2524 Int32x4GetFlagInstr* instr = new Int32x4GetFlagInstr( | 2565 Int32x4GetFlagInstr* instr = new(isolate()) Int32x4GetFlagInstr( |
2525 getter, | 2566 getter, |
2526 new Value(call->ArgumentAt(0)), | 2567 new(isolate()) Value(call->ArgumentAt(0)), |
2527 call->deopt_id()); | 2568 call->deopt_id()); |
2528 ReplaceCall(call, instr); | 2569 ReplaceCall(call, instr); |
2529 return true; | 2570 return true; |
2530 } | 2571 } |
2531 } | 2572 } |
2532 | 2573 |
2533 | 2574 |
2534 bool FlowGraphOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, | 2575 bool FlowGraphOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, |
2535 Token::Kind op_kind) { | 2576 Token::Kind op_kind) { |
2536 if (!ShouldInlineSimd()) { | 2577 if (!ShouldInlineSimd()) { |
2537 return false; | 2578 return false; |
2538 } | 2579 } |
2539 ASSERT(call->ArgumentCount() == 2); | 2580 ASSERT(call->ArgumentCount() == 2); |
2540 Definition* left = call->ArgumentAt(0); | 2581 Definition* left = call->ArgumentAt(0); |
2541 Definition* right = call->ArgumentAt(1); | 2582 Definition* right = call->ArgumentAt(1); |
2542 // Type check left. | 2583 // Type check left. |
2543 AddCheckClass(left, | 2584 AddCheckClass(left, |
2544 ICData::ZoneHandle( | 2585 ICData::ZoneHandle( |
2545 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 2586 isolate(), call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
2546 call->deopt_id(), | 2587 call->deopt_id(), |
2547 call->env(), | 2588 call->env(), |
2548 call); | 2589 call); |
2549 // Type check right. | 2590 // Type check right. |
2550 AddCheckClass(right, | 2591 AddCheckClass(right, |
2551 ICData::ZoneHandle( | 2592 ICData::ZoneHandle( |
2552 call->ic_data()->AsUnaryClassChecksForArgNr(1)), | 2593 isolate(), call->ic_data()->AsUnaryClassChecksForArgNr(1)), |
2553 call->deopt_id(), | 2594 call->deopt_id(), |
2554 call->env(), | 2595 call->env(), |
2555 call); | 2596 call); |
2556 // Replace call. | 2597 // Replace call. |
2557 BinaryFloat32x4OpInstr* float32x4_bin_op = | 2598 BinaryFloat32x4OpInstr* float32x4_bin_op = |
2558 new BinaryFloat32x4OpInstr(op_kind, new Value(left), new Value(right), | 2599 new(isolate()) BinaryFloat32x4OpInstr( |
2559 call->deopt_id()); | 2600 op_kind, new(isolate()) Value(left), new(isolate()) Value(right), |
| 2601 call->deopt_id()); |
2560 ReplaceCall(call, float32x4_bin_op); | 2602 ReplaceCall(call, float32x4_bin_op); |
2561 | 2603 |
2562 return true; | 2604 return true; |
2563 } | 2605 } |
2564 | 2606 |
2565 | 2607 |
2566 bool FlowGraphOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, | 2608 bool FlowGraphOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, |
2567 Token::Kind op_kind) { | 2609 Token::Kind op_kind) { |
2568 if (!ShouldInlineSimd()) { | 2610 if (!ShouldInlineSimd()) { |
2569 return false; | 2611 return false; |
2570 } | 2612 } |
2571 ASSERT(call->ArgumentCount() == 2); | 2613 ASSERT(call->ArgumentCount() == 2); |
2572 Definition* left = call->ArgumentAt(0); | 2614 Definition* left = call->ArgumentAt(0); |
2573 Definition* right = call->ArgumentAt(1); | 2615 Definition* right = call->ArgumentAt(1); |
2574 // Type check left. | 2616 // Type check left. |
2575 AddCheckClass(left, | 2617 AddCheckClass(left, |
2576 ICData::ZoneHandle( | 2618 ICData::ZoneHandle( |
2577 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 2619 isolate(), call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
2578 call->deopt_id(), | 2620 call->deopt_id(), |
2579 call->env(), | 2621 call->env(), |
2580 call); | 2622 call); |
2581 // Type check right. | 2623 // Type check right. |
2582 AddCheckClass(right, | 2624 AddCheckClass(right, |
2583 ICData::ZoneHandle( | 2625 ICData::ZoneHandle(isolate(), |
2584 call->ic_data()->AsUnaryClassChecksForArgNr(1)), | 2626 call->ic_data()->AsUnaryClassChecksForArgNr(1)), |
2585 call->deopt_id(), | 2627 call->deopt_id(), |
2586 call->env(), | 2628 call->env(), |
2587 call); | 2629 call); |
2588 // Replace call. | 2630 // Replace call. |
2589 BinaryInt32x4OpInstr* int32x4_bin_op = | 2631 BinaryInt32x4OpInstr* int32x4_bin_op = |
2590 new BinaryInt32x4OpInstr(op_kind, new Value(left), new Value(right), | 2632 new(isolate()) BinaryInt32x4OpInstr( |
2591 call->deopt_id()); | 2633 op_kind, new(isolate()) Value(left), new(isolate()) Value(right), |
| 2634 call->deopt_id()); |
2592 ReplaceCall(call, int32x4_bin_op); | 2635 ReplaceCall(call, int32x4_bin_op); |
2593 return true; | 2636 return true; |
2594 } | 2637 } |
2595 | 2638 |
2596 | 2639 |
2597 bool FlowGraphOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, | 2640 bool FlowGraphOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, |
2598 Token::Kind op_kind) { | 2641 Token::Kind op_kind) { |
2599 if (!ShouldInlineSimd()) { | 2642 if (!ShouldInlineSimd()) { |
2600 return false; | 2643 return false; |
2601 } | 2644 } |
2602 ASSERT(call->ArgumentCount() == 2); | 2645 ASSERT(call->ArgumentCount() == 2); |
2603 Definition* left = call->ArgumentAt(0); | 2646 Definition* left = call->ArgumentAt(0); |
2604 Definition* right = call->ArgumentAt(1); | 2647 Definition* right = call->ArgumentAt(1); |
2605 // Type check left. | 2648 // Type check left. |
2606 AddCheckClass(left, | 2649 AddCheckClass(left, |
2607 ICData::ZoneHandle( | 2650 ICData::ZoneHandle( |
2608 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 2651 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
2609 call->deopt_id(), | 2652 call->deopt_id(), |
2610 call->env(), | 2653 call->env(), |
2611 call); | 2654 call); |
2612 // Type check right. | 2655 // Type check right. |
2613 AddCheckClass(right, | 2656 AddCheckClass(right, |
2614 ICData::ZoneHandle( | 2657 ICData::ZoneHandle( |
2615 call->ic_data()->AsUnaryClassChecksForArgNr(1)), | 2658 call->ic_data()->AsUnaryClassChecksForArgNr(1)), |
2616 call->deopt_id(), | 2659 call->deopt_id(), |
2617 call->env(), | 2660 call->env(), |
2618 call); | 2661 call); |
2619 // Replace call. | 2662 // Replace call. |
2620 BinaryFloat64x2OpInstr* float64x2_bin_op = | 2663 BinaryFloat64x2OpInstr* float64x2_bin_op = |
2621 new BinaryFloat64x2OpInstr(op_kind, new Value(left), new Value(right), | 2664 new(isolate()) BinaryFloat64x2OpInstr( |
2622 call->deopt_id()); | 2665 op_kind, new(isolate()) Value(left), new(isolate()) Value(right), |
| 2666 call->deopt_id()); |
2623 ReplaceCall(call, float64x2_bin_op); | 2667 ReplaceCall(call, float64x2_bin_op); |
2624 return true; | 2668 return true; |
2625 } | 2669 } |
2626 | 2670 |
2627 | 2671 |
2628 // Only unique implicit instance getters can be currently handled. | 2672 // Only unique implicit instance getters can be currently handled. |
2629 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { | 2673 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { |
2630 ASSERT(call->HasICData()); | 2674 ASSERT(call->HasICData()); |
2631 const ICData& ic_data = *call->ic_data(); | 2675 const ICData& ic_data = *call->ic_data(); |
2632 if (ic_data.NumberOfChecks() == 0) { | 2676 if (ic_data.NumberOfChecks() == 0) { |
2633 // No type feedback collected. | 2677 // No type feedback collected. |
2634 return false; | 2678 return false; |
2635 } | 2679 } |
2636 | 2680 |
2637 if (!ic_data.HasOneTarget()) { | 2681 if (!ic_data.HasOneTarget()) { |
2638 // Polymorphic sites are inlined like normal methods by conventional | 2682 // Polymorphic sites are inlined like normal methods by conventional |
2639 // inlining in FlowGraphInliner. | 2683 // inlining in FlowGraphInliner. |
2640 return false; | 2684 return false; |
2641 } | 2685 } |
2642 | 2686 |
2643 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); | 2687 const Function& target = Function::Handle(isolate(), ic_data.GetTargetAt(0)); |
2644 if (target.kind() != RawFunction::kImplicitGetter) { | 2688 if (target.kind() != RawFunction::kImplicitGetter) { |
2645 // Non-implicit getters are inlined like normal methods by conventional | 2689 // Non-implicit getters are inlined like normal methods by conventional |
2646 // inlining in FlowGraphInliner. | 2690 // inlining in FlowGraphInliner. |
2647 return false; | 2691 return false; |
2648 } | 2692 } |
2649 InlineImplicitInstanceGetter(call); | 2693 InlineImplicitInstanceGetter(call); |
2650 return true; | 2694 return true; |
2651 } | 2695 } |
2652 | 2696 |
2653 | 2697 |
2654 bool FlowGraphOptimizer::TryReplaceInstanceCallWithInline( | 2698 bool FlowGraphOptimizer::TryReplaceInstanceCallWithInline( |
2655 InstanceCallInstr* call) { | 2699 InstanceCallInstr* call) { |
2656 ASSERT(call->HasICData()); | 2700 ASSERT(call->HasICData()); |
2657 Function& target = Function::Handle(); | 2701 Function& target = Function::Handle(isolate(), Function::null()); |
2658 GrowableArray<intptr_t> class_ids; | 2702 GrowableArray<intptr_t> class_ids; |
2659 call->ic_data()->GetCheckAt(0, &class_ids, &target); | 2703 call->ic_data()->GetCheckAt(0, &class_ids, &target); |
2660 const intptr_t receiver_cid = class_ids[0]; | 2704 const intptr_t receiver_cid = class_ids[0]; |
2661 | 2705 |
2662 TargetEntryInstr* entry; | 2706 TargetEntryInstr* entry; |
2663 Definition* last; | 2707 Definition* last; |
2664 if (!TryInlineRecognizedMethod(receiver_cid, | 2708 if (!TryInlineRecognizedMethod(receiver_cid, |
2665 target, | 2709 target, |
2666 call, | 2710 call, |
2667 call->ArgumentAt(0), | 2711 call->ArgumentAt(0), |
(...skipping 29 matching lines...) Expand all Loading... |
2697 | 2741 |
2698 // Returns the LoadIndexedInstr. | 2742 // Returns the LoadIndexedInstr. |
2699 Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp( | 2743 Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp( |
2700 Instruction* call, | 2744 Instruction* call, |
2701 intptr_t cid, | 2745 intptr_t cid, |
2702 Definition* str, | 2746 Definition* str, |
2703 Definition* index, | 2747 Definition* index, |
2704 Instruction* cursor) { | 2748 Instruction* cursor) { |
2705 | 2749 |
2706 cursor = flow_graph()->AppendTo(cursor, | 2750 cursor = flow_graph()->AppendTo(cursor, |
2707 new CheckSmiInstr(new Value(index), | 2751 new(isolate()) CheckSmiInstr( |
2708 call->deopt_id(), | 2752 new(isolate()) Value(index), |
2709 call->token_pos()), | 2753 call->deopt_id(), |
| 2754 call->token_pos()), |
2710 call->env(), | 2755 call->env(), |
2711 FlowGraph::kEffect); | 2756 FlowGraph::kEffect); |
2712 | 2757 |
2713 // Load the length of the string. | 2758 // Load the length of the string. |
2714 LoadFieldInstr* length = BuildLoadStringLength(str); | 2759 LoadFieldInstr* length = BuildLoadStringLength(str); |
2715 cursor = flow_graph()->AppendTo(cursor, length, NULL, FlowGraph::kValue); | 2760 cursor = flow_graph()->AppendTo(cursor, length, NULL, FlowGraph::kValue); |
2716 // Bounds check. | 2761 // Bounds check. |
2717 cursor = flow_graph()->AppendTo(cursor, | 2762 cursor = flow_graph()->AppendTo(cursor, |
2718 new CheckArrayBoundInstr(new Value(length), | 2763 new(isolate()) CheckArrayBoundInstr( |
2719 new Value(index), | 2764 new(isolate()) Value(length), |
2720 call->deopt_id()), | 2765 new(isolate()) Value(index), |
| 2766 call->deopt_id()), |
2721 call->env(), | 2767 call->env(), |
2722 FlowGraph::kEffect); | 2768 FlowGraph::kEffect); |
2723 | 2769 |
2724 LoadIndexedInstr* load_indexed = new LoadIndexedInstr( | 2770 LoadIndexedInstr* load_indexed = new(isolate()) LoadIndexedInstr( |
2725 new Value(str), | 2771 new(isolate()) Value(str), |
2726 new Value(index), | 2772 new(isolate()) Value(index), |
2727 FlowGraphCompiler::ElementSizeFor(cid), | 2773 FlowGraphCompiler::ElementSizeFor(cid), |
2728 cid, | 2774 cid, |
2729 Isolate::kNoDeoptId, | 2775 Isolate::kNoDeoptId, |
2730 call->token_pos()); | 2776 call->token_pos()); |
2731 | 2777 |
2732 cursor = flow_graph()->AppendTo(cursor, | 2778 cursor = flow_graph()->AppendTo(cursor, |
2733 load_indexed, | 2779 load_indexed, |
2734 NULL, | 2780 NULL, |
2735 FlowGraph::kValue); | 2781 FlowGraph::kValue); |
2736 ASSERT(cursor == load_indexed); | 2782 ASSERT(cursor == load_indexed); |
2737 return load_indexed; | 2783 return load_indexed; |
2738 } | 2784 } |
2739 | 2785 |
2740 | 2786 |
2741 bool FlowGraphOptimizer::InlineStringCodeUnitAt( | 2787 bool FlowGraphOptimizer::InlineStringCodeUnitAt( |
2742 Instruction* call, | 2788 Instruction* call, |
2743 intptr_t cid, | 2789 intptr_t cid, |
2744 TargetEntryInstr** entry, | 2790 TargetEntryInstr** entry, |
2745 Definition** last) { | 2791 Definition** last) { |
2746 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. | 2792 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. |
2747 if (RawObject::IsExternalStringClassId(cid)) { | 2793 if (RawObject::IsExternalStringClassId(cid)) { |
2748 return false; | 2794 return false; |
2749 } | 2795 } |
2750 | 2796 |
2751 Definition* str = call->ArgumentAt(0); | 2797 Definition* str = call->ArgumentAt(0); |
2752 Definition* index = call->ArgumentAt(1); | 2798 Definition* index = call->ArgumentAt(1); |
2753 | 2799 |
2754 *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(), | 2800 *entry = new(isolate()) TargetEntryInstr(flow_graph()->allocate_block_id(), |
2755 call->GetBlock()->try_index()); | 2801 call->GetBlock()->try_index()); |
2756 (*entry)->InheritDeoptTarget(call); | 2802 (*entry)->InheritDeoptTarget(isolate(), call); |
2757 | 2803 |
2758 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); | 2804 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); |
2759 | 2805 |
2760 return true; | 2806 return true; |
2761 } | 2807 } |
2762 | 2808 |
2763 | 2809 |
2764 bool FlowGraphOptimizer::InlineStringBaseCharAt( | 2810 bool FlowGraphOptimizer::InlineStringBaseCharAt( |
2765 Instruction* call, | 2811 Instruction* call, |
2766 intptr_t cid, | 2812 intptr_t cid, |
2767 TargetEntryInstr** entry, | 2813 TargetEntryInstr** entry, |
2768 Definition** last) { | 2814 Definition** last) { |
2769 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. | 2815 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. |
2770 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { | 2816 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { |
2771 return false; | 2817 return false; |
2772 } | 2818 } |
2773 Definition* str = call->ArgumentAt(0); | 2819 Definition* str = call->ArgumentAt(0); |
2774 Definition* index = call->ArgumentAt(1); | 2820 Definition* index = call->ArgumentAt(1); |
2775 | 2821 |
2776 *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(), | 2822 *entry = new(isolate()) TargetEntryInstr(flow_graph()->allocate_block_id(), |
2777 call->GetBlock()->try_index()); | 2823 call->GetBlock()->try_index()); |
2778 (*entry)->InheritDeoptTarget(call); | 2824 (*entry)->InheritDeoptTarget(isolate(), call); |
2779 | 2825 |
2780 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); | 2826 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); |
2781 | 2827 |
2782 StringFromCharCodeInstr* char_at = | 2828 StringFromCharCodeInstr* char_at = new(isolate()) StringFromCharCodeInstr( |
2783 new StringFromCharCodeInstr(new Value(*last), cid); | 2829 new(isolate()) Value(*last), cid); |
2784 | 2830 |
2785 flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue); | 2831 flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue); |
2786 *last = char_at; | 2832 *last = char_at; |
2787 | 2833 |
2788 return true; | 2834 return true; |
2789 } | 2835 } |
2790 | 2836 |
2791 | 2837 |
2792 void FlowGraphOptimizer::ReplaceWithMathCFunction( | 2838 void FlowGraphOptimizer::ReplaceWithMathCFunction( |
2793 InstanceCallInstr* call, | 2839 InstanceCallInstr* call, |
2794 MethodRecognizer::Kind recognized_kind) { | 2840 MethodRecognizer::Kind recognized_kind) { |
2795 AddReceiverCheck(call); | 2841 AddReceiverCheck(call); |
2796 ZoneGrowableArray<Value*>* args = | 2842 ZoneGrowableArray<Value*>* args = |
2797 new ZoneGrowableArray<Value*>(call->ArgumentCount()); | 2843 new(isolate()) ZoneGrowableArray<Value*>(call->ArgumentCount()); |
2798 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | 2844 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { |
2799 args->Add(new Value(call->ArgumentAt(i))); | 2845 args->Add(new(isolate()) Value(call->ArgumentAt(i))); |
2800 } | 2846 } |
2801 InvokeMathCFunctionInstr* invoke = | 2847 InvokeMathCFunctionInstr* invoke = |
2802 new InvokeMathCFunctionInstr(args, | 2848 new(isolate()) InvokeMathCFunctionInstr(args, |
2803 call->deopt_id(), | 2849 call->deopt_id(), |
2804 recognized_kind, | 2850 recognized_kind, |
2805 call->token_pos()); | 2851 call->token_pos()); |
2806 ReplaceCall(call, invoke); | 2852 ReplaceCall(call, invoke); |
2807 } | 2853 } |
2808 | 2854 |
2809 | 2855 |
2810 static bool IsSupportedByteArrayViewCid(intptr_t cid) { | 2856 static bool IsSupportedByteArrayViewCid(intptr_t cid) { |
2811 switch (cid) { | 2857 switch (cid) { |
2812 case kTypedDataInt8ArrayCid: | 2858 case kTypedDataInt8ArrayCid: |
2813 case kTypedDataUint8ArrayCid: | 2859 case kTypedDataUint8ArrayCid: |
2814 case kExternalTypedDataUint8ArrayCid: | 2860 case kExternalTypedDataUint8ArrayCid: |
2815 case kTypedDataUint8ClampedArrayCid: | 2861 case kTypedDataUint8ClampedArrayCid: |
(...skipping 15 matching lines...) Expand all Loading... |
2831 | 2877 |
2832 // Inline only simple, frequently called core library methods. | 2878 // Inline only simple, frequently called core library methods. |
2833 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { | 2879 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { |
2834 ASSERT(call->HasICData()); | 2880 ASSERT(call->HasICData()); |
2835 const ICData& ic_data = *call->ic_data(); | 2881 const ICData& ic_data = *call->ic_data(); |
2836 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { | 2882 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { |
2837 // No type feedback collected or multiple targets found. | 2883 // No type feedback collected or multiple targets found. |
2838 return false; | 2884 return false; |
2839 } | 2885 } |
2840 | 2886 |
2841 Function& target = Function::Handle(); | 2887 Function& target = Function::Handle(isolate(), Function::null()); |
2842 GrowableArray<intptr_t> class_ids; | 2888 GrowableArray<intptr_t> class_ids; |
2843 ic_data.GetCheckAt(0, &class_ids, &target); | 2889 ic_data.GetCheckAt(0, &class_ids, &target); |
2844 MethodRecognizer::Kind recognized_kind = | 2890 MethodRecognizer::Kind recognized_kind = |
2845 MethodRecognizer::RecognizeKind(target); | 2891 MethodRecognizer::RecognizeKind(target); |
2846 | 2892 |
2847 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) && | 2893 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) && |
2848 (ic_data.NumberOfChecks() == 1) && | 2894 (ic_data.NumberOfChecks() == 1) && |
2849 (class_ids[0] == kGrowableObjectArrayCid)) { | 2895 (class_ids[0] == kGrowableObjectArrayCid)) { |
2850 // This is an internal method, no need to check argument types. | 2896 // This is an internal method, no need to check argument types. |
2851 Definition* array = call->ArgumentAt(0); | 2897 Definition* array = call->ArgumentAt(0); |
2852 Definition* value = call->ArgumentAt(1); | 2898 Definition* value = call->ArgumentAt(1); |
2853 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( | 2899 StoreInstanceFieldInstr* store = new(isolate()) StoreInstanceFieldInstr( |
2854 GrowableObjectArray::data_offset(), | 2900 GrowableObjectArray::data_offset(), |
2855 new Value(array), | 2901 new(isolate()) Value(array), |
2856 new Value(value), | 2902 new(isolate()) Value(value), |
2857 kEmitStoreBarrier, | 2903 kEmitStoreBarrier, |
2858 call->token_pos()); | 2904 call->token_pos()); |
2859 ReplaceCall(call, store); | 2905 ReplaceCall(call, store); |
2860 return true; | 2906 return true; |
2861 } | 2907 } |
2862 | 2908 |
2863 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) && | 2909 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) && |
2864 (ic_data.NumberOfChecks() == 1) && | 2910 (ic_data.NumberOfChecks() == 1) && |
2865 (class_ids[0] == kGrowableObjectArrayCid)) { | 2911 (class_ids[0] == kGrowableObjectArrayCid)) { |
2866 // This is an internal method, no need to check argument types nor | 2912 // This is an internal method, no need to check argument types nor |
2867 // range. | 2913 // range. |
2868 Definition* array = call->ArgumentAt(0); | 2914 Definition* array = call->ArgumentAt(0); |
2869 Definition* value = call->ArgumentAt(1); | 2915 Definition* value = call->ArgumentAt(1); |
2870 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( | 2916 StoreInstanceFieldInstr* store = new(isolate()) StoreInstanceFieldInstr( |
2871 GrowableObjectArray::length_offset(), | 2917 GrowableObjectArray::length_offset(), |
2872 new Value(array), | 2918 new(isolate()) Value(array), |
2873 new Value(value), | 2919 new(isolate()) Value(value), |
2874 kEmitStoreBarrier, | 2920 kEmitStoreBarrier, |
2875 call->token_pos()); | 2921 call->token_pos()); |
2876 ReplaceCall(call, store); | 2922 ReplaceCall(call, store); |
2877 return true; | 2923 return true; |
2878 } | 2924 } |
2879 | 2925 |
2880 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || | 2926 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || |
2881 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && | 2927 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && |
2882 (ic_data.NumberOfChecks() == 1) && | 2928 (ic_data.NumberOfChecks() == 1) && |
2883 ((class_ids[0] == kOneByteStringCid) || | 2929 ((class_ids[0] == kOneByteStringCid) || |
2884 (class_ids[0] == kTwoByteStringCid))) { | 2930 (class_ids[0] == kTwoByteStringCid))) { |
2885 return TryReplaceInstanceCallWithInline(call); | 2931 return TryReplaceInstanceCallWithInline(call); |
2886 } | 2932 } |
2887 | 2933 |
2888 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { | 2934 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { |
2889 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { | 2935 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { |
2890 // This is an internal method, no need to check argument types nor | 2936 // This is an internal method, no need to check argument types nor |
2891 // range. | 2937 // range. |
2892 Definition* str = call->ArgumentAt(0); | 2938 Definition* str = call->ArgumentAt(0); |
2893 Definition* index = call->ArgumentAt(1); | 2939 Definition* index = call->ArgumentAt(1); |
2894 Definition* value = call->ArgumentAt(2); | 2940 Definition* value = call->ArgumentAt(2); |
2895 StoreIndexedInstr* store_op = new StoreIndexedInstr( | 2941 StoreIndexedInstr* store_op = new(isolate()) StoreIndexedInstr( |
2896 new Value(str), | 2942 new(isolate()) Value(str), |
2897 new Value(index), | 2943 new(isolate()) Value(index), |
2898 new Value(value), | 2944 new(isolate()) Value(value), |
2899 kNoStoreBarrier, | 2945 kNoStoreBarrier, |
2900 1, // Index scale | 2946 1, // Index scale |
2901 kOneByteStringCid, | 2947 kOneByteStringCid, |
2902 call->deopt_id(), | 2948 call->deopt_id(), |
2903 call->token_pos()); | 2949 call->token_pos()); |
2904 ReplaceCall(call, store_op); | 2950 ReplaceCall(call, store_op); |
2905 return true; | 2951 return true; |
2906 } | 2952 } |
2907 return false; | 2953 return false; |
2908 } | 2954 } |
2909 | 2955 |
2910 if (CanUnboxDouble() && | 2956 if (CanUnboxDouble() && |
2911 (recognized_kind == MethodRecognizer::kIntegerToDouble) && | 2957 (recognized_kind == MethodRecognizer::kIntegerToDouble) && |
2912 (ic_data.NumberOfChecks() == 1) && | 2958 (ic_data.NumberOfChecks() == 1) && |
2913 (class_ids[0] == kSmiCid)) { | 2959 (class_ids[0] == kSmiCid)) { |
2914 AddReceiverCheck(call); | 2960 AddReceiverCheck(call); |
2915 ReplaceCall(call, | 2961 ReplaceCall(call, |
2916 new SmiToDoubleInstr(new Value(call->ArgumentAt(0)), | 2962 new(isolate()) SmiToDoubleInstr( |
2917 call->token_pos())); | 2963 new(isolate()) Value(call->ArgumentAt(0)), |
| 2964 call->token_pos())); |
2918 return true; | 2965 return true; |
2919 } | 2966 } |
2920 | 2967 |
2921 if (class_ids[0] == kDoubleCid) { | 2968 if (class_ids[0] == kDoubleCid) { |
2922 if (!CanUnboxDouble()) { | 2969 if (!CanUnboxDouble()) { |
2923 return false; | 2970 return false; |
2924 } | 2971 } |
2925 switch (recognized_kind) { | 2972 switch (recognized_kind) { |
2926 case MethodRecognizer::kDoubleToInteger: { | 2973 case MethodRecognizer::kDoubleToInteger: { |
2927 AddReceiverCheck(call); | 2974 AddReceiverCheck(call); |
2928 ASSERT(call->HasICData()); | 2975 ASSERT(call->HasICData()); |
2929 const ICData& ic_data = *call->ic_data(); | 2976 const ICData& ic_data = *call->ic_data(); |
2930 Definition* input = call->ArgumentAt(0); | 2977 Definition* input = call->ArgumentAt(0); |
2931 Definition* d2i_instr = NULL; | 2978 Definition* d2i_instr = NULL; |
2932 if (ic_data.HasDeoptReason(ICData::kDeoptDoubleToSmi)) { | 2979 if (ic_data.HasDeoptReason(ICData::kDeoptDoubleToSmi)) { |
2933 // Do not repeatedly deoptimize because result didn't fit into Smi. | 2980 // Do not repeatedly deoptimize because result didn't fit into Smi. |
2934 d2i_instr = new DoubleToIntegerInstr(new Value(input), call); | 2981 d2i_instr = new(isolate()) DoubleToIntegerInstr( |
| 2982 new(isolate()) Value(input), call); |
2935 } else { | 2983 } else { |
2936 // Optimistically assume result fits into Smi. | 2984 // Optimistically assume result fits into Smi. |
2937 d2i_instr = new DoubleToSmiInstr(new Value(input), call->deopt_id()); | 2985 d2i_instr = new(isolate()) DoubleToSmiInstr( |
| 2986 new(isolate()) Value(input), call->deopt_id()); |
2938 } | 2987 } |
2939 ReplaceCall(call, d2i_instr); | 2988 ReplaceCall(call, d2i_instr); |
2940 return true; | 2989 return true; |
2941 } | 2990 } |
2942 case MethodRecognizer::kDoubleMod: | 2991 case MethodRecognizer::kDoubleMod: |
2943 case MethodRecognizer::kDoubleRound: | 2992 case MethodRecognizer::kDoubleRound: |
2944 ReplaceWithMathCFunction(call, recognized_kind); | 2993 ReplaceWithMathCFunction(call, recognized_kind); |
2945 return true; | 2994 return true; |
2946 case MethodRecognizer::kDoubleTruncate: | 2995 case MethodRecognizer::kDoubleTruncate: |
2947 case MethodRecognizer::kDoubleFloor: | 2996 case MethodRecognizer::kDoubleFloor: |
2948 case MethodRecognizer::kDoubleCeil: | 2997 case MethodRecognizer::kDoubleCeil: |
2949 if (!TargetCPUFeatures::double_truncate_round_supported()) { | 2998 if (!TargetCPUFeatures::double_truncate_round_supported()) { |
2950 ReplaceWithMathCFunction(call, recognized_kind); | 2999 ReplaceWithMathCFunction(call, recognized_kind); |
2951 } else { | 3000 } else { |
2952 AddReceiverCheck(call); | 3001 AddReceiverCheck(call); |
2953 DoubleToDoubleInstr* d2d_instr = | 3002 DoubleToDoubleInstr* d2d_instr = |
2954 new DoubleToDoubleInstr(new Value(call->ArgumentAt(0)), | 3003 new(isolate()) DoubleToDoubleInstr( |
2955 recognized_kind, call->deopt_id()); | 3004 new(isolate()) Value(call->ArgumentAt(0)), |
| 3005 recognized_kind, call->deopt_id()); |
2956 ReplaceCall(call, d2d_instr); | 3006 ReplaceCall(call, d2d_instr); |
2957 } | 3007 } |
2958 return true; | 3008 return true; |
2959 default: | 3009 default: |
2960 // Unsupported method. | 3010 // Unsupported method. |
2961 return false; | 3011 return false; |
2962 } | 3012 } |
2963 } | 3013 } |
2964 | 3014 |
2965 if (IsSupportedByteArrayViewCid(class_ids[0]) && | 3015 if (IsSupportedByteArrayViewCid(class_ids[0]) && |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3062 ASSERT(int32_mask->IsConstant()); | 3112 ASSERT(int32_mask->IsConstant()); |
3063 const Integer& mask_literal = Integer::Cast( | 3113 const Integer& mask_literal = Integer::Cast( |
3064 int32_mask->AsConstant()->value()); | 3114 int32_mask->AsConstant()->value()); |
3065 const int64_t mask_value = mask_literal.AsInt64Value(); | 3115 const int64_t mask_value = mask_literal.AsInt64Value(); |
3066 ASSERT(mask_value >= 0); | 3116 ASSERT(mask_value >= 0); |
3067 if (mask_value > Smi::kMaxValue) { | 3117 if (mask_value > Smi::kMaxValue) { |
3068 // The result will not be Smi. | 3118 // The result will not be Smi. |
3069 return false; | 3119 return false; |
3070 } | 3120 } |
3071 BinarySmiOpInstr* left_shift = | 3121 BinarySmiOpInstr* left_shift = |
3072 new BinarySmiOpInstr(Token::kSHL, | 3122 new(isolate()) BinarySmiOpInstr(Token::kSHL, |
3073 new Value(value), new Value(count), | 3123 new(isolate()) Value(value), |
3074 call->deopt_id(), call->token_pos()); | 3124 new(isolate()) Value(count), |
| 3125 call->deopt_id(), call->token_pos()); |
3075 left_shift->set_is_truncating(true); | 3126 left_shift->set_is_truncating(true); |
3076 if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) { | 3127 if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) { |
3077 // No BIT_AND operation needed. | 3128 // No BIT_AND operation needed. |
3078 ReplaceCall(call, left_shift); | 3129 ReplaceCall(call, left_shift); |
3079 } else { | 3130 } else { |
3080 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue); | 3131 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue); |
3081 BinarySmiOpInstr* bit_and = | 3132 BinarySmiOpInstr* bit_and = |
3082 new BinarySmiOpInstr(Token::kBIT_AND, | 3133 new(isolate()) BinarySmiOpInstr(Token::kBIT_AND, |
3083 new Value(left_shift), new Value(int32_mask), | 3134 new(isolate()) Value(left_shift), |
3084 call->deopt_id(), call->token_pos()); | 3135 new(isolate()) Value(int32_mask), |
| 3136 call->deopt_id(), |
| 3137 call->token_pos()); |
3085 ReplaceCall(call, bit_and); | 3138 ReplaceCall(call, bit_and); |
3086 } | 3139 } |
3087 return true; | 3140 return true; |
3088 } | 3141 } |
3089 | 3142 |
3090 if (HasTwoMintOrSmi(ic_data) && | 3143 if (HasTwoMintOrSmi(ic_data) && |
3091 HasOnlyOneSmi(ICData::Handle(ic_data.AsUnaryClassChecksForArgNr(1)))) { | 3144 HasOnlyOneSmi(ICData::Handle(isolate(), |
| 3145 ic_data.AsUnaryClassChecksForArgNr(1)))) { |
3092 if (!FlowGraphCompiler::SupportsUnboxedMints() || | 3146 if (!FlowGraphCompiler::SupportsUnboxedMints() || |
3093 ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { | 3147 ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { |
3094 return false; | 3148 return false; |
3095 } | 3149 } |
3096 ShiftMintOpInstr* left_shift = | 3150 ShiftMintOpInstr* left_shift = |
3097 new ShiftMintOpInstr(Token::kSHL, | 3151 new(isolate()) ShiftMintOpInstr(Token::kSHL, |
3098 new Value(value), new Value(count), | 3152 new(isolate()) Value(value), |
3099 call->deopt_id()); | 3153 new(isolate()) Value(count), |
| 3154 call->deopt_id()); |
3100 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue); | 3155 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue); |
3101 BinaryMintOpInstr* bit_and = | 3156 BinaryMintOpInstr* bit_and = |
3102 new BinaryMintOpInstr(Token::kBIT_AND, | 3157 new(isolate()) BinaryMintOpInstr(Token::kBIT_AND, |
3103 new Value(left_shift), new Value(int32_mask), | 3158 new(isolate()) Value(left_shift), |
3104 call->deopt_id()); | 3159 new(isolate()) Value(int32_mask), |
| 3160 call->deopt_id()); |
3105 ReplaceCall(call, bit_and); | 3161 ReplaceCall(call, bit_and); |
3106 return true; | 3162 return true; |
3107 } | 3163 } |
3108 } | 3164 } |
3109 return false; | 3165 return false; |
3110 } | 3166 } |
3111 | 3167 |
3112 | 3168 |
3113 bool FlowGraphOptimizer::TryInlineFloat32x4Constructor( | 3169 bool FlowGraphOptimizer::TryInlineFloat32x4Constructor( |
3114 StaticCallInstr* call, | 3170 StaticCallInstr* call, |
3115 MethodRecognizer::Kind recognized_kind) { | 3171 MethodRecognizer::Kind recognized_kind) { |
3116 if (!ShouldInlineSimd()) { | 3172 if (!ShouldInlineSimd()) { |
3117 return false; | 3173 return false; |
3118 } | 3174 } |
3119 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) { | 3175 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) { |
3120 Float32x4ZeroInstr* zero = new Float32x4ZeroInstr(call->deopt_id()); | 3176 Float32x4ZeroInstr* zero = |
| 3177 new(isolate()) Float32x4ZeroInstr(call->deopt_id()); |
3121 ReplaceCall(call, zero); | 3178 ReplaceCall(call, zero); |
3122 return true; | 3179 return true; |
3123 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) { | 3180 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) { |
3124 Float32x4SplatInstr* splat = | 3181 Float32x4SplatInstr* splat = |
3125 new Float32x4SplatInstr(new Value(call->ArgumentAt(1)), | 3182 new(isolate()) Float32x4SplatInstr( |
3126 call->deopt_id()); | 3183 new(isolate()) Value(call->ArgumentAt(1)), call->deopt_id()); |
3127 ReplaceCall(call, splat); | 3184 ReplaceCall(call, splat); |
3128 return true; | 3185 return true; |
3129 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) { | 3186 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) { |
3130 Float32x4ConstructorInstr* con = | 3187 Float32x4ConstructorInstr* con = |
3131 new Float32x4ConstructorInstr(new Value(call->ArgumentAt(1)), | 3188 new(isolate()) Float32x4ConstructorInstr( |
3132 new Value(call->ArgumentAt(2)), | 3189 new(isolate()) Value(call->ArgumentAt(1)), |
3133 new Value(call->ArgumentAt(3)), | 3190 new(isolate()) Value(call->ArgumentAt(2)), |
3134 new Value(call->ArgumentAt(4)), | 3191 new(isolate()) Value(call->ArgumentAt(3)), |
3135 call->deopt_id()); | 3192 new(isolate()) Value(call->ArgumentAt(4)), |
| 3193 call->deopt_id()); |
3136 ReplaceCall(call, con); | 3194 ReplaceCall(call, con); |
3137 return true; | 3195 return true; |
3138 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromInt32x4Bits) { | 3196 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromInt32x4Bits) { |
3139 Int32x4ToFloat32x4Instr* cast = | 3197 Int32x4ToFloat32x4Instr* cast = |
3140 new Int32x4ToFloat32x4Instr(new Value(call->ArgumentAt(1)), | 3198 new(isolate()) Int32x4ToFloat32x4Instr( |
3141 call->deopt_id()); | 3199 new(isolate()) Value(call->ArgumentAt(1)), call->deopt_id()); |
3142 ReplaceCall(call, cast); | 3200 ReplaceCall(call, cast); |
3143 return true; | 3201 return true; |
3144 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2) { | 3202 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2) { |
3145 Float64x2ToFloat32x4Instr* cast = | 3203 Float64x2ToFloat32x4Instr* cast = |
3146 new Float64x2ToFloat32x4Instr(new Value(call->ArgumentAt(1)), | 3204 new(isolate()) Float64x2ToFloat32x4Instr( |
3147 call->deopt_id()); | 3205 new(isolate()) Value(call->ArgumentAt(1)), call->deopt_id()); |
3148 ReplaceCall(call, cast); | 3206 ReplaceCall(call, cast); |
3149 return true; | 3207 return true; |
3150 } | 3208 } |
3151 return false; | 3209 return false; |
3152 } | 3210 } |
3153 | 3211 |
3154 | 3212 |
3155 bool FlowGraphOptimizer::TryInlineFloat64x2Constructor( | 3213 bool FlowGraphOptimizer::TryInlineFloat64x2Constructor( |
3156 StaticCallInstr* call, | 3214 StaticCallInstr* call, |
3157 MethodRecognizer::Kind recognized_kind) { | 3215 MethodRecognizer::Kind recognized_kind) { |
3158 if (!ShouldInlineSimd()) { | 3216 if (!ShouldInlineSimd()) { |
3159 return false; | 3217 return false; |
3160 } | 3218 } |
3161 if (recognized_kind == MethodRecognizer::kFloat64x2Zero) { | 3219 if (recognized_kind == MethodRecognizer::kFloat64x2Zero) { |
3162 Float64x2ZeroInstr* zero = new Float64x2ZeroInstr(call->deopt_id()); | 3220 Float64x2ZeroInstr* zero = |
| 3221 new(isolate()) Float64x2ZeroInstr(call->deopt_id()); |
3163 ReplaceCall(call, zero); | 3222 ReplaceCall(call, zero); |
3164 return true; | 3223 return true; |
3165 } else if (recognized_kind == MethodRecognizer::kFloat64x2Splat) { | 3224 } else if (recognized_kind == MethodRecognizer::kFloat64x2Splat) { |
3166 Float64x2SplatInstr* splat = | 3225 Float64x2SplatInstr* splat = |
3167 new Float64x2SplatInstr(new Value(call->ArgumentAt(1)), | 3226 new(isolate()) Float64x2SplatInstr( |
3168 call->deopt_id()); | 3227 new(isolate()) Value(call->ArgumentAt(1)), call->deopt_id()); |
3169 ReplaceCall(call, splat); | 3228 ReplaceCall(call, splat); |
3170 return true; | 3229 return true; |
3171 } else if (recognized_kind == MethodRecognizer::kFloat64x2Constructor) { | 3230 } else if (recognized_kind == MethodRecognizer::kFloat64x2Constructor) { |
3172 Float64x2ConstructorInstr* con = | 3231 Float64x2ConstructorInstr* con = |
3173 new Float64x2ConstructorInstr(new Value(call->ArgumentAt(1)), | 3232 new(isolate()) Float64x2ConstructorInstr( |
3174 new Value(call->ArgumentAt(2)), | 3233 new(isolate()) Value(call->ArgumentAt(1)), |
3175 call->deopt_id()); | 3234 new(isolate()) Value(call->ArgumentAt(2)), |
| 3235 call->deopt_id()); |
3176 ReplaceCall(call, con); | 3236 ReplaceCall(call, con); |
3177 return true; | 3237 return true; |
3178 } else if (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4) { | 3238 } else if (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4) { |
3179 Float32x4ToFloat64x2Instr* cast = | 3239 Float32x4ToFloat64x2Instr* cast = |
3180 new Float32x4ToFloat64x2Instr(new Value(call->ArgumentAt(1)), | 3240 new(isolate()) Float32x4ToFloat64x2Instr( |
3181 call->deopt_id()); | 3241 new(isolate()) Value(call->ArgumentAt(1)), call->deopt_id()); |
3182 ReplaceCall(call, cast); | 3242 ReplaceCall(call, cast); |
3183 return true; | 3243 return true; |
3184 } | 3244 } |
3185 return false; | 3245 return false; |
3186 } | 3246 } |
3187 | 3247 |
3188 | 3248 |
3189 bool FlowGraphOptimizer::TryInlineInt32x4Constructor( | 3249 bool FlowGraphOptimizer::TryInlineInt32x4Constructor( |
3190 StaticCallInstr* call, | 3250 StaticCallInstr* call, |
3191 MethodRecognizer::Kind recognized_kind) { | 3251 MethodRecognizer::Kind recognized_kind) { |
3192 if (!ShouldInlineSimd()) { | 3252 if (!ShouldInlineSimd()) { |
3193 return false; | 3253 return false; |
3194 } | 3254 } |
3195 if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) { | 3255 if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) { |
3196 Int32x4BoolConstructorInstr* con = new Int32x4BoolConstructorInstr( | 3256 Int32x4BoolConstructorInstr* con = |
3197 new Value(call->ArgumentAt(1)), | 3257 new(isolate()) Int32x4BoolConstructorInstr( |
3198 new Value(call->ArgumentAt(2)), | 3258 new(isolate()) Value(call->ArgumentAt(1)), |
3199 new Value(call->ArgumentAt(3)), | 3259 new(isolate()) Value(call->ArgumentAt(2)), |
3200 new Value(call->ArgumentAt(4)), | 3260 new(isolate()) Value(call->ArgumentAt(3)), |
3201 call->deopt_id()); | 3261 new(isolate()) Value(call->ArgumentAt(4)), |
| 3262 call->deopt_id()); |
3202 ReplaceCall(call, con); | 3263 ReplaceCall(call, con); |
3203 return true; | 3264 return true; |
3204 } else if (recognized_kind == MethodRecognizer::kInt32x4FromFloat32x4Bits) { | 3265 } else if (recognized_kind == MethodRecognizer::kInt32x4FromFloat32x4Bits) { |
3205 Float32x4ToInt32x4Instr* cast = | 3266 Float32x4ToInt32x4Instr* cast = |
3206 new Float32x4ToInt32x4Instr(new Value(call->ArgumentAt(1)), | 3267 new(isolate()) Float32x4ToInt32x4Instr( |
3207 call->deopt_id()); | 3268 new(isolate()) Value(call->ArgumentAt(1)), call->deopt_id()); |
3208 ReplaceCall(call, cast); | 3269 ReplaceCall(call, cast); |
3209 return true; | 3270 return true; |
3210 } | 3271 } |
3211 return false; | 3272 return false; |
3212 } | 3273 } |
3213 | 3274 |
3214 | 3275 |
3215 bool FlowGraphOptimizer::TryInlineFloat32x4Method( | 3276 bool FlowGraphOptimizer::TryInlineFloat32x4Method( |
3216 InstanceCallInstr* call, | 3277 InstanceCallInstr* call, |
3217 MethodRecognizer::Kind recognized_kind) { | 3278 MethodRecognizer::Kind recognized_kind) { |
(...skipping 15 matching lines...) Expand all Loading... |
3233 case MethodRecognizer::kFloat32x4GreaterThan: | 3294 case MethodRecognizer::kFloat32x4GreaterThan: |
3234 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: | 3295 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: |
3235 case MethodRecognizer::kFloat32x4LessThan: | 3296 case MethodRecognizer::kFloat32x4LessThan: |
3236 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 3297 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
3237 case MethodRecognizer::kFloat32x4NotEqual: { | 3298 case MethodRecognizer::kFloat32x4NotEqual: { |
3238 Definition* left = call->ArgumentAt(0); | 3299 Definition* left = call->ArgumentAt(0); |
3239 Definition* right = call->ArgumentAt(1); | 3300 Definition* right = call->ArgumentAt(1); |
3240 // Type check left. | 3301 // Type check left. |
3241 AddCheckClass(left, | 3302 AddCheckClass(left, |
3242 ICData::ZoneHandle( | 3303 ICData::ZoneHandle( |
| 3304 isolate(), |
3243 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 3305 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3244 call->deopt_id(), | 3306 call->deopt_id(), |
3245 call->env(), | 3307 call->env(), |
3246 call); | 3308 call); |
3247 // Replace call. | 3309 // Replace call. |
3248 Float32x4ComparisonInstr* cmp = | 3310 Float32x4ComparisonInstr* cmp = |
3249 new Float32x4ComparisonInstr(recognized_kind, new Value(left), | 3311 new(isolate()) Float32x4ComparisonInstr( |
3250 new Value(right), call->deopt_id()); | 3312 recognized_kind, |
| 3313 new(isolate()) Value(left), |
| 3314 new(isolate()) Value(right), |
| 3315 call->deopt_id()); |
3251 ReplaceCall(call, cmp); | 3316 ReplaceCall(call, cmp); |
3252 return true; | 3317 return true; |
3253 } | 3318 } |
3254 case MethodRecognizer::kFloat32x4Min: | 3319 case MethodRecognizer::kFloat32x4Min: |
3255 case MethodRecognizer::kFloat32x4Max: { | 3320 case MethodRecognizer::kFloat32x4Max: { |
3256 Definition* left = call->ArgumentAt(0); | 3321 Definition* left = call->ArgumentAt(0); |
3257 Definition* right = call->ArgumentAt(1); | 3322 Definition* right = call->ArgumentAt(1); |
3258 // Type check left. | 3323 // Type check left. |
3259 AddCheckClass(left, | 3324 AddCheckClass(left, |
3260 ICData::ZoneHandle( | 3325 ICData::ZoneHandle( |
| 3326 isolate(), |
3261 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 3327 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3262 call->deopt_id(), | 3328 call->deopt_id(), |
3263 call->env(), | 3329 call->env(), |
3264 call); | 3330 call); |
3265 Float32x4MinMaxInstr* minmax = | 3331 Float32x4MinMaxInstr* minmax = |
3266 new Float32x4MinMaxInstr(recognized_kind, new Value(left), | 3332 new(isolate()) Float32x4MinMaxInstr( |
3267 new Value(right), call->deopt_id()); | 3333 recognized_kind, |
| 3334 new(isolate()) Value(left), |
| 3335 new(isolate()) Value(right), |
| 3336 call->deopt_id()); |
3268 ReplaceCall(call, minmax); | 3337 ReplaceCall(call, minmax); |
3269 return true; | 3338 return true; |
3270 } | 3339 } |
3271 case MethodRecognizer::kFloat32x4Scale: { | 3340 case MethodRecognizer::kFloat32x4Scale: { |
3272 Definition* left = call->ArgumentAt(0); | 3341 Definition* left = call->ArgumentAt(0); |
3273 Definition* right = call->ArgumentAt(1); | 3342 Definition* right = call->ArgumentAt(1); |
3274 // Type check left. | 3343 // Type check left. |
3275 AddCheckClass(left, | 3344 AddCheckClass(left, |
3276 ICData::ZoneHandle( | 3345 ICData::ZoneHandle( |
| 3346 isolate(), |
3277 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 3347 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3278 call->deopt_id(), | 3348 call->deopt_id(), |
3279 call->env(), | 3349 call->env(), |
3280 call); | 3350 call); |
3281 // Left and right values are swapped when handed to the instruction, | 3351 // Left and right values are swapped when handed to the instruction, |
3282 // this is done so that the double value is loaded into the output | 3352 // this is done so that the double value is loaded into the output |
3283 // register and can be destroyed. | 3353 // register and can be destroyed. |
3284 Float32x4ScaleInstr* scale = | 3354 Float32x4ScaleInstr* scale = |
3285 new Float32x4ScaleInstr(recognized_kind, new Value(right), | 3355 new(isolate()) Float32x4ScaleInstr( |
3286 new Value(left), call->deopt_id()); | 3356 recognized_kind, |
| 3357 new(isolate()) Value(right), |
| 3358 new(isolate()) Value(left), |
| 3359 call->deopt_id()); |
3287 ReplaceCall(call, scale); | 3360 ReplaceCall(call, scale); |
3288 return true; | 3361 return true; |
3289 } | 3362 } |
3290 case MethodRecognizer::kFloat32x4Sqrt: | 3363 case MethodRecognizer::kFloat32x4Sqrt: |
3291 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 3364 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
3292 case MethodRecognizer::kFloat32x4Reciprocal: { | 3365 case MethodRecognizer::kFloat32x4Reciprocal: { |
3293 Definition* left = call->ArgumentAt(0); | 3366 Definition* left = call->ArgumentAt(0); |
3294 AddCheckClass(left, | 3367 AddCheckClass(left, |
3295 ICData::ZoneHandle( | 3368 ICData::ZoneHandle( |
| 3369 isolate(), |
3296 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 3370 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3297 call->deopt_id(), | 3371 call->deopt_id(), |
3298 call->env(), | 3372 call->env(), |
3299 call); | 3373 call); |
3300 Float32x4SqrtInstr* sqrt = | 3374 Float32x4SqrtInstr* sqrt = |
3301 new Float32x4SqrtInstr(recognized_kind, new Value(left), | 3375 new(isolate()) Float32x4SqrtInstr( |
3302 call->deopt_id()); | 3376 recognized_kind, |
| 3377 new(isolate()) Value(left), |
| 3378 call->deopt_id()); |
3303 ReplaceCall(call, sqrt); | 3379 ReplaceCall(call, sqrt); |
3304 return true; | 3380 return true; |
3305 } | 3381 } |
3306 case MethodRecognizer::kFloat32x4WithX: | 3382 case MethodRecognizer::kFloat32x4WithX: |
3307 case MethodRecognizer::kFloat32x4WithY: | 3383 case MethodRecognizer::kFloat32x4WithY: |
3308 case MethodRecognizer::kFloat32x4WithZ: | 3384 case MethodRecognizer::kFloat32x4WithZ: |
3309 case MethodRecognizer::kFloat32x4WithW: { | 3385 case MethodRecognizer::kFloat32x4WithW: { |
3310 Definition* left = call->ArgumentAt(0); | 3386 Definition* left = call->ArgumentAt(0); |
3311 Definition* right = call->ArgumentAt(1); | 3387 Definition* right = call->ArgumentAt(1); |
3312 // Type check left. | 3388 // Type check left. |
3313 AddCheckClass(left, | 3389 AddCheckClass(left, |
3314 ICData::ZoneHandle( | 3390 ICData::ZoneHandle( |
| 3391 isolate(), |
3315 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 3392 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3316 call->deopt_id(), | 3393 call->deopt_id(), |
3317 call->env(), | 3394 call->env(), |
3318 call); | 3395 call); |
3319 Float32x4WithInstr* with = new Float32x4WithInstr(recognized_kind, | 3396 Float32x4WithInstr* with = new(isolate()) Float32x4WithInstr( |
3320 new Value(left), | 3397 recognized_kind, |
3321 new Value(right), | 3398 new(isolate()) Value(left), |
3322 call->deopt_id()); | 3399 new(isolate()) Value(right), |
| 3400 call->deopt_id()); |
3323 ReplaceCall(call, with); | 3401 ReplaceCall(call, with); |
3324 return true; | 3402 return true; |
3325 } | 3403 } |
3326 case MethodRecognizer::kFloat32x4Absolute: | 3404 case MethodRecognizer::kFloat32x4Absolute: |
3327 case MethodRecognizer::kFloat32x4Negate: { | 3405 case MethodRecognizer::kFloat32x4Negate: { |
3328 Definition* left = call->ArgumentAt(0); | 3406 Definition* left = call->ArgumentAt(0); |
3329 // Type check left. | 3407 // Type check left. |
3330 AddCheckClass(left, | 3408 AddCheckClass(left, |
3331 ICData::ZoneHandle( | 3409 ICData::ZoneHandle( |
| 3410 isolate(), |
3332 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 3411 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3333 call->deopt_id(), | 3412 call->deopt_id(), |
3334 call->env(), | 3413 call->env(), |
3335 call); | 3414 call); |
3336 Float32x4ZeroArgInstr* zeroArg = | 3415 Float32x4ZeroArgInstr* zeroArg = |
3337 new Float32x4ZeroArgInstr(recognized_kind, new Value(left), | 3416 new(isolate()) Float32x4ZeroArgInstr( |
3338 call->deopt_id()); | 3417 recognized_kind, new(isolate()) Value(left), call->deopt_id()); |
3339 ReplaceCall(call, zeroArg); | 3418 ReplaceCall(call, zeroArg); |
3340 return true; | 3419 return true; |
3341 } | 3420 } |
3342 case MethodRecognizer::kFloat32x4Clamp: { | 3421 case MethodRecognizer::kFloat32x4Clamp: { |
3343 Definition* left = call->ArgumentAt(0); | 3422 Definition* left = call->ArgumentAt(0); |
3344 Definition* lower = call->ArgumentAt(1); | 3423 Definition* lower = call->ArgumentAt(1); |
3345 Definition* upper = call->ArgumentAt(2); | 3424 Definition* upper = call->ArgumentAt(2); |
3346 // Type check left. | 3425 // Type check left. |
3347 AddCheckClass(left, | 3426 AddCheckClass(left, |
3348 ICData::ZoneHandle( | 3427 ICData::ZoneHandle( |
| 3428 isolate(), |
3349 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 3429 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3350 call->deopt_id(), | 3430 call->deopt_id(), |
3351 call->env(), | 3431 call->env(), |
3352 call); | 3432 call); |
3353 Float32x4ClampInstr* clamp = new Float32x4ClampInstr(new Value(left), | 3433 Float32x4ClampInstr* clamp = new(isolate()) Float32x4ClampInstr( |
3354 new Value(lower), | 3434 new(isolate()) Value(left), |
3355 new Value(upper), | 3435 new(isolate()) Value(lower), |
3356 call->deopt_id()); | 3436 new(isolate()) Value(upper), |
| 3437 call->deopt_id()); |
3357 ReplaceCall(call, clamp); | 3438 ReplaceCall(call, clamp); |
3358 return true; | 3439 return true; |
3359 } | 3440 } |
3360 case MethodRecognizer::kFloat32x4ShuffleMix: | 3441 case MethodRecognizer::kFloat32x4ShuffleMix: |
3361 case MethodRecognizer::kFloat32x4Shuffle: { | 3442 case MethodRecognizer::kFloat32x4Shuffle: { |
3362 return InlineFloat32x4Getter(call, recognized_kind); | 3443 return InlineFloat32x4Getter(call, recognized_kind); |
3363 } | 3444 } |
3364 default: | 3445 default: |
3365 return false; | 3446 return false; |
3366 } | 3447 } |
(...skipping 14 matching lines...) Expand all Loading... |
3381 ASSERT(call->ic_data()->HasOneTarget()); | 3462 ASSERT(call->ic_data()->HasOneTarget()); |
3382 return InlineFloat64x2Getter(call, recognized_kind); | 3463 return InlineFloat64x2Getter(call, recognized_kind); |
3383 case MethodRecognizer::kFloat64x2Negate: | 3464 case MethodRecognizer::kFloat64x2Negate: |
3384 case MethodRecognizer::kFloat64x2Abs: | 3465 case MethodRecognizer::kFloat64x2Abs: |
3385 case MethodRecognizer::kFloat64x2Sqrt: | 3466 case MethodRecognizer::kFloat64x2Sqrt: |
3386 case MethodRecognizer::kFloat64x2GetSignMask: { | 3467 case MethodRecognizer::kFloat64x2GetSignMask: { |
3387 Definition* left = call->ArgumentAt(0); | 3468 Definition* left = call->ArgumentAt(0); |
3388 // Type check left. | 3469 // Type check left. |
3389 AddCheckClass(left, | 3470 AddCheckClass(left, |
3390 ICData::ZoneHandle( | 3471 ICData::ZoneHandle( |
| 3472 isolate(), |
3391 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 3473 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3392 call->deopt_id(), | 3474 call->deopt_id(), |
3393 call->env(), | 3475 call->env(), |
3394 call); | 3476 call); |
3395 Float64x2ZeroArgInstr* zeroArg = | 3477 Float64x2ZeroArgInstr* zeroArg = |
3396 new Float64x2ZeroArgInstr(recognized_kind, new Value(left), | 3478 new(isolate()) Float64x2ZeroArgInstr( |
3397 call->deopt_id()); | 3479 recognized_kind, new(isolate()) Value(left), call->deopt_id()); |
3398 ReplaceCall(call, zeroArg); | 3480 ReplaceCall(call, zeroArg); |
3399 return true; | 3481 return true; |
3400 } | 3482 } |
3401 case MethodRecognizer::kFloat64x2Scale: | 3483 case MethodRecognizer::kFloat64x2Scale: |
3402 case MethodRecognizer::kFloat64x2WithX: | 3484 case MethodRecognizer::kFloat64x2WithX: |
3403 case MethodRecognizer::kFloat64x2WithY: | 3485 case MethodRecognizer::kFloat64x2WithY: |
3404 case MethodRecognizer::kFloat64x2Min: | 3486 case MethodRecognizer::kFloat64x2Min: |
3405 case MethodRecognizer::kFloat64x2Max: { | 3487 case MethodRecognizer::kFloat64x2Max: { |
3406 Definition* left = call->ArgumentAt(0); | 3488 Definition* left = call->ArgumentAt(0); |
3407 Definition* right = call->ArgumentAt(1); | 3489 Definition* right = call->ArgumentAt(1); |
3408 // Type check left. | 3490 // Type check left. |
3409 AddCheckClass(left, | 3491 AddCheckClass(left, |
3410 ICData::ZoneHandle( | 3492 ICData::ZoneHandle( |
| 3493 isolate(), |
3411 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 3494 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3412 call->deopt_id(), | 3495 call->deopt_id(), |
3413 call->env(), | 3496 call->env(), |
3414 call); | 3497 call); |
3415 Float64x2OneArgInstr* zeroArg = | 3498 Float64x2OneArgInstr* zeroArg = |
3416 new Float64x2OneArgInstr(recognized_kind, new Value(left), | 3499 new(isolate()) Float64x2OneArgInstr( |
3417 new Value(right), call->deopt_id()); | 3500 recognized_kind, |
| 3501 new(isolate()) Value(left), |
| 3502 new(isolate()) Value(right), |
| 3503 call->deopt_id()); |
3418 ReplaceCall(call, zeroArg); | 3504 ReplaceCall(call, zeroArg); |
3419 return true; | 3505 return true; |
3420 } | 3506 } |
3421 default: | 3507 default: |
3422 return false; | 3508 return false; |
3423 } | 3509 } |
3424 } | 3510 } |
3425 | 3511 |
3426 | 3512 |
3427 bool FlowGraphOptimizer::TryInlineInt32x4Method( | 3513 bool FlowGraphOptimizer::TryInlineInt32x4Method( |
(...skipping 15 matching lines...) Expand all Loading... |
3443 ASSERT(call->ic_data()->HasOneTarget()); | 3529 ASSERT(call->ic_data()->HasOneTarget()); |
3444 return InlineInt32x4Getter(call, recognized_kind); | 3530 return InlineInt32x4Getter(call, recognized_kind); |
3445 | 3531 |
3446 case MethodRecognizer::kInt32x4Select: { | 3532 case MethodRecognizer::kInt32x4Select: { |
3447 Definition* mask = call->ArgumentAt(0); | 3533 Definition* mask = call->ArgumentAt(0); |
3448 Definition* trueValue = call->ArgumentAt(1); | 3534 Definition* trueValue = call->ArgumentAt(1); |
3449 Definition* falseValue = call->ArgumentAt(2); | 3535 Definition* falseValue = call->ArgumentAt(2); |
3450 // Type check left. | 3536 // Type check left. |
3451 AddCheckClass(mask, | 3537 AddCheckClass(mask, |
3452 ICData::ZoneHandle( | 3538 ICData::ZoneHandle( |
| 3539 isolate(), |
3453 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 3540 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3454 call->deopt_id(), | 3541 call->deopt_id(), |
3455 call->env(), | 3542 call->env(), |
3456 call); | 3543 call); |
3457 Int32x4SelectInstr* select = new Int32x4SelectInstr( | 3544 Int32x4SelectInstr* select = new(isolate()) Int32x4SelectInstr( |
3458 new Value(mask), | 3545 new(isolate()) Value(mask), |
3459 new Value(trueValue), | 3546 new(isolate()) Value(trueValue), |
3460 new Value(falseValue), | 3547 new(isolate()) Value(falseValue), |
3461 call->deopt_id()); | 3548 call->deopt_id()); |
3462 ReplaceCall(call, select); | 3549 ReplaceCall(call, select); |
3463 return true; | 3550 return true; |
3464 } | 3551 } |
3465 case MethodRecognizer::kInt32x4WithFlagX: | 3552 case MethodRecognizer::kInt32x4WithFlagX: |
3466 case MethodRecognizer::kInt32x4WithFlagY: | 3553 case MethodRecognizer::kInt32x4WithFlagY: |
3467 case MethodRecognizer::kInt32x4WithFlagZ: | 3554 case MethodRecognizer::kInt32x4WithFlagZ: |
3468 case MethodRecognizer::kInt32x4WithFlagW: { | 3555 case MethodRecognizer::kInt32x4WithFlagW: { |
3469 Definition* left = call->ArgumentAt(0); | 3556 Definition* left = call->ArgumentAt(0); |
3470 Definition* flag = call->ArgumentAt(1); | 3557 Definition* flag = call->ArgumentAt(1); |
3471 // Type check left. | 3558 // Type check left. |
3472 AddCheckClass(left, | 3559 AddCheckClass(left, |
3473 ICData::ZoneHandle( | 3560 ICData::ZoneHandle( |
| 3561 isolate(), |
3474 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 3562 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
3475 call->deopt_id(), | 3563 call->deopt_id(), |
3476 call->env(), | 3564 call->env(), |
3477 call); | 3565 call); |
3478 Int32x4SetFlagInstr* setFlag = new Int32x4SetFlagInstr( | 3566 Int32x4SetFlagInstr* setFlag = new(isolate()) Int32x4SetFlagInstr( |
3479 recognized_kind, | 3567 recognized_kind, |
3480 new Value(left), | 3568 new(isolate()) Value(left), |
3481 new Value(flag), | 3569 new(isolate()) Value(flag), |
3482 call->deopt_id()); | 3570 call->deopt_id()); |
3483 ReplaceCall(call, setFlag); | 3571 ReplaceCall(call, setFlag); |
3484 return true; | 3572 return true; |
3485 } | 3573 } |
3486 default: | 3574 default: |
3487 return false; | 3575 return false; |
3488 } | 3576 } |
3489 } | 3577 } |
3490 | 3578 |
3491 | 3579 |
3492 bool FlowGraphOptimizer::InlineByteArrayViewLoad(Instruction* call, | 3580 bool FlowGraphOptimizer::InlineByteArrayViewLoad(Instruction* call, |
3493 Definition* receiver, | 3581 Definition* receiver, |
3494 intptr_t array_cid, | 3582 intptr_t array_cid, |
3495 intptr_t view_cid, | 3583 intptr_t view_cid, |
3496 const ICData& ic_data, | 3584 const ICData& ic_data, |
3497 TargetEntryInstr** entry, | 3585 TargetEntryInstr** entry, |
3498 Definition** last) { | 3586 Definition** last) { |
3499 ASSERT(array_cid != kIllegalCid); | 3587 ASSERT(array_cid != kIllegalCid); |
3500 Definition* array = receiver; | 3588 Definition* array = receiver; |
3501 Definition* index = call->ArgumentAt(1); | 3589 Definition* index = call->ArgumentAt(1); |
3502 *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(), | 3590 *entry = new(isolate()) TargetEntryInstr(flow_graph()->allocate_block_id(), |
3503 call->GetBlock()->try_index()); | 3591 call->GetBlock()->try_index()); |
3504 (*entry)->InheritDeoptTarget(call); | 3592 (*entry)->InheritDeoptTarget(isolate(), call); |
3505 Instruction* cursor = *entry; | 3593 Instruction* cursor = *entry; |
3506 | 3594 |
3507 array_cid = PrepareInlineByteArrayViewOp(call, | 3595 array_cid = PrepareInlineByteArrayViewOp(call, |
3508 array_cid, | 3596 array_cid, |
3509 view_cid, | 3597 view_cid, |
3510 &array, | 3598 &array, |
3511 index, | 3599 index, |
3512 &cursor); | 3600 &cursor); |
3513 | 3601 |
3514 intptr_t deopt_id = Isolate::kNoDeoptId; | 3602 intptr_t deopt_id = Isolate::kNoDeoptId; |
3515 if ((array_cid == kTypedDataInt32ArrayCid) || | 3603 if ((array_cid == kTypedDataInt32ArrayCid) || |
3516 (array_cid == kTypedDataUint32ArrayCid)) { | 3604 (array_cid == kTypedDataUint32ArrayCid)) { |
3517 // Set deopt_id if we can optimistically assume that the result is Smi. | 3605 // Set deopt_id if we can optimistically assume that the result is Smi. |
3518 // Assume mixed Mint/Smi if this instruction caused deoptimization once. | 3606 // Assume mixed Mint/Smi if this instruction caused deoptimization once. |
3519 deopt_id = ic_data.HasDeoptReasons() ? | 3607 deopt_id = ic_data.HasDeoptReasons() ? |
3520 Isolate::kNoDeoptId : call->deopt_id(); | 3608 Isolate::kNoDeoptId : call->deopt_id(); |
3521 } | 3609 } |
3522 | 3610 |
3523 *last = new LoadIndexedInstr(new Value(array), | 3611 *last = new(isolate()) LoadIndexedInstr(new(isolate()) Value(array), |
3524 new Value(index), | 3612 new(isolate()) Value(index), |
3525 1, | 3613 1, |
3526 view_cid, | 3614 view_cid, |
3527 deopt_id, | 3615 deopt_id, |
3528 call->token_pos()); | 3616 call->token_pos()); |
3529 cursor = flow_graph()->AppendTo( | 3617 cursor = flow_graph()->AppendTo( |
3530 cursor, | 3618 cursor, |
3531 *last, | 3619 *last, |
3532 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 3620 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
3533 FlowGraph::kValue); | 3621 FlowGraph::kValue); |
3534 | 3622 |
3535 if (view_cid == kTypedDataFloat32ArrayCid) { | 3623 if (view_cid == kTypedDataFloat32ArrayCid) { |
3536 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); | 3624 *last = new(isolate()) FloatToDoubleInstr( |
| 3625 new(isolate()) Value(*last), deopt_id); |
3537 flow_graph()->AppendTo(cursor, | 3626 flow_graph()->AppendTo(cursor, |
3538 *last, | 3627 *last, |
3539 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 3628 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
3540 FlowGraph::kValue); | 3629 FlowGraph::kValue); |
3541 } | 3630 } |
3542 return true; | 3631 return true; |
3543 } | 3632 } |
3544 | 3633 |
3545 | 3634 |
3546 bool FlowGraphOptimizer::InlineByteArrayViewStore(const Function& target, | 3635 bool FlowGraphOptimizer::InlineByteArrayViewStore(const Function& target, |
3547 Instruction* call, | 3636 Instruction* call, |
3548 Definition* receiver, | 3637 Definition* receiver, |
3549 intptr_t array_cid, | 3638 intptr_t array_cid, |
3550 intptr_t view_cid, | 3639 intptr_t view_cid, |
3551 const ICData& ic_data, | 3640 const ICData& ic_data, |
3552 TargetEntryInstr** entry, | 3641 TargetEntryInstr** entry, |
3553 Definition** last) { | 3642 Definition** last) { |
3554 ASSERT(array_cid != kIllegalCid); | 3643 ASSERT(array_cid != kIllegalCid); |
3555 Definition* array = receiver; | 3644 Definition* array = receiver; |
3556 Definition* index = call->ArgumentAt(1); | 3645 Definition* index = call->ArgumentAt(1); |
3557 *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(), | 3646 *entry = new(isolate()) TargetEntryInstr(flow_graph()->allocate_block_id(), |
3558 call->GetBlock()->try_index()); | 3647 call->GetBlock()->try_index()); |
3559 (*entry)->InheritDeoptTarget(call); | 3648 (*entry)->InheritDeoptTarget(isolate(), call); |
3560 Instruction* cursor = *entry; | 3649 Instruction* cursor = *entry; |
3561 | 3650 |
3562 array_cid = PrepareInlineByteArrayViewOp(call, | 3651 array_cid = PrepareInlineByteArrayViewOp(call, |
3563 array_cid, | 3652 array_cid, |
3564 view_cid, | 3653 view_cid, |
3565 &array, | 3654 &array, |
3566 index, | 3655 index, |
3567 &cursor); | 3656 &cursor); |
3568 | 3657 |
3569 // Extract the instance call so we can use the function_name in the stored | 3658 // Extract the instance call so we can use the function_name in the stored |
3570 // value check ICData. | 3659 // value check ICData. |
3571 InstanceCallInstr* i_call = NULL; | 3660 InstanceCallInstr* i_call = NULL; |
3572 if (call->IsPolymorphicInstanceCall()) { | 3661 if (call->IsPolymorphicInstanceCall()) { |
3573 i_call = call->AsPolymorphicInstanceCall()->instance_call(); | 3662 i_call = call->AsPolymorphicInstanceCall()->instance_call(); |
3574 } else { | 3663 } else { |
3575 ASSERT(call->IsInstanceCall()); | 3664 ASSERT(call->IsInstanceCall()); |
3576 i_call = call->AsInstanceCall(); | 3665 i_call = call->AsInstanceCall(); |
3577 } | 3666 } |
3578 ASSERT(i_call != NULL); | 3667 ASSERT(i_call != NULL); |
3579 ICData& value_check = ICData::ZoneHandle(); | 3668 ICData& value_check = ICData::ZoneHandle(isolate(), ICData::null()); |
3580 switch (view_cid) { | 3669 switch (view_cid) { |
3581 case kTypedDataInt8ArrayCid: | 3670 case kTypedDataInt8ArrayCid: |
3582 case kTypedDataUint8ArrayCid: | 3671 case kTypedDataUint8ArrayCid: |
3583 case kTypedDataUint8ClampedArrayCid: | 3672 case kTypedDataUint8ClampedArrayCid: |
3584 case kExternalTypedDataUint8ArrayCid: | 3673 case kExternalTypedDataUint8ArrayCid: |
3585 case kExternalTypedDataUint8ClampedArrayCid: | 3674 case kExternalTypedDataUint8ClampedArrayCid: |
3586 case kTypedDataInt16ArrayCid: | 3675 case kTypedDataInt16ArrayCid: |
3587 case kTypedDataUint16ArrayCid: { | 3676 case kTypedDataUint16ArrayCid: { |
3588 // Check that value is always smi. | 3677 // Check that value is always smi. |
3589 value_check = ICData::New(flow_graph_->parsed_function().function(), | 3678 value_check = ICData::New(flow_graph_->parsed_function().function(), |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3644 UNREACHABLE(); | 3733 UNREACHABLE(); |
3645 } | 3734 } |
3646 | 3735 |
3647 Definition* stored_value = call->ArgumentAt(2); | 3736 Definition* stored_value = call->ArgumentAt(2); |
3648 if (!value_check.IsNull()) { | 3737 if (!value_check.IsNull()) { |
3649 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), | 3738 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), |
3650 call); | 3739 call); |
3651 } | 3740 } |
3652 | 3741 |
3653 if (view_cid == kTypedDataFloat32ArrayCid) { | 3742 if (view_cid == kTypedDataFloat32ArrayCid) { |
3654 stored_value = | 3743 stored_value = new(isolate()) DoubleToFloatInstr( |
3655 new DoubleToFloatInstr(new Value(stored_value), call->deopt_id()); | 3744 new(isolate()) Value(stored_value), call->deopt_id()); |
3656 cursor = flow_graph()->AppendTo(cursor, | 3745 cursor = flow_graph()->AppendTo(cursor, |
3657 stored_value, | 3746 stored_value, |
3658 NULL, | 3747 NULL, |
3659 FlowGraph::kValue); | 3748 FlowGraph::kValue); |
3660 } | 3749 } |
3661 | 3750 |
3662 StoreBarrierType needs_store_barrier = kNoStoreBarrier; | 3751 StoreBarrierType needs_store_barrier = kNoStoreBarrier; |
3663 *last = new StoreIndexedInstr(new Value(array), | 3752 *last = new(isolate()) StoreIndexedInstr(new(isolate()) Value(array), |
3664 new Value(index), | 3753 new(isolate()) Value(index), |
3665 new Value(stored_value), | 3754 new(isolate()) Value(stored_value), |
3666 needs_store_barrier, | 3755 needs_store_barrier, |
3667 1, // Index scale | 3756 1, // Index scale |
3668 view_cid, | 3757 view_cid, |
3669 call->deopt_id(), | 3758 call->deopt_id(), |
3670 call->token_pos()); | 3759 call->token_pos()); |
3671 | 3760 |
3672 flow_graph()->AppendTo(cursor, | 3761 flow_graph()->AppendTo(cursor, |
3673 *last, | 3762 *last, |
3674 call->deopt_id() != Isolate::kNoDeoptId ? | 3763 call->deopt_id() != Isolate::kNoDeoptId ? |
3675 call->env() : NULL, | 3764 call->env() : NULL, |
3676 FlowGraph::kEffect); | 3765 FlowGraph::kEffect); |
3677 return true; | 3766 return true; |
3678 } | 3767 } |
3679 | 3768 |
3680 | 3769 |
3681 | 3770 |
3682 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp( | 3771 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp( |
3683 Instruction* call, | 3772 Instruction* call, |
3684 intptr_t array_cid, | 3773 intptr_t array_cid, |
3685 intptr_t view_cid, | 3774 intptr_t view_cid, |
3686 Definition** array, | 3775 Definition** array, |
3687 Definition* byte_index, | 3776 Definition* byte_index, |
3688 Instruction** cursor) { | 3777 Instruction** cursor) { |
3689 // Insert byte_index smi check. | 3778 // Insert byte_index smi check. |
3690 *cursor = flow_graph()->AppendTo(*cursor, | 3779 *cursor = flow_graph()->AppendTo(*cursor, |
3691 new CheckSmiInstr(new Value(byte_index), | 3780 new(isolate()) CheckSmiInstr( |
3692 call->deopt_id(), | 3781 new(isolate()) Value(byte_index), |
3693 call->token_pos()), | 3782 call->deopt_id(), |
| 3783 call->token_pos()), |
3694 call->env(), | 3784 call->env(), |
3695 FlowGraph::kEffect); | 3785 FlowGraph::kEffect); |
3696 | 3786 |
3697 LoadFieldInstr* length = | 3787 LoadFieldInstr* length = |
3698 new LoadFieldInstr(new Value(*array), | 3788 new(isolate()) LoadFieldInstr( |
3699 CheckArrayBoundInstr::LengthOffsetFor(array_cid), | 3789 new(isolate()) Value(*array), |
3700 Type::ZoneHandle(Type::SmiType()), | 3790 CheckArrayBoundInstr::LengthOffsetFor(array_cid), |
3701 call->token_pos()); | 3791 Type::ZoneHandle(isolate(), Type::SmiType()), |
| 3792 call->token_pos()); |
3702 length->set_is_immutable(true); | 3793 length->set_is_immutable(true); |
3703 length->set_result_cid(kSmiCid); | 3794 length->set_result_cid(kSmiCid); |
3704 length->set_recognized_kind( | 3795 length->set_recognized_kind( |
3705 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); | 3796 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); |
3706 *cursor = flow_graph()->AppendTo(*cursor, | 3797 *cursor = flow_graph()->AppendTo(*cursor, |
3707 length, | 3798 length, |
3708 NULL, | 3799 NULL, |
3709 FlowGraph::kValue); | 3800 FlowGraph::kValue); |
3710 | 3801 |
3711 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(array_cid); | 3802 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(array_cid); |
3712 ConstantInstr* bytes_per_element = | 3803 ConstantInstr* bytes_per_element = |
3713 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size))); | 3804 flow_graph()->GetConstant(Smi::Handle(isolate(), Smi::New(element_size))); |
3714 BinarySmiOpInstr* len_in_bytes = | 3805 BinarySmiOpInstr* len_in_bytes = |
3715 new BinarySmiOpInstr(Token::kMUL, | 3806 new(isolate()) BinarySmiOpInstr(Token::kMUL, |
3716 new Value(length), | 3807 new(isolate()) Value(length), |
3717 new Value(bytes_per_element), | 3808 new(isolate()) Value(bytes_per_element), |
3718 call->deopt_id(), call->token_pos()); | 3809 call->deopt_id(), call->token_pos()); |
3719 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(), | 3810 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(), |
3720 FlowGraph::kValue); | 3811 FlowGraph::kValue); |
3721 | 3812 |
3722 ConstantInstr* length_adjustment = | 3813 ConstantInstr* length_adjustment = |
3723 flow_graph()->GetConstant(Smi::Handle(Smi::New( | 3814 flow_graph()->GetConstant(Smi::Handle(isolate(), Smi::New( |
3724 FlowGraphCompiler::ElementSizeFor(view_cid) - 1))); | 3815 FlowGraphCompiler::ElementSizeFor(view_cid) - 1))); |
3725 // adjusted_length = len_in_bytes - (element_size - 1). | 3816 // adjusted_length = len_in_bytes - (element_size - 1). |
3726 BinarySmiOpInstr* adjusted_length = | 3817 BinarySmiOpInstr* adjusted_length = |
3727 new BinarySmiOpInstr(Token::kSUB, | 3818 new(isolate()) BinarySmiOpInstr(Token::kSUB, |
3728 new Value(len_in_bytes), | 3819 new(isolate()) Value(len_in_bytes), |
3729 new Value(length_adjustment), | 3820 new(isolate()) Value(length_adjustment), |
3730 call->deopt_id(), call->token_pos()); | 3821 call->deopt_id(), call->token_pos()); |
3731 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(), | 3822 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(), |
3732 FlowGraph::kValue); | 3823 FlowGraph::kValue); |
3733 | 3824 |
3734 // Check adjusted_length > 0. | 3825 // Check adjusted_length > 0. |
3735 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0))); | 3826 ConstantInstr* zero = |
| 3827 flow_graph()->GetConstant(Smi::Handle(isolate(), Smi::New(0))); |
3736 *cursor = flow_graph()->AppendTo(*cursor, | 3828 *cursor = flow_graph()->AppendTo(*cursor, |
3737 new CheckArrayBoundInstr( | 3829 new(isolate()) CheckArrayBoundInstr( |
3738 new Value(adjusted_length), | 3830 new(isolate()) Value(adjusted_length), |
3739 new Value(zero), | 3831 new(isolate()) Value(zero), |
3740 call->deopt_id()), | 3832 call->deopt_id()), |
3741 call->env(), | 3833 call->env(), |
3742 FlowGraph::kEffect); | 3834 FlowGraph::kEffect); |
3743 // Check 0 <= byte_index < adjusted_length. | 3835 // Check 0 <= byte_index < adjusted_length. |
3744 *cursor = flow_graph()->AppendTo(*cursor, | 3836 *cursor = flow_graph()->AppendTo(*cursor, |
3745 new CheckArrayBoundInstr( | 3837 new(isolate()) CheckArrayBoundInstr( |
3746 new Value(adjusted_length), | 3838 new(isolate()) Value(adjusted_length), |
3747 new Value(byte_index), | 3839 new(isolate()) Value(byte_index), |
3748 call->deopt_id()), | 3840 call->deopt_id()), |
3749 call->env(), | 3841 call->env(), |
3750 FlowGraph::kEffect); | 3842 FlowGraph::kEffect); |
3751 | 3843 |
3752 if (RawObject::IsExternalTypedDataClassId(array_cid)) { | 3844 if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
3753 LoadUntaggedInstr* elements = | 3845 LoadUntaggedInstr* elements = |
3754 new LoadUntaggedInstr(new Value(*array), | 3846 new(isolate()) LoadUntaggedInstr(new(isolate()) Value(*array), |
3755 ExternalTypedData::data_offset()); | 3847 ExternalTypedData::data_offset()); |
3756 *cursor = flow_graph()->AppendTo(*cursor, | 3848 *cursor = flow_graph()->AppendTo(*cursor, |
3757 elements, | 3849 elements, |
3758 NULL, | 3850 NULL, |
3759 FlowGraph::kValue); | 3851 FlowGraph::kValue); |
3760 *array = elements; | 3852 *array = elements; |
3761 } | 3853 } |
3762 return array_cid; | 3854 return array_cid; |
3763 } | 3855 } |
3764 | 3856 |
3765 | 3857 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3803 // check. | 3895 // check. |
3804 RawBool* FlowGraphOptimizer::InstanceOfAsBool( | 3896 RawBool* FlowGraphOptimizer::InstanceOfAsBool( |
3805 const ICData& ic_data, | 3897 const ICData& ic_data, |
3806 const AbstractType& type, | 3898 const AbstractType& type, |
3807 ZoneGrowableArray<intptr_t>* results) const { | 3899 ZoneGrowableArray<intptr_t>* results) const { |
3808 ASSERT(results->is_empty()); | 3900 ASSERT(results->is_empty()); |
3809 ASSERT(ic_data.NumArgsTested() == 1); // Unary checks only. | 3901 ASSERT(ic_data.NumArgsTested() == 1); // Unary checks only. |
3810 if (!type.IsInstantiated() || type.IsMalformedOrMalbounded()) { | 3902 if (!type.IsInstantiated() || type.IsMalformedOrMalbounded()) { |
3811 return Bool::null(); | 3903 return Bool::null(); |
3812 } | 3904 } |
3813 const Class& type_class = Class::Handle(type.type_class()); | 3905 const Class& type_class = Class::Handle(isolate(), type.type_class()); |
3814 const intptr_t num_type_args = type_class.NumTypeArguments(); | 3906 const intptr_t num_type_args = type_class.NumTypeArguments(); |
3815 if (num_type_args > 0) { | 3907 if (num_type_args > 0) { |
3816 // Only raw types can be directly compared, thus disregarding type | 3908 // Only raw types can be directly compared, thus disregarding type |
3817 // arguments. | 3909 // arguments. |
3818 const intptr_t num_type_params = type_class.NumTypeParameters(); | 3910 const intptr_t num_type_params = type_class.NumTypeParameters(); |
3819 const intptr_t from_index = num_type_args - num_type_params; | 3911 const intptr_t from_index = num_type_args - num_type_params; |
3820 const TypeArguments& type_arguments = | 3912 const TypeArguments& type_arguments = |
3821 TypeArguments::Handle(type.arguments()); | 3913 TypeArguments::Handle(isolate(), type.arguments()); |
3822 const bool is_raw_type = type_arguments.IsNull() || | 3914 const bool is_raw_type = type_arguments.IsNull() || |
3823 type_arguments.IsRaw(from_index, num_type_params); | 3915 type_arguments.IsRaw(from_index, num_type_params); |
3824 if (!is_raw_type) { | 3916 if (!is_raw_type) { |
3825 // Unknown result. | 3917 // Unknown result. |
3826 return Bool::null(); | 3918 return Bool::null(); |
3827 } | 3919 } |
3828 } | 3920 } |
3829 | 3921 |
3830 const ClassTable& class_table = *Isolate::Current()->class_table(); | 3922 const ClassTable& class_table = *isolate()->class_table(); |
3831 Bool& prev = Bool::Handle(); | 3923 Bool& prev = Bool::Handle(isolate(), Bool::null()); |
3832 Class& cls = Class::Handle(); | 3924 Class& cls = Class::Handle(isolate(), Class::null()); |
3833 | 3925 |
3834 bool results_differ = false; | 3926 bool results_differ = false; |
3835 for (int i = 0; i < ic_data.NumberOfChecks(); i++) { | 3927 for (int i = 0; i < ic_data.NumberOfChecks(); i++) { |
3836 cls = class_table.At(ic_data.GetReceiverClassIdAt(i)); | 3928 cls = class_table.At(ic_data.GetReceiverClassIdAt(i)); |
3837 if (cls.NumTypeArguments() > 0) { | 3929 if (cls.NumTypeArguments() > 0) { |
3838 return Bool::null(); | 3930 return Bool::null(); |
3839 } | 3931 } |
3840 const bool is_subtype = cls.IsSubtypeOf(TypeArguments::Handle(), | 3932 const bool is_subtype = cls.IsSubtypeOf( |
3841 type_class, | 3933 TypeArguments::Handle(isolate(), TypeArguments::null()), |
3842 TypeArguments::Handle(), | 3934 type_class, |
3843 NULL); | 3935 TypeArguments::Handle(isolate(), TypeArguments::null()), |
| 3936 NULL); |
3844 results->Add(cls.id()); | 3937 results->Add(cls.id()); |
3845 results->Add(is_subtype); | 3938 results->Add(is_subtype); |
3846 if (prev.IsNull()) { | 3939 if (prev.IsNull()) { |
3847 prev = Bool::Get(is_subtype).raw(); | 3940 prev = Bool::Get(is_subtype).raw(); |
3848 } else { | 3941 } else { |
3849 if (is_subtype != prev.value()) { | 3942 if (is_subtype != prev.value()) { |
3850 results_differ = true; | 3943 results_differ = true; |
3851 } | 3944 } |
3852 } | 3945 } |
3853 } | 3946 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3944 void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { | 4037 void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { |
3945 ASSERT(Token::IsTypeTestOperator(call->token_kind())); | 4038 ASSERT(Token::IsTypeTestOperator(call->token_kind())); |
3946 Definition* left = call->ArgumentAt(0); | 4039 Definition* left = call->ArgumentAt(0); |
3947 Definition* instantiator = call->ArgumentAt(1); | 4040 Definition* instantiator = call->ArgumentAt(1); |
3948 Definition* type_args = call->ArgumentAt(2); | 4041 Definition* type_args = call->ArgumentAt(2); |
3949 const AbstractType& type = | 4042 const AbstractType& type = |
3950 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); | 4043 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); |
3951 const bool negate = Bool::Cast( | 4044 const bool negate = Bool::Cast( |
3952 call->ArgumentAt(4)->OriginalDefinition()->AsConstant()->value()).value(); | 4045 call->ArgumentAt(4)->OriginalDefinition()->AsConstant()->value()).value(); |
3953 const ICData& unary_checks = | 4046 const ICData& unary_checks = |
3954 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); | 4047 ICData::ZoneHandle(isolate(), call->ic_data()->AsUnaryClassChecks()); |
3955 if (FLAG_warn_on_javascript_compatibility && | 4048 if (FLAG_warn_on_javascript_compatibility && |
3956 !unary_checks.IssuedJSWarning() && | 4049 !unary_checks.IssuedJSWarning() && |
3957 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { | 4050 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { |
3958 // No warning was reported yet for this type check, either because it has | 4051 // No warning was reported yet for this type check, either because it has |
3959 // not been executed yet, or because no problematic combinations of instance | 4052 // not been executed yet, or because no problematic combinations of instance |
3960 // type and test type have been encountered so far. A warning may still be | 4053 // type and test type have been encountered so far. A warning may still be |
3961 // reported, so do not replace the instance call. | 4054 // reported, so do not replace the instance call. |
3962 return; | 4055 return; |
3963 } | 4056 } |
3964 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { | 4057 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { |
3965 ZoneGrowableArray<intptr_t>* results = | 4058 ZoneGrowableArray<intptr_t>* results = |
3966 new ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); | 4059 new(isolate()) ZoneGrowableArray<intptr_t>( |
| 4060 unary_checks.NumberOfChecks() * 2); |
3967 Bool& as_bool = | 4061 Bool& as_bool = |
3968 Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type, results)); | 4062 Bool::ZoneHandle(isolate(), |
| 4063 InstanceOfAsBool(unary_checks, type, results)); |
3969 if (as_bool.IsNull()) { | 4064 if (as_bool.IsNull()) { |
3970 if (results->length() == unary_checks.NumberOfChecks() * 2) { | 4065 if (results->length() == unary_checks.NumberOfChecks() * 2) { |
3971 const bool can_deopt = TryExpandTestCidsResult(results, type); | 4066 const bool can_deopt = TryExpandTestCidsResult(results, type); |
3972 TestCidsInstr* test_cids = new TestCidsInstr( | 4067 TestCidsInstr* test_cids = new(isolate()) TestCidsInstr( |
3973 call->token_pos(), | 4068 call->token_pos(), |
3974 negate ? Token::kISNOT : Token::kIS, | 4069 negate ? Token::kISNOT : Token::kIS, |
3975 new Value(left), | 4070 new(isolate()) Value(left), |
3976 *results, | 4071 *results, |
3977 can_deopt ? call->deopt_id() : Isolate::kNoDeoptId); | 4072 can_deopt ? call->deopt_id() : Isolate::kNoDeoptId); |
3978 // Remove type. | 4073 // Remove type. |
3979 ReplaceCall(call, test_cids); | 4074 ReplaceCall(call, test_cids); |
3980 return; | 4075 return; |
3981 } | 4076 } |
3982 } else { | 4077 } else { |
3983 // TODO(srdjan): Use TestCidsInstr also for this case. | 4078 // TODO(srdjan): Use TestCidsInstr also for this case. |
3984 // One result only. | 4079 // One result only. |
3985 AddReceiverCheck(call); | 4080 AddReceiverCheck(call); |
3986 if (negate) { | 4081 if (negate) { |
3987 as_bool = Bool::Get(!as_bool.value()).raw(); | 4082 as_bool = Bool::Get(!as_bool.value()).raw(); |
3988 } | 4083 } |
3989 ConstantInstr* bool_const = flow_graph()->GetConstant(as_bool); | 4084 ConstantInstr* bool_const = flow_graph()->GetConstant(as_bool); |
3990 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 4085 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
3991 PushArgumentInstr* push = call->PushArgumentAt(i); | 4086 PushArgumentInstr* push = call->PushArgumentAt(i); |
3992 push->ReplaceUsesWith(push->value()->definition()); | 4087 push->ReplaceUsesWith(push->value()->definition()); |
3993 push->RemoveFromGraph(); | 4088 push->RemoveFromGraph(); |
3994 } | 4089 } |
3995 call->ReplaceUsesWith(bool_const); | 4090 call->ReplaceUsesWith(bool_const); |
3996 ASSERT(current_iterator()->Current() == call); | 4091 ASSERT(current_iterator()->Current() == call); |
3997 current_iterator()->RemoveCurrentFromGraph(); | 4092 current_iterator()->RemoveCurrentFromGraph(); |
3998 return; | 4093 return; |
3999 } | 4094 } |
4000 } | 4095 } |
4001 | 4096 |
4002 if (TypeCheckAsClassEquality(type)) { | 4097 if (TypeCheckAsClassEquality(type)) { |
4003 LoadClassIdInstr* left_cid = new LoadClassIdInstr(new Value(left)); | 4098 LoadClassIdInstr* left_cid = |
| 4099 new(isolate()) LoadClassIdInstr(new(isolate()) Value(left)); |
4004 InsertBefore(call, | 4100 InsertBefore(call, |
4005 left_cid, | 4101 left_cid, |
4006 NULL, | 4102 NULL, |
4007 FlowGraph::kValue); | 4103 FlowGraph::kValue); |
4008 const intptr_t type_cid = Class::Handle(type.type_class()).id(); | 4104 const intptr_t type_cid = Class::Handle(isolate(), type.type_class()).id(); |
4009 ConstantInstr* cid = | 4105 ConstantInstr* cid = |
4010 flow_graph()->GetConstant(Smi::Handle(Smi::New(type_cid))); | 4106 flow_graph()->GetConstant(Smi::Handle(isolate(), Smi::New(type_cid))); |
4011 | 4107 |
4012 StrictCompareInstr* check_cid = | 4108 StrictCompareInstr* check_cid = |
4013 new StrictCompareInstr(call->token_pos(), | 4109 new(isolate()) StrictCompareInstr( |
4014 negate ? Token::kNE_STRICT : Token::kEQ_STRICT, | 4110 call->token_pos(), |
4015 new Value(left_cid), | 4111 negate ? Token::kNE_STRICT : Token::kEQ_STRICT, |
4016 new Value(cid), | 4112 new(isolate()) Value(left_cid), |
4017 false); // No number check. | 4113 new(isolate()) Value(cid), |
| 4114 false); // No number check. |
4018 ReplaceCall(call, check_cid); | 4115 ReplaceCall(call, check_cid); |
4019 return; | 4116 return; |
4020 } | 4117 } |
4021 | 4118 |
4022 InstanceOfInstr* instance_of = | 4119 InstanceOfInstr* instance_of = |
4023 new InstanceOfInstr(call->token_pos(), | 4120 new(isolate()) InstanceOfInstr(call->token_pos(), |
4024 new Value(left), | 4121 new(isolate()) Value(left), |
4025 new Value(instantiator), | 4122 new(isolate()) Value(instantiator), |
4026 new Value(type_args), | 4123 new(isolate()) Value(type_args), |
4027 type, | 4124 type, |
4028 negate, | 4125 negate, |
4029 call->deopt_id()); | 4126 call->deopt_id()); |
4030 ReplaceCall(call, instance_of); | 4127 ReplaceCall(call, instance_of); |
4031 } | 4128 } |
4032 | 4129 |
4033 | 4130 |
4034 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). | 4131 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). |
4035 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { | 4132 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { |
4036 ASSERT(Token::IsTypeCastOperator(call->token_kind())); | 4133 ASSERT(Token::IsTypeCastOperator(call->token_kind())); |
4037 Definition* left = call->ArgumentAt(0); | 4134 Definition* left = call->ArgumentAt(0); |
4038 Definition* instantiator = call->ArgumentAt(1); | 4135 Definition* instantiator = call->ArgumentAt(1); |
4039 Definition* type_args = call->ArgumentAt(2); | 4136 Definition* type_args = call->ArgumentAt(2); |
4040 const AbstractType& type = | 4137 const AbstractType& type = |
4041 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); | 4138 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); |
4042 ASSERT(!type.IsMalformedOrMalbounded()); | 4139 ASSERT(!type.IsMalformedOrMalbounded()); |
4043 const ICData& unary_checks = | 4140 const ICData& unary_checks = |
4044 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); | 4141 ICData::ZoneHandle(isolate(), call->ic_data()->AsUnaryClassChecks()); |
4045 if (FLAG_warn_on_javascript_compatibility && | 4142 if (FLAG_warn_on_javascript_compatibility && |
4046 !unary_checks.IssuedJSWarning() && | 4143 !unary_checks.IssuedJSWarning() && |
4047 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { | 4144 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { |
4048 // No warning was reported yet for this type check, either because it has | 4145 // No warning was reported yet for this type check, either because it has |
4049 // not been executed yet, or because no problematic combinations of instance | 4146 // not been executed yet, or because no problematic combinations of instance |
4050 // type and test type have been encountered so far. A warning may still be | 4147 // type and test type have been encountered so far. A warning may still be |
4051 // reported, so do not replace the instance call. | 4148 // reported, so do not replace the instance call. |
4052 return; | 4149 return; |
4053 } | 4150 } |
4054 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { | 4151 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { |
4055 ZoneGrowableArray<intptr_t>* results = | 4152 ZoneGrowableArray<intptr_t>* results = |
4056 new ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); | 4153 new(isolate()) ZoneGrowableArray<intptr_t>( |
4057 const Bool& as_bool = | 4154 unary_checks.NumberOfChecks() * 2); |
4058 Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type, results)); | 4155 const Bool& as_bool = Bool::ZoneHandle(isolate(), |
| 4156 InstanceOfAsBool(unary_checks, type, results)); |
4059 if (as_bool.raw() == Bool::True().raw()) { | 4157 if (as_bool.raw() == Bool::True().raw()) { |
4060 AddReceiverCheck(call); | 4158 AddReceiverCheck(call); |
4061 // Remove the original push arguments. | 4159 // Remove the original push arguments. |
4062 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 4160 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
4063 PushArgumentInstr* push = call->PushArgumentAt(i); | 4161 PushArgumentInstr* push = call->PushArgumentAt(i); |
4064 push->ReplaceUsesWith(push->value()->definition()); | 4162 push->ReplaceUsesWith(push->value()->definition()); |
4065 push->RemoveFromGraph(); | 4163 push->RemoveFromGraph(); |
4066 } | 4164 } |
4067 // Remove call, replace it with 'left'. | 4165 // Remove call, replace it with 'left'. |
4068 call->ReplaceUsesWith(left); | 4166 call->ReplaceUsesWith(left); |
4069 ASSERT(current_iterator()->Current() == call); | 4167 ASSERT(current_iterator()->Current() == call); |
4070 current_iterator()->RemoveCurrentFromGraph(); | 4168 current_iterator()->RemoveCurrentFromGraph(); |
4071 return; | 4169 return; |
4072 } | 4170 } |
4073 } | 4171 } |
4074 const String& dst_name = String::ZoneHandle( | 4172 const String& dst_name = String::ZoneHandle(isolate(), |
4075 Symbols::New(Exceptions::kCastErrorDstName)); | 4173 Symbols::New(Exceptions::kCastErrorDstName)); |
4076 AssertAssignableInstr* assert_as = | 4174 AssertAssignableInstr* assert_as = |
4077 new AssertAssignableInstr(call->token_pos(), | 4175 new(isolate()) AssertAssignableInstr(call->token_pos(), |
4078 new Value(left), | 4176 new(isolate()) Value(left), |
4079 new Value(instantiator), | 4177 new(isolate()) Value(instantiator), |
4080 new Value(type_args), | 4178 new(isolate()) Value(type_args), |
4081 type, | 4179 type, |
4082 dst_name); | 4180 dst_name); |
4083 // Newly inserted instructions that can deoptimize or throw an exception | 4181 // Newly inserted instructions that can deoptimize or throw an exception |
4084 // must have a deoptimization id that is valid for lookup in the unoptimized | 4182 // must have a deoptimization id that is valid for lookup in the unoptimized |
4085 // code. | 4183 // code. |
4086 assert_as->deopt_id_ = call->deopt_id(); | 4184 assert_as->deopt_id_ = call->deopt_id(); |
4087 ReplaceCall(call, assert_as); | 4185 ReplaceCall(call, assert_as); |
4088 } | 4186 } |
4089 | 4187 |
4090 | 4188 |
4091 // Tries to optimize instance call by replacing it with a faster instruction | 4189 // Tries to optimize instance call by replacing it with a faster instruction |
4092 // (e.g, binary op, field load, ..). | 4190 // (e.g, binary op, field load, ..). |
4093 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { | 4191 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
4094 if (!instr->HasICData() || (instr->ic_data()->NumberOfChecks() == 0)) { | 4192 if (!instr->HasICData() || (instr->ic_data()->NumberOfChecks() == 0)) { |
4095 return; | 4193 return; |
4096 } | 4194 } |
4097 | 4195 |
4098 const Token::Kind op_kind = instr->token_kind(); | 4196 const Token::Kind op_kind = instr->token_kind(); |
4099 // Type test is special as it always gets converted into inlined code. | 4197 // Type test is special as it always gets converted into inlined code. |
4100 if (Token::IsTypeTestOperator(op_kind)) { | 4198 if (Token::IsTypeTestOperator(op_kind)) { |
4101 ReplaceWithInstanceOf(instr); | 4199 ReplaceWithInstanceOf(instr); |
4102 return; | 4200 return; |
4103 } | 4201 } |
4104 | 4202 |
4105 if (Token::IsTypeCastOperator(op_kind)) { | 4203 if (Token::IsTypeCastOperator(op_kind)) { |
4106 ReplaceWithTypeCast(instr); | 4204 ReplaceWithTypeCast(instr); |
4107 return; | 4205 return; |
4108 } | 4206 } |
4109 | 4207 |
4110 const ICData& unary_checks = | 4208 const ICData& unary_checks = |
4111 ICData::ZoneHandle(instr->ic_data()->AsUnaryClassChecks()); | 4209 ICData::ZoneHandle(isolate(), instr->ic_data()->AsUnaryClassChecks()); |
4112 | 4210 |
4113 intptr_t max_checks = (op_kind == Token::kEQ) | 4211 intptr_t max_checks = (op_kind == Token::kEQ) |
4114 ? FLAG_max_equality_polymorphic_checks | 4212 ? FLAG_max_equality_polymorphic_checks |
4115 : FLAG_max_polymorphic_checks; | 4213 : FLAG_max_polymorphic_checks; |
4116 if ((unary_checks.NumberOfChecks() > max_checks) && | 4214 if ((unary_checks.NumberOfChecks() > max_checks) && |
4117 InstanceCallNeedsClassCheck(instr)) { | 4215 InstanceCallNeedsClassCheck(instr)) { |
4118 // Too many checks, it will be megamorphic which needs unary checks. | 4216 // Too many checks, it will be megamorphic which needs unary checks. |
4119 instr->set_ic_data(&unary_checks); | 4217 instr->set_ic_data(&unary_checks); |
4120 return; | 4218 return; |
4121 } | 4219 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4153 } | 4251 } |
4154 if (TryInlineInstanceMethod(instr)) { | 4252 if (TryInlineInstanceMethod(instr)) { |
4155 return; | 4253 return; |
4156 } | 4254 } |
4157 | 4255 |
4158 bool has_one_target = unary_checks.HasOneTarget(); | 4256 bool has_one_target = unary_checks.HasOneTarget(); |
4159 | 4257 |
4160 if (has_one_target) { | 4258 if (has_one_target) { |
4161 // Check if the single target is a polymorphic target, if it is, | 4259 // Check if the single target is a polymorphic target, if it is, |
4162 // we don't have one target. | 4260 // we don't have one target. |
4163 const Function& target = Function::Handle(unary_checks.GetTargetAt(0)); | 4261 const Function& target = |
| 4262 Function::Handle(isolate(), unary_checks.GetTargetAt(0)); |
4164 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); | 4263 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); |
4165 has_one_target = !polymorphic_target; | 4264 has_one_target = !polymorphic_target; |
4166 } | 4265 } |
4167 | 4266 |
4168 if (has_one_target) { | 4267 if (has_one_target) { |
4169 const bool is_method_extraction = | 4268 const bool is_method_extraction = |
4170 Function::Handle(unary_checks.GetTargetAt(0)).IsMethodExtractor(); | 4269 Function::Handle(isolate(), |
| 4270 unary_checks.GetTargetAt(0)).IsMethodExtractor(); |
4171 | 4271 |
4172 if ((is_method_extraction && !MethodExtractorNeedsClassCheck(instr)) || | 4272 if ((is_method_extraction && !MethodExtractorNeedsClassCheck(instr)) || |
4173 (!is_method_extraction && !InstanceCallNeedsClassCheck(instr))) { | 4273 (!is_method_extraction && !InstanceCallNeedsClassCheck(instr))) { |
4174 const bool call_with_checks = false; | 4274 const bool call_with_checks = false; |
4175 PolymorphicInstanceCallInstr* call = | 4275 PolymorphicInstanceCallInstr* call = |
4176 new PolymorphicInstanceCallInstr(instr, unary_checks, | 4276 new(isolate()) PolymorphicInstanceCallInstr(instr, unary_checks, |
4177 call_with_checks); | 4277 call_with_checks); |
4178 instr->ReplaceWith(call, current_iterator()); | 4278 instr->ReplaceWith(call, current_iterator()); |
4179 return; | 4279 return; |
4180 } | 4280 } |
4181 } | 4281 } |
4182 | 4282 |
4183 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { | 4283 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { |
4184 bool call_with_checks; | 4284 bool call_with_checks; |
4185 if (has_one_target) { | 4285 if (has_one_target) { |
4186 // Type propagation has not run yet, we cannot eliminate the check. | 4286 // Type propagation has not run yet, we cannot eliminate the check. |
4187 AddReceiverCheck(instr); | 4287 AddReceiverCheck(instr); |
4188 // Call can still deoptimize, do not detach environment from instr. | 4288 // Call can still deoptimize, do not detach environment from instr. |
4189 call_with_checks = false; | 4289 call_with_checks = false; |
4190 } else { | 4290 } else { |
4191 call_with_checks = true; | 4291 call_with_checks = true; |
4192 } | 4292 } |
4193 PolymorphicInstanceCallInstr* call = | 4293 PolymorphicInstanceCallInstr* call = |
4194 new PolymorphicInstanceCallInstr(instr, unary_checks, | 4294 new(isolate()) PolymorphicInstanceCallInstr(instr, unary_checks, |
4195 call_with_checks); | 4295 call_with_checks); |
4196 instr->ReplaceWith(call, current_iterator()); | 4296 instr->ReplaceWith(call, current_iterator()); |
4197 } | 4297 } |
4198 } | 4298 } |
4199 | 4299 |
4200 | 4300 |
4201 void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) { | 4301 void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) { |
4202 if (!CanUnboxDouble()) { | 4302 if (!CanUnboxDouble()) { |
4203 return; | 4303 return; |
4204 } | 4304 } |
4205 MethodRecognizer::Kind recognized_kind = | 4305 MethodRecognizer::Kind recognized_kind = |
4206 MethodRecognizer::RecognizeKind(call->function()); | 4306 MethodRecognizer::RecognizeKind(call->function()); |
4207 MathUnaryInstr::MathUnaryKind unary_kind; | 4307 MathUnaryInstr::MathUnaryKind unary_kind; |
4208 switch (recognized_kind) { | 4308 switch (recognized_kind) { |
4209 case MethodRecognizer::kMathSqrt: | 4309 case MethodRecognizer::kMathSqrt: |
4210 unary_kind = MathUnaryInstr::kSqrt; | 4310 unary_kind = MathUnaryInstr::kSqrt; |
4211 break; | 4311 break; |
4212 case MethodRecognizer::kMathSin: | 4312 case MethodRecognizer::kMathSin: |
4213 unary_kind = MathUnaryInstr::kSin; | 4313 unary_kind = MathUnaryInstr::kSin; |
4214 break; | 4314 break; |
4215 case MethodRecognizer::kMathCos: | 4315 case MethodRecognizer::kMathCos: |
4216 unary_kind = MathUnaryInstr::kCos; | 4316 unary_kind = MathUnaryInstr::kCos; |
4217 break; | 4317 break; |
4218 default: | 4318 default: |
4219 unary_kind = MathUnaryInstr::kIllegal; | 4319 unary_kind = MathUnaryInstr::kIllegal; |
4220 break; | 4320 break; |
4221 } | 4321 } |
4222 if (unary_kind != MathUnaryInstr::kIllegal) { | 4322 if (unary_kind != MathUnaryInstr::kIllegal) { |
4223 MathUnaryInstr* math_unary = | 4323 MathUnaryInstr* math_unary = |
4224 new MathUnaryInstr(unary_kind, | 4324 new(isolate()) MathUnaryInstr(unary_kind, |
4225 new Value(call->ArgumentAt(0)), | 4325 new(isolate()) Value(call->ArgumentAt(0)), |
4226 call->deopt_id()); | 4326 call->deopt_id()); |
4227 ReplaceCall(call, math_unary); | 4327 ReplaceCall(call, math_unary); |
4228 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) || | 4328 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) || |
4229 (recognized_kind == MethodRecognizer::kFloat32x4Splat) || | 4329 (recognized_kind == MethodRecognizer::kFloat32x4Splat) || |
4230 (recognized_kind == MethodRecognizer::kFloat32x4Constructor) || | 4330 (recognized_kind == MethodRecognizer::kFloat32x4Constructor) || |
4231 (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2)) { | 4331 (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2)) { |
4232 TryInlineFloat32x4Constructor(call, recognized_kind); | 4332 TryInlineFloat32x4Constructor(call, recognized_kind); |
4233 } else if ((recognized_kind == MethodRecognizer::kFloat64x2Constructor) || | 4333 } else if ((recognized_kind == MethodRecognizer::kFloat64x2Constructor) || |
4234 (recognized_kind == MethodRecognizer::kFloat64x2Zero) || | 4334 (recognized_kind == MethodRecognizer::kFloat64x2Zero) || |
4235 (recognized_kind == MethodRecognizer::kFloat64x2Splat) || | 4335 (recognized_kind == MethodRecognizer::kFloat64x2Splat) || |
4236 (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4)) { | 4336 (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4)) { |
(...skipping 18 matching lines...) Expand all Loading... |
4255 // being either doubles or smis. | 4355 // being either doubles or smis. |
4256 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { | 4356 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { |
4257 const ICData& ic_data = *call->ic_data(); | 4357 const ICData& ic_data = *call->ic_data(); |
4258 intptr_t result_cid = kIllegalCid; | 4358 intptr_t result_cid = kIllegalCid; |
4259 if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, kDoubleCid)) { | 4359 if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, kDoubleCid)) { |
4260 result_cid = kDoubleCid; | 4360 result_cid = kDoubleCid; |
4261 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { | 4361 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { |
4262 result_cid = kSmiCid; | 4362 result_cid = kSmiCid; |
4263 } | 4363 } |
4264 if (result_cid != kIllegalCid) { | 4364 if (result_cid != kIllegalCid) { |
4265 MathMinMaxInstr* min_max = new MathMinMaxInstr( | 4365 MathMinMaxInstr* min_max = new(isolate()) MathMinMaxInstr( |
4266 recognized_kind, | 4366 recognized_kind, |
4267 new Value(call->ArgumentAt(0)), | 4367 new(isolate()) Value(call->ArgumentAt(0)), |
4268 new Value(call->ArgumentAt(1)), | 4368 new(isolate()) Value(call->ArgumentAt(1)), |
4269 call->deopt_id(), | 4369 call->deopt_id(), |
4270 result_cid); | 4370 result_cid); |
4271 const ICData& unary_checks = | 4371 const ICData& unary_checks = |
4272 ICData::ZoneHandle(ic_data.AsUnaryClassChecks()); | 4372 ICData::ZoneHandle(isolate(), ic_data.AsUnaryClassChecks()); |
4273 AddCheckClass(min_max->left()->definition(), | 4373 AddCheckClass(min_max->left()->definition(), |
4274 unary_checks, | 4374 unary_checks, |
4275 call->deopt_id(), | 4375 call->deopt_id(), |
4276 call->env(), | 4376 call->env(), |
4277 call); | 4377 call); |
4278 AddCheckClass(min_max->right()->definition(), | 4378 AddCheckClass(min_max->right()->definition(), |
4279 unary_checks, | 4379 unary_checks, |
4280 call->deopt_id(), | 4380 call->deopt_id(), |
4281 call->env(), | 4381 call->env(), |
4282 call); | 4382 call); |
4283 ReplaceCall(call, min_max); | 4383 ReplaceCall(call, min_max); |
4284 } | 4384 } |
4285 } | 4385 } |
4286 } else if (recognized_kind == MethodRecognizer::kMathDoublePow) { | 4386 } else if (recognized_kind == MethodRecognizer::kMathDoublePow) { |
4287 // We know that first argument is double, the second is num. | 4387 // We know that first argument is double, the second is num. |
4288 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble | 4388 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble |
4289 // instructions contain type checks and conversions to double. | 4389 // instructions contain type checks and conversions to double. |
4290 ZoneGrowableArray<Value*>* args = | 4390 ZoneGrowableArray<Value*>* args = |
4291 new ZoneGrowableArray<Value*>(call->ArgumentCount()); | 4391 new(isolate()) ZoneGrowableArray<Value*>(call->ArgumentCount()); |
4292 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | 4392 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { |
4293 args->Add(new Value(call->ArgumentAt(i))); | 4393 args->Add(new(isolate()) Value(call->ArgumentAt(i))); |
4294 } | 4394 } |
4295 InvokeMathCFunctionInstr* invoke = | 4395 InvokeMathCFunctionInstr* invoke = |
4296 new InvokeMathCFunctionInstr(args, | 4396 new(isolate()) InvokeMathCFunctionInstr(args, |
4297 call->deopt_id(), | 4397 call->deopt_id(), |
4298 recognized_kind, | 4398 recognized_kind, |
4299 call->token_pos()); | 4399 call->token_pos()); |
4300 ReplaceCall(call, invoke); | 4400 ReplaceCall(call, invoke); |
4301 } else if (recognized_kind == MethodRecognizer::kObjectArrayConstructor) { | 4401 } else if (recognized_kind == MethodRecognizer::kObjectArrayConstructor) { |
4302 Value* type = new Value(call->ArgumentAt(0)); | 4402 Value* type = new(isolate()) Value(call->ArgumentAt(0)); |
4303 Value* num_elements = new Value(call->ArgumentAt(1)); | 4403 Value* num_elements = new(isolate()) Value(call->ArgumentAt(1)); |
4304 CreateArrayInstr* create_array = | 4404 CreateArrayInstr* create_array = |
4305 new CreateArrayInstr(call->token_pos(), type, num_elements); | 4405 new(isolate()) CreateArrayInstr(call->token_pos(), type, num_elements); |
4306 ReplaceCall(call, create_array); | 4406 ReplaceCall(call, create_array); |
4307 } else if (Library::PrivateCoreLibName(Symbols::ClassId()).Equals( | 4407 } else if (Library::PrivateCoreLibName(Symbols::ClassId()).Equals( |
4308 String::Handle(call->function().name()))) { | 4408 String::Handle(isolate(), call->function().name()))) { |
4309 // Check for core library get:_classId. | 4409 // Check for core library get:_classId. |
4310 intptr_t cid = Class::Handle(call->function().Owner()).id(); | 4410 intptr_t cid = Class::Handle(isolate(), call->function().Owner()).id(); |
4311 // Currently only implemented for a subset of classes. | 4411 // Currently only implemented for a subset of classes. |
4312 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || | 4412 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || |
4313 (cid == kExternalOneByteStringCid) || | 4413 (cid == kExternalOneByteStringCid) || |
4314 (cid == kGrowableObjectArrayCid) || | 4414 (cid == kGrowableObjectArrayCid) || |
4315 (cid == kImmutableArrayCid) || (cid == kArrayCid)); | 4415 (cid == kImmutableArrayCid) || (cid == kArrayCid)); |
4316 ConstantInstr* cid_instr = new ConstantInstr(Smi::Handle(Smi::New(cid))); | 4416 ConstantInstr* cid_instr = |
| 4417 new(isolate()) ConstantInstr(Smi::Handle(isolate(), Smi::New(cid))); |
4317 ReplaceCall(call, cid_instr); | 4418 ReplaceCall(call, cid_instr); |
4318 } else if (call->function().IsFactory()) { | 4419 } else if (call->function().IsFactory()) { |
4319 const Class& function_class = Class::Handle(call->function().Owner()); | 4420 const Class& function_class = |
| 4421 Class::Handle(isolate(), call->function().Owner()); |
4320 if ((function_class.library() == Library::CoreLibrary()) || | 4422 if ((function_class.library() == Library::CoreLibrary()) || |
4321 (function_class.library() == Library::TypedDataLibrary())) { | 4423 (function_class.library() == Library::TypedDataLibrary())) { |
4322 intptr_t cid = FactoryRecognizer::ResultCid(call->function()); | 4424 intptr_t cid = FactoryRecognizer::ResultCid(call->function()); |
4323 switch (cid) { | 4425 switch (cid) { |
4324 case kArrayCid: { | 4426 case kArrayCid: { |
4325 Value* type = new Value(call->ArgumentAt(0)); | 4427 Value* type = new(isolate()) Value(call->ArgumentAt(0)); |
4326 Value* num_elements = new Value(call->ArgumentAt(1)); | 4428 Value* num_elements = new(isolate()) Value(call->ArgumentAt(1)); |
4327 if (num_elements->BindsToConstant() && | 4429 if (num_elements->BindsToConstant() && |
4328 num_elements->BoundConstant().IsSmi()) { | 4430 num_elements->BoundConstant().IsSmi()) { |
4329 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); | 4431 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); |
4330 if (length >= 0 && length <= Array::kMaxElements) { | 4432 if (length >= 0 && length <= Array::kMaxElements) { |
4331 CreateArrayInstr* create_array = | 4433 CreateArrayInstr* create_array = |
4332 new CreateArrayInstr(call->token_pos(), type, num_elements); | 4434 new(isolate()) CreateArrayInstr( |
| 4435 call->token_pos(), type, num_elements); |
4333 ReplaceCall(call, create_array); | 4436 ReplaceCall(call, create_array); |
4334 } | 4437 } |
4335 } | 4438 } |
4336 } | 4439 } |
4337 default: | 4440 default: |
4338 break; | 4441 break; |
4339 } | 4442 } |
4340 } | 4443 } |
4341 } | 4444 } |
4342 } | 4445 } |
4343 | 4446 |
4344 | 4447 |
4345 void FlowGraphOptimizer::VisitStoreInstanceField( | 4448 void FlowGraphOptimizer::VisitStoreInstanceField( |
4346 StoreInstanceFieldInstr* instr) { | 4449 StoreInstanceFieldInstr* instr) { |
4347 if (instr->IsUnboxedStore()) { | 4450 if (instr->IsUnboxedStore()) { |
4348 ASSERT(instr->is_initialization_); | 4451 ASSERT(instr->is_initialization_); |
4349 // Determine if this field should be unboxed based on the usage of getter | 4452 // Determine if this field should be unboxed based on the usage of getter |
4350 // and setter functions: The heuristic requires that the setter has a | 4453 // and setter functions: The heuristic requires that the setter has a |
4351 // usage count of at least 1/kGetterSetterRatio of the getter usage count. | 4454 // usage count of at least 1/kGetterSetterRatio of the getter usage count. |
4352 // This is to avoid unboxing fields where the setter is never or rarely | 4455 // This is to avoid unboxing fields where the setter is never or rarely |
4353 // executed. | 4456 // executed. |
4354 const Field& field = Field::ZoneHandle(instr->field().raw()); | 4457 const Field& field = Field::ZoneHandle(isolate(), instr->field().raw()); |
4355 const String& field_name = String::Handle(field.name()); | 4458 const String& field_name = String::Handle(isolate(), field.name()); |
4356 class Class& owner = Class::Handle(field.owner()); | 4459 class Class& owner = Class::Handle(isolate(), field.owner()); |
4357 const Function& getter = | 4460 const Function& getter = |
4358 Function::Handle(owner.LookupGetterFunction(field_name)); | 4461 Function::Handle(isolate(), owner.LookupGetterFunction(field_name)); |
4359 const Function& setter = | 4462 const Function& setter = |
4360 Function::Handle(owner.LookupSetterFunction(field_name)); | 4463 Function::Handle(isolate(), owner.LookupSetterFunction(field_name)); |
4361 bool result = !getter.IsNull() | 4464 bool result = !getter.IsNull() |
4362 && !setter.IsNull() | 4465 && !setter.IsNull() |
4363 && (setter.usage_counter() > 0) | 4466 && (setter.usage_counter() > 0) |
4364 && (FLAG_getter_setter_ratio * setter.usage_counter() > | 4467 && (FLAG_getter_setter_ratio * setter.usage_counter() > |
4365 getter.usage_counter()); | 4468 getter.usage_counter()); |
4366 if (!result) { | 4469 if (!result) { |
4367 if (FLAG_trace_optimization) { | 4470 if (FLAG_trace_optimization) { |
4368 OS::Print("Disabling unboxing of %s\n", field.ToCString()); | 4471 OS::Print("Disabling unboxing of %s\n", field.ToCString()); |
4369 } | 4472 } |
4370 field.set_is_unboxing_candidate(false); | 4473 field.set_is_unboxing_candidate(false); |
(...skipping 18 matching lines...) Expand all Loading... |
4389 ASSERT(instr->HasICData()); | 4492 ASSERT(instr->HasICData()); |
4390 if (unary_ic_data.NumberOfChecks() == 0) { | 4493 if (unary_ic_data.NumberOfChecks() == 0) { |
4391 // No type feedback collected. | 4494 // No type feedback collected. |
4392 return false; | 4495 return false; |
4393 } | 4496 } |
4394 if (!unary_ic_data.HasOneTarget()) { | 4497 if (!unary_ic_data.HasOneTarget()) { |
4395 // Polymorphic sites are inlined like normal method calls by conventional | 4498 // Polymorphic sites are inlined like normal method calls by conventional |
4396 // inlining. | 4499 // inlining. |
4397 return false; | 4500 return false; |
4398 } | 4501 } |
4399 Function& target = Function::Handle(); | 4502 Function& target = Function::Handle(isolate(), Function::null()); |
4400 intptr_t class_id; | 4503 intptr_t class_id; |
4401 unary_ic_data.GetOneClassCheckAt(0, &class_id, &target); | 4504 unary_ic_data.GetOneClassCheckAt(0, &class_id, &target); |
4402 if (target.kind() != RawFunction::kImplicitSetter) { | 4505 if (target.kind() != RawFunction::kImplicitSetter) { |
4403 // Non-implicit setter are inlined like normal method calls. | 4506 // Non-implicit setter are inlined like normal method calls. |
4404 return false; | 4507 return false; |
4405 } | 4508 } |
4406 // Inline implicit instance setter. | 4509 // Inline implicit instance setter. |
4407 const String& field_name = | 4510 const String& field_name = |
4408 String::Handle(Field::NameFromSetter(instr->function_name())); | 4511 String::Handle(isolate(), Field::NameFromSetter(instr->function_name())); |
4409 const Field& field = Field::ZoneHandle(GetField(class_id, field_name)); | 4512 const Field& field = |
| 4513 Field::ZoneHandle(isolate(), GetField(class_id, field_name)); |
4410 ASSERT(!field.IsNull()); | 4514 ASSERT(!field.IsNull()); |
4411 | 4515 |
4412 if (InstanceCallNeedsClassCheck(instr)) { | 4516 if (InstanceCallNeedsClassCheck(instr)) { |
4413 AddReceiverCheck(instr); | 4517 AddReceiverCheck(instr); |
4414 } | 4518 } |
4415 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; | 4519 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; |
4416 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) { | 4520 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) { |
4417 InsertBefore(instr, | 4521 InsertBefore(instr, |
4418 new CheckSmiInstr(new Value(instr->ArgumentAt(1)), | 4522 new(isolate()) CheckSmiInstr( |
4419 instr->deopt_id(), | 4523 new(isolate()) Value(instr->ArgumentAt(1)), |
4420 instr->token_pos()), | 4524 instr->deopt_id(), |
| 4525 instr->token_pos()), |
4421 instr->env(), | 4526 instr->env(), |
4422 FlowGraph::kEffect); | 4527 FlowGraph::kEffect); |
4423 needs_store_barrier = kNoStoreBarrier; | 4528 needs_store_barrier = kNoStoreBarrier; |
4424 } | 4529 } |
4425 | 4530 |
4426 if (field.guarded_cid() != kDynamicCid) { | 4531 if (field.guarded_cid() != kDynamicCid) { |
4427 InsertBefore(instr, | 4532 InsertBefore(instr, |
4428 new GuardFieldInstr(new Value(instr->ArgumentAt(1)), | 4533 new(isolate()) GuardFieldInstr( |
4429 field, | 4534 new(isolate()) Value(instr->ArgumentAt(1)), |
4430 instr->deopt_id()), | 4535 field, |
| 4536 instr->deopt_id()), |
4431 instr->env(), | 4537 instr->env(), |
4432 FlowGraph::kEffect); | 4538 FlowGraph::kEffect); |
4433 } | 4539 } |
4434 | 4540 |
4435 // Field guard was detached. | 4541 // Field guard was detached. |
4436 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( | 4542 StoreInstanceFieldInstr* store = new(isolate()) StoreInstanceFieldInstr( |
4437 field, | 4543 field, |
4438 new Value(instr->ArgumentAt(0)), | 4544 new(isolate()) Value(instr->ArgumentAt(0)), |
4439 new Value(instr->ArgumentAt(1)), | 4545 new(isolate()) Value(instr->ArgumentAt(1)), |
4440 needs_store_barrier, | 4546 needs_store_barrier, |
4441 instr->token_pos()); | 4547 instr->token_pos()); |
4442 | 4548 |
4443 if (store->IsUnboxedStore()) { | 4549 if (store->IsUnboxedStore()) { |
4444 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | 4550 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
4445 } | 4551 } |
4446 | 4552 |
4447 // Discard the environment from the original instruction because the store | 4553 // Discard the environment from the original instruction because the store |
4448 // can't deoptimize. | 4554 // can't deoptimize. |
4449 instr->RemoveEnvironment(); | 4555 instr->RemoveEnvironment(); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4524 if (*direction != new_direction) { | 4630 if (*direction != new_direction) { |
4525 if (*direction != kUnknown) new_direction = kBoth; | 4631 if (*direction != kUnknown) new_direction = kBoth; |
4526 *direction = new_direction; | 4632 *direction = new_direction; |
4527 } | 4633 } |
4528 } | 4634 } |
4529 | 4635 |
4530 // Remove artificial Constraint instructions and replace them with actual | 4636 // Remove artificial Constraint instructions and replace them with actual |
4531 // unconstrained definitions. | 4637 // unconstrained definitions. |
4532 void RemoveConstraints(); | 4638 void RemoveConstraints(); |
4533 | 4639 |
| 4640 Range* ConstraintRange(Token::Kind op, Definition* boundary); |
| 4641 |
| 4642 Isolate* isolate() const { return flow_graph_->isolate(); } |
| 4643 |
4534 FlowGraph* flow_graph_; | 4644 FlowGraph* flow_graph_; |
4535 | 4645 |
4536 GrowableArray<Definition*> smi_values_; // Value that are known to be smi. | 4646 GrowableArray<Definition*> smi_values_; // Value that are known to be smi. |
4537 GrowableArray<CheckSmiInstr*> smi_checks_; // All CheckSmi instructions. | 4647 GrowableArray<CheckSmiInstr*> smi_checks_; // All CheckSmi instructions. |
4538 | 4648 |
4539 // All Constraints inserted during InsertConstraints phase. They are treated | 4649 // All Constraints inserted during InsertConstraints phase. They are treated |
4540 // as smi values. | 4650 // as smi values. |
4541 GrowableArray<ConstraintInstr*> constraints_; | 4651 GrowableArray<ConstraintInstr*> constraints_; |
4542 | 4652 |
4543 // Bitvector for a quick filtering of known smi values. | 4653 // Bitvector for a quick filtering of known smi values. |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4676 return Token::kILLEGAL; | 4786 return Token::kILLEGAL; |
4677 } | 4787 } |
4678 } | 4788 } |
4679 | 4789 |
4680 | 4790 |
4681 // Given a boundary (right operand) and a comparison operation return | 4791 // Given a boundary (right operand) and a comparison operation return |
4682 // a symbolic range constraint for the left operand of the comparison assuming | 4792 // a symbolic range constraint for the left operand of the comparison assuming |
4683 // that it evaluated to true. | 4793 // that it evaluated to true. |
4684 // For example for the comparison a < b symbol a is constrained with range | 4794 // For example for the comparison a < b symbol a is constrained with range |
4685 // [Smi::kMinValue, b - 1]. | 4795 // [Smi::kMinValue, b - 1]. |
4686 static Range* ConstraintRange(Token::Kind op, Definition* boundary) { | 4796 Range* RangeAnalysis::ConstraintRange(Token::Kind op, Definition* boundary) { |
4687 switch (op) { | 4797 switch (op) { |
4688 case Token::kEQ: | 4798 case Token::kEQ: |
4689 return new Range(RangeBoundary::FromDefinition(boundary), | 4799 return new(isolate()) Range(RangeBoundary::FromDefinition(boundary), |
4690 RangeBoundary::FromDefinition(boundary)); | 4800 RangeBoundary::FromDefinition(boundary)); |
4691 case Token::kNE: | 4801 case Token::kNE: |
4692 return Range::Unknown(); | 4802 return Range::Unknown(); |
4693 case Token::kLT: | 4803 case Token::kLT: |
4694 return new Range(RangeBoundary::MinSmi(), | 4804 return new(isolate()) Range(RangeBoundary::MinSmi(), |
4695 RangeBoundary::FromDefinition(boundary, -1)); | 4805 RangeBoundary::FromDefinition(boundary, -1)); |
4696 case Token::kGT: | 4806 case Token::kGT: |
4697 return new Range(RangeBoundary::FromDefinition(boundary, 1), | 4807 return new(isolate()) Range(RangeBoundary::FromDefinition(boundary, 1), |
4698 RangeBoundary::MaxSmi()); | 4808 RangeBoundary::MaxSmi()); |
4699 case Token::kLTE: | 4809 case Token::kLTE: |
4700 return new Range(RangeBoundary::MinSmi(), | 4810 return new(isolate()) Range(RangeBoundary::MinSmi(), |
4701 RangeBoundary::FromDefinition(boundary)); | 4811 RangeBoundary::FromDefinition(boundary)); |
4702 case Token::kGTE: | 4812 case Token::kGTE: |
4703 return new Range(RangeBoundary::FromDefinition(boundary), | 4813 return new(isolate()) Range(RangeBoundary::FromDefinition(boundary), |
4704 RangeBoundary::MaxSmi()); | 4814 RangeBoundary::MaxSmi()); |
4705 default: | 4815 default: |
4706 UNREACHABLE(); | 4816 UNREACHABLE(); |
4707 return Range::Unknown(); | 4817 return Range::Unknown(); |
4708 } | 4818 } |
4709 } | 4819 } |
4710 | 4820 |
4711 | 4821 |
4712 ConstraintInstr* RangeAnalysis::InsertConstraintFor(Definition* defn, | 4822 ConstraintInstr* RangeAnalysis::InsertConstraintFor(Definition* defn, |
4713 Range* constraint_range, | 4823 Range* constraint_range, |
4714 Instruction* after) { | 4824 Instruction* after) { |
4715 // No need to constrain constants. | 4825 // No need to constrain constants. |
4716 if (defn->IsConstant()) return NULL; | 4826 if (defn->IsConstant()) return NULL; |
4717 | 4827 |
4718 ConstraintInstr* constraint = | 4828 ConstraintInstr* constraint = new(isolate()) ConstraintInstr( |
4719 new ConstraintInstr(new Value(defn), constraint_range); | 4829 new(isolate()) Value(defn), constraint_range); |
4720 flow_graph_->InsertAfter(after, constraint, NULL, FlowGraph::kValue); | 4830 flow_graph_->InsertAfter(after, constraint, NULL, FlowGraph::kValue); |
4721 RenameDominatedUses(defn, constraint, constraint); | 4831 RenameDominatedUses(defn, constraint, constraint); |
4722 constraints_.Add(constraint); | 4832 constraints_.Add(constraint); |
4723 return constraint; | 4833 return constraint; |
4724 } | 4834 } |
4725 | 4835 |
4726 | 4836 |
4727 void RangeAnalysis::ConstrainValueAfterBranch(Definition* defn, Value* use) { | 4837 void RangeAnalysis::ConstrainValueAfterBranch(Definition* defn, Value* use) { |
4728 BranchInstr* branch = use->instruction()->AsBranch(); | 4838 BranchInstr* branch = use->instruction()->AsBranch(); |
4729 RelationalOpInstr* rel_op = branch->comparison()->AsRelationalOp(); | 4839 RelationalOpInstr* rel_op = branch->comparison()->AsRelationalOp(); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4784 } | 4894 } |
4785 } | 4895 } |
4786 } | 4896 } |
4787 | 4897 |
4788 | 4898 |
4789 void RangeAnalysis::ConstrainValueAfterCheckArrayBound( | 4899 void RangeAnalysis::ConstrainValueAfterCheckArrayBound( |
4790 Definition* defn, CheckArrayBoundInstr* check, intptr_t use_index) { | 4900 Definition* defn, CheckArrayBoundInstr* check, intptr_t use_index) { |
4791 Range* constraint_range = NULL; | 4901 Range* constraint_range = NULL; |
4792 if (use_index == CheckArrayBoundInstr::kIndexPos) { | 4902 if (use_index == CheckArrayBoundInstr::kIndexPos) { |
4793 Definition* length = check->length()->definition(); | 4903 Definition* length = check->length()->definition(); |
4794 constraint_range = new Range( | 4904 constraint_range = new(isolate()) Range( |
4795 RangeBoundary::FromConstant(0), | 4905 RangeBoundary::FromConstant(0), |
4796 RangeBoundary::FromDefinition(length, -1)); | 4906 RangeBoundary::FromDefinition(length, -1)); |
4797 } else { | 4907 } else { |
4798 ASSERT(use_index == CheckArrayBoundInstr::kLengthPos); | 4908 ASSERT(use_index == CheckArrayBoundInstr::kLengthPos); |
4799 Definition* index = check->index()->definition(); | 4909 Definition* index = check->index()->definition(); |
4800 constraint_range = new Range( | 4910 constraint_range = new(isolate()) Range( |
4801 RangeBoundary::FromDefinition(index, 1), | 4911 RangeBoundary::FromDefinition(index, 1), |
4802 RangeBoundary::MaxSmi()); | 4912 RangeBoundary::MaxSmi()); |
4803 } | 4913 } |
4804 InsertConstraintFor(defn, constraint_range, check); | 4914 InsertConstraintFor(defn, constraint_range, check); |
4805 } | 4915 } |
4806 | 4916 |
4807 | 4917 |
4808 void RangeAnalysis::InsertConstraints() { | 4918 void RangeAnalysis::InsertConstraints() { |
4809 for (intptr_t i = 0; i < smi_checks_.length(); i++) { | 4919 for (intptr_t i = 0; i < smi_checks_.length(); i++) { |
4810 CheckSmiInstr* check = smi_checks_[i]; | 4920 CheckSmiInstr* check = smi_checks_[i]; |
4811 InsertConstraintFor(check->value()->definition(), Range::Unknown(), check); | 4921 InsertConstraintFor(check->value()->definition(), Range::Unknown(), check); |
4812 } | 4922 } |
4813 | 4923 |
4814 for (intptr_t i = 0; i < smi_values_.length(); i++) { | 4924 for (intptr_t i = 0; i < smi_values_.length(); i++) { |
4815 InsertConstraintsFor(smi_values_[i]); | 4925 InsertConstraintsFor(smi_values_[i]); |
4816 } | 4926 } |
4817 | 4927 |
4818 for (intptr_t i = 0; i < constraints_.length(); i++) { | 4928 for (intptr_t i = 0; i < constraints_.length(); i++) { |
4819 InsertConstraintsFor(constraints_[i]); | 4929 InsertConstraintsFor(constraints_[i]); |
4820 } | 4930 } |
4821 } | 4931 } |
4822 | 4932 |
4823 | 4933 |
4824 void RangeAnalysis::ResetWorklist() { | 4934 void RangeAnalysis::ResetWorklist() { |
4825 if (marked_defns_ == NULL) { | 4935 if (marked_defns_ == NULL) { |
4826 marked_defns_ = new BitVector(flow_graph_->current_ssa_temp_index()); | 4936 marked_defns_ = new(isolate()) BitVector( |
| 4937 flow_graph_->current_ssa_temp_index()); |
4827 } else { | 4938 } else { |
4828 marked_defns_->Clear(); | 4939 marked_defns_->Clear(); |
4829 } | 4940 } |
4830 worklist_.Clear(); | 4941 worklist_.Clear(); |
4831 } | 4942 } |
4832 | 4943 |
4833 | 4944 |
4834 void RangeAnalysis::MarkDefinition(Definition* defn) { | 4945 void RangeAnalysis::MarkDefinition(Definition* defn) { |
4835 // Unwrap constrained value. | 4946 // Unwrap constrained value. |
4836 while (defn->IsConstraint()) { | 4947 while (defn->IsConstraint()) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4934 } | 5045 } |
4935 } | 5046 } |
4936 | 5047 |
4937 | 5048 |
4938 // We transitively discovered all dependencies of the given phi | 5049 // We transitively discovered all dependencies of the given phi |
4939 // and confirmed that it depends on a single value coming from outside of | 5050 // and confirmed that it depends on a single value coming from outside of |
4940 // the loop and some linear combinations of itself. | 5051 // the loop and some linear combinations of itself. |
4941 // Compute the range based on initial value and the direction of the growth. | 5052 // Compute the range based on initial value and the direction of the growth. |
4942 switch (direction) { | 5053 switch (direction) { |
4943 case kPositive: | 5054 case kPositive: |
4944 return new Range(RangeBoundary::FromDefinition(initial_value), | 5055 return new(isolate()) Range(RangeBoundary::FromDefinition(initial_value), |
4945 RangeBoundary::MaxSmi()); | 5056 RangeBoundary::MaxSmi()); |
4946 | 5057 |
4947 case kNegative: | 5058 case kNegative: |
4948 return new Range(RangeBoundary::MinSmi(), | 5059 return new(isolate()) Range(RangeBoundary::MinSmi(), |
4949 RangeBoundary::FromDefinition(initial_value)); | 5060 RangeBoundary::FromDefinition(initial_value)); |
4950 | 5061 |
4951 case kUnknown: | 5062 case kUnknown: |
4952 case kBoth: | 5063 case kBoth: |
4953 return Range::Unknown(); | 5064 return Range::Unknown(); |
4954 } | 5065 } |
4955 | 5066 |
4956 UNREACHABLE(); | 5067 UNREACHABLE(); |
4957 return NULL; | 5068 return NULL; |
4958 } | 5069 } |
4959 | 5070 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4999 } | 5110 } |
5000 | 5111 |
5001 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { | 5112 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { |
5002 InferRangesRecursive(block->dominated_blocks()[i]); | 5113 InferRangesRecursive(block->dominated_blocks()[i]); |
5003 } | 5114 } |
5004 } | 5115 } |
5005 | 5116 |
5006 | 5117 |
5007 void RangeAnalysis::InferRanges() { | 5118 void RangeAnalysis::InferRanges() { |
5008 // Initialize bitvector for quick filtering of smi values. | 5119 // Initialize bitvector for quick filtering of smi values. |
5009 smi_definitions_ = new BitVector(flow_graph_->current_ssa_temp_index()); | 5120 smi_definitions_ = |
| 5121 new(isolate()) BitVector(flow_graph_->current_ssa_temp_index()); |
5010 for (intptr_t i = 0; i < smi_values_.length(); i++) { | 5122 for (intptr_t i = 0; i < smi_values_.length(); i++) { |
5011 smi_definitions_->Add(smi_values_[i]->ssa_temp_index()); | 5123 smi_definitions_->Add(smi_values_[i]->ssa_temp_index()); |
5012 } | 5124 } |
5013 for (intptr_t i = 0; i < constraints_.length(); i++) { | 5125 for (intptr_t i = 0; i < constraints_.length(); i++) { |
5014 smi_definitions_->Add(constraints_[i]->ssa_temp_index()); | 5126 smi_definitions_->Add(constraints_[i]->ssa_temp_index()); |
5015 } | 5127 } |
5016 | 5128 |
5017 // Infer initial values of ranges. | 5129 // Infer initial values of ranges. |
5018 const GrowableArray<Definition*>& initial = | 5130 const GrowableArray<Definition*>& initial = |
5019 *flow_graph_->graph_entry()->initial_definitions(); | 5131 *flow_graph_->graph_entry()->initial_definitions(); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5103 } | 5215 } |
5104 } | 5216 } |
5105 } | 5217 } |
5106 } | 5218 } |
5107 } | 5219 } |
5108 for (intptr_t j = 0; j < idefs->length(); ++j) { | 5220 for (intptr_t j = 0; j < idefs->length(); ++j) { |
5109 if (cdefs[j] != NULL && cdefs[j]->IsConstant()) { | 5221 if (cdefs[j] != NULL && cdefs[j]->IsConstant()) { |
5110 // TODO(fschneider): Use constants from the constant pool. | 5222 // TODO(fschneider): Use constants from the constant pool. |
5111 Definition* old = (*idefs)[j]; | 5223 Definition* old = (*idefs)[j]; |
5112 ConstantInstr* orig = cdefs[j]->AsConstant(); | 5224 ConstantInstr* orig = cdefs[j]->AsConstant(); |
5113 ConstantInstr* copy = new ConstantInstr(orig->value()); | 5225 ConstantInstr* copy = |
| 5226 new(flow_graph->isolate()) ConstantInstr(orig->value()); |
5114 copy->set_ssa_temp_index(flow_graph->alloc_ssa_temp_index()); | 5227 copy->set_ssa_temp_index(flow_graph->alloc_ssa_temp_index()); |
5115 old->ReplaceUsesWith(copy); | 5228 old->ReplaceUsesWith(copy); |
5116 (*idefs)[j] = copy; | 5229 (*idefs)[j] = copy; |
5117 } | 5230 } |
5118 } | 5231 } |
5119 } | 5232 } |
5120 } | 5233 } |
5121 | 5234 |
5122 | 5235 |
5123 static BlockEntryInstr* FindPreHeader(BlockEntryInstr* header) { | 5236 static BlockEntryInstr* FindPreHeader(BlockEntryInstr* header) { |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5586 } | 5699 } |
5587 | 5700 |
5588 bool Equals(Place* other) const { | 5701 bool Equals(Place* other) const { |
5589 return (kind_ == other->kind_) && | 5702 return (kind_ == other->kind_) && |
5590 (representation_ == other->representation_) && | 5703 (representation_ == other->representation_) && |
5591 (instance_ == other->instance_) && | 5704 (instance_ == other->instance_) && |
5592 SameField(other); | 5705 SameField(other); |
5593 } | 5706 } |
5594 | 5707 |
5595 // Create a zone allocated copy of this place. | 5708 // Create a zone allocated copy of this place. |
5596 static Place* Wrap(const Place& place); | 5709 static Place* Wrap(Isolate* isolate, const Place& place); |
5597 | 5710 |
5598 private: | 5711 private: |
5599 bool SameField(Place* other) const { | 5712 bool SameField(Place* other) const { |
5600 return (kind_ == kField) ? (field().raw() == other->field().raw()) | 5713 return (kind_ == kField) ? (field().raw() == other->field().raw()) |
5601 : (offset_in_bytes_ == other->offset_in_bytes_); | 5714 : (offset_in_bytes_ == other->offset_in_bytes_); |
5602 } | 5715 } |
5603 | 5716 |
5604 intptr_t FieldHashcode() const { | 5717 intptr_t FieldHashcode() const { |
5605 return (kind_ == kField) ? reinterpret_cast<intptr_t>(field().raw()) | 5718 return (kind_ == kField) ? reinterpret_cast<intptr_t>(field().raw()) |
5606 : offset_in_bytes_; | 5719 : offset_in_bytes_; |
(...skipping 17 matching lines...) Expand all Loading... |
5624 public: | 5737 public: |
5625 explicit ZonePlace(const Place& place) : place_(place) { } | 5738 explicit ZonePlace(const Place& place) : place_(place) { } |
5626 | 5739 |
5627 Place* place() { return &place_; } | 5740 Place* place() { return &place_; } |
5628 | 5741 |
5629 private: | 5742 private: |
5630 Place place_; | 5743 Place place_; |
5631 }; | 5744 }; |
5632 | 5745 |
5633 | 5746 |
5634 Place* Place::Wrap(const Place& place) { | 5747 Place* Place::Wrap(Isolate* isolate, const Place& place) { |
5635 return (new ZonePlace(place))->place(); | 5748 return (new(isolate) ZonePlace(place))->place(); |
5636 } | 5749 } |
5637 | 5750 |
5638 | 5751 |
5639 // Correspondence between places connected through outgoing phi moves on the | 5752 // Correspondence between places connected through outgoing phi moves on the |
5640 // edge that targets join. | 5753 // edge that targets join. |
5641 class PhiPlaceMoves : public ZoneAllocated { | 5754 class PhiPlaceMoves : public ZoneAllocated { |
5642 public: | 5755 public: |
5643 // Record a move from the place with id |from| to the place with id |to| at | 5756 // Record a move from the place with id |from| to the place with id |to| at |
5644 // the given block. | 5757 // the given block. |
5645 void CreateOutgoingMove(BlockEntryInstr* block, intptr_t from, intptr_t to) { | 5758 void CreateOutgoingMove(Isolate* isolate, |
| 5759 BlockEntryInstr* block, intptr_t from, intptr_t to) { |
5646 const intptr_t block_num = block->preorder_number(); | 5760 const intptr_t block_num = block->preorder_number(); |
5647 while (moves_.length() <= block_num) { | 5761 while (moves_.length() <= block_num) { |
5648 moves_.Add(NULL); | 5762 moves_.Add(NULL); |
5649 } | 5763 } |
5650 | 5764 |
5651 if (moves_[block_num] == NULL) { | 5765 if (moves_[block_num] == NULL) { |
5652 moves_[block_num] = new ZoneGrowableArray<Move>(5); | 5766 moves_[block_num] = new(isolate) ZoneGrowableArray<Move>(5); |
5653 } | 5767 } |
5654 | 5768 |
5655 moves_[block_num]->Add(Move(from, to)); | 5769 moves_[block_num]->Add(Move(from, to)); |
5656 } | 5770 } |
5657 | 5771 |
5658 class Move { | 5772 class Move { |
5659 public: | 5773 public: |
5660 Move(intptr_t from, intptr_t to) : from_(from), to_(to) { } | 5774 Move(intptr_t from, intptr_t to) : from_(from), to_(to) { } |
5661 | 5775 |
5662 intptr_t from() const { return from_; } | 5776 intptr_t from() const { return from_; } |
(...skipping 15 matching lines...) Expand all Loading... |
5678 private: | 5792 private: |
5679 GrowableArray<ZoneGrowableArray<Move>* > moves_; | 5793 GrowableArray<ZoneGrowableArray<Move>* > moves_; |
5680 }; | 5794 }; |
5681 | 5795 |
5682 | 5796 |
5683 // A map from aliases to a set of places sharing the alias. Additionally | 5797 // A map from aliases to a set of places sharing the alias. Additionally |
5684 // carries a set of places that can be aliased by side-effects, essentially | 5798 // carries a set of places that can be aliased by side-effects, essentially |
5685 // those that are affected by calls. | 5799 // those that are affected by calls. |
5686 class AliasedSet : public ZoneAllocated { | 5800 class AliasedSet : public ZoneAllocated { |
5687 public: | 5801 public: |
5688 explicit AliasedSet(ZoneGrowableArray<Place*>* places, | 5802 AliasedSet(Isolate* isolate, |
5689 PhiPlaceMoves* phi_moves) | 5803 ZoneGrowableArray<Place*>* places, |
5690 : places_(*places), | 5804 PhiPlaceMoves* phi_moves) |
| 5805 : isolate_(isolate), |
| 5806 places_(*places), |
5691 phi_moves_(phi_moves), | 5807 phi_moves_(phi_moves), |
5692 sets_(), | 5808 sets_(), |
5693 aliased_by_effects_(new BitVector(places->length())), | 5809 aliased_by_effects_(new(isolate) BitVector(places->length())), |
5694 max_field_id_(0), | 5810 max_field_id_(0), |
5695 field_ids_(), | 5811 field_ids_(), |
5696 max_index_id_(0), | 5812 max_index_id_(0), |
5697 index_ids_(), | 5813 index_ids_(), |
5698 max_unknown_index_id_(0), | 5814 max_unknown_index_id_(0), |
5699 unknown_index_ids_(), | 5815 unknown_index_ids_(), |
5700 max_vm_field_id_(0), | 5816 max_vm_field_id_(0), |
5701 vm_field_ids_() { } | 5817 vm_field_ids_() { } |
5702 | 5818 |
5703 Alias ComputeAlias(Place* place) { | 5819 Alias ComputeAlias(Place* place) { |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5813 } | 5929 } |
5814 } | 5930 } |
5815 | 5931 |
5816 void AddIdForAlias(const Alias alias, intptr_t place_id) { | 5932 void AddIdForAlias(const Alias alias, intptr_t place_id) { |
5817 const intptr_t idx = alias.ToIndex(); | 5933 const intptr_t idx = alias.ToIndex(); |
5818 while (sets_.length() <= idx) { | 5934 while (sets_.length() <= idx) { |
5819 sets_.Add(NULL); | 5935 sets_.Add(NULL); |
5820 } | 5936 } |
5821 | 5937 |
5822 if (sets_[idx] == NULL) { | 5938 if (sets_[idx] == NULL) { |
5823 sets_[idx] = new BitVector(max_place_id()); | 5939 sets_[idx] = new(isolate_) BitVector(max_place_id()); |
5824 } | 5940 } |
5825 | 5941 |
5826 sets_[idx]->Add(place_id); | 5942 sets_[idx]->Add(place_id); |
5827 } | 5943 } |
5828 | 5944 |
5829 intptr_t max_place_id() const { return places().length(); } | 5945 intptr_t max_place_id() const { return places().length(); } |
5830 bool IsEmpty() const { return max_place_id() == 0; } | 5946 bool IsEmpty() const { return max_place_id() == 0; } |
5831 | 5947 |
5832 BitVector* aliased_by_effects() const { return aliased_by_effects_; } | 5948 BitVector* aliased_by_effects() const { return aliased_by_effects_; } |
5833 | 5949 |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6166 static inline bool IsKeyEqual(Pair kv, Key key) { | 6282 static inline bool IsKeyEqual(Pair kv, Key key) { |
6167 return (KeyOf(kv).offset_ == key.offset_) && | 6283 return (KeyOf(kv).offset_ == key.offset_) && |
6168 (KeyOf(kv).instance_id_ == key.instance_id_); | 6284 (KeyOf(kv).instance_id_ == key.instance_id_); |
6169 } | 6285 } |
6170 | 6286 |
6171 private: | 6287 private: |
6172 Key key_; | 6288 Key key_; |
6173 Value value_; | 6289 Value value_; |
6174 }; | 6290 }; |
6175 | 6291 |
| 6292 Isolate* isolate_; |
| 6293 |
6176 const ZoneGrowableArray<Place*>& places_; | 6294 const ZoneGrowableArray<Place*>& places_; |
6177 | 6295 |
6178 const PhiPlaceMoves* phi_moves_; | 6296 const PhiPlaceMoves* phi_moves_; |
6179 | 6297 |
6180 // Maps alias index to a set of ssa indexes corresponding to loads with the | 6298 // Maps alias index to a set of ssa indexes corresponding to loads with the |
6181 // given alias. | 6299 // given alias. |
6182 GrowableArray<BitVector*> sets_; | 6300 GrowableArray<BitVector*> sets_; |
6183 | 6301 |
6184 BitVector* aliased_by_effects_; | 6302 BitVector* aliased_by_effects_; |
6185 | 6303 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6230 } | 6348 } |
6231 | 6349 |
6232 | 6350 |
6233 // For each place that depends on a phi ensure that equivalent places | 6351 // For each place that depends on a phi ensure that equivalent places |
6234 // corresponding to phi input are numbered and record outgoing phi moves | 6352 // corresponding to phi input are numbered and record outgoing phi moves |
6235 // for each block which establish correspondence between phi dependent place | 6353 // for each block which establish correspondence between phi dependent place |
6236 // and phi input's place that is flowing in. | 6354 // and phi input's place that is flowing in. |
6237 static PhiPlaceMoves* ComputePhiMoves( | 6355 static PhiPlaceMoves* ComputePhiMoves( |
6238 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map, | 6356 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map, |
6239 ZoneGrowableArray<Place*>* places) { | 6357 ZoneGrowableArray<Place*>* places) { |
6240 PhiPlaceMoves* phi_moves = new PhiPlaceMoves(); | 6358 Isolate* isolate = Isolate::Current(); |
| 6359 PhiPlaceMoves* phi_moves = new(isolate) PhiPlaceMoves(); |
6241 | 6360 |
6242 for (intptr_t i = 0; i < places->length(); i++) { | 6361 for (intptr_t i = 0; i < places->length(); i++) { |
6243 Place* place = (*places)[i]; | 6362 Place* place = (*places)[i]; |
6244 | 6363 |
6245 if (IsPhiDependentPlace(place)) { | 6364 if (IsPhiDependentPlace(place)) { |
6246 PhiInstr* phi = place->instance()->AsPhi(); | 6365 PhiInstr* phi = place->instance()->AsPhi(); |
6247 BlockEntryInstr* block = phi->GetBlock(); | 6366 BlockEntryInstr* block = phi->GetBlock(); |
6248 | 6367 |
6249 if (FLAG_trace_optimization) { | 6368 if (FLAG_trace_optimization) { |
6250 OS::Print("phi dependent place %s\n", place->ToCString()); | 6369 OS::Print("phi dependent place %s\n", place->ToCString()); |
6251 } | 6370 } |
6252 | 6371 |
6253 Place input_place(*place); | 6372 Place input_place(*place); |
6254 for (intptr_t j = 0; j < phi->InputCount(); j++) { | 6373 for (intptr_t j = 0; j < phi->InputCount(); j++) { |
6255 input_place.set_instance(phi->InputAt(j)->definition()); | 6374 input_place.set_instance(phi->InputAt(j)->definition()); |
6256 | 6375 |
6257 Place* result = map->Lookup(&input_place); | 6376 Place* result = map->Lookup(&input_place); |
6258 if (result == NULL) { | 6377 if (result == NULL) { |
6259 input_place.set_id(places->length()); | 6378 input_place.set_id(places->length()); |
6260 result = Place::Wrap(input_place); | 6379 result = Place::Wrap(isolate, input_place); |
6261 map->Insert(result); | 6380 map->Insert(result); |
6262 places->Add(result); | 6381 places->Add(result); |
6263 if (FLAG_trace_optimization) { | 6382 if (FLAG_trace_optimization) { |
6264 OS::Print(" adding place %s as %" Pd "\n", | 6383 OS::Print(" adding place %s as %" Pd "\n", |
6265 result->ToCString(), | 6384 result->ToCString(), |
6266 result->id()); | 6385 result->id()); |
6267 } | 6386 } |
6268 } | 6387 } |
6269 phi_moves->CreateOutgoingMove(block->PredecessorAt(j), | 6388 phi_moves->CreateOutgoingMove(isolate, |
| 6389 block->PredecessorAt(j), |
6270 result->id(), | 6390 result->id(), |
6271 place->id()); | 6391 place->id()); |
6272 } | 6392 } |
6273 } | 6393 } |
6274 } | 6394 } |
6275 | 6395 |
6276 return phi_moves; | 6396 return phi_moves; |
6277 } | 6397 } |
6278 | 6398 |
6279 | 6399 |
6280 enum CSEMode { | 6400 enum CSEMode { |
6281 kOptimizeLoads, | 6401 kOptimizeLoads, |
6282 kOptimizeStores | 6402 kOptimizeStores |
6283 }; | 6403 }; |
6284 | 6404 |
6285 | 6405 |
6286 static AliasedSet* NumberPlaces( | 6406 static AliasedSet* NumberPlaces( |
6287 FlowGraph* graph, | 6407 FlowGraph* graph, |
6288 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map, | 6408 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map, |
6289 CSEMode mode) { | 6409 CSEMode mode) { |
6290 // Loads representing different expression ids will be collected and | 6410 // Loads representing different expression ids will be collected and |
6291 // used to build per offset kill sets. | 6411 // used to build per offset kill sets. |
6292 ZoneGrowableArray<Place*>* places = new ZoneGrowableArray<Place*>(10); | 6412 Isolate* isolate = graph->isolate(); |
| 6413 ZoneGrowableArray<Place*>* places = |
| 6414 new(isolate) ZoneGrowableArray<Place*>(10); |
6293 | 6415 |
6294 bool has_loads = false; | 6416 bool has_loads = false; |
6295 bool has_stores = false; | 6417 bool has_stores = false; |
6296 for (BlockIterator it = graph->reverse_postorder_iterator(); | 6418 for (BlockIterator it = graph->reverse_postorder_iterator(); |
6297 !it.Done(); | 6419 !it.Done(); |
6298 it.Advance()) { | 6420 it.Advance()) { |
6299 BlockEntryInstr* block = it.Current(); | 6421 BlockEntryInstr* block = it.Current(); |
6300 for (ForwardInstructionIterator instr_it(block); | 6422 for (ForwardInstructionIterator instr_it(block); |
6301 !instr_it.Done(); | 6423 !instr_it.Done(); |
6302 instr_it.Advance()) { | 6424 instr_it.Advance()) { |
6303 Instruction* instr = instr_it.Current(); | 6425 Instruction* instr = instr_it.Current(); |
6304 Place place(instr, &has_loads, &has_stores); | 6426 Place place(instr, &has_loads, &has_stores); |
6305 if (place.kind() == Place::kNone) { | 6427 if (place.kind() == Place::kNone) { |
6306 continue; | 6428 continue; |
6307 } | 6429 } |
6308 | 6430 |
6309 Place* result = map->Lookup(&place); | 6431 Place* result = map->Lookup(&place); |
6310 if (result == NULL) { | 6432 if (result == NULL) { |
6311 place.set_id(places->length()); | 6433 place.set_id(places->length()); |
6312 result = Place::Wrap(place); | 6434 result = Place::Wrap(isolate, place); |
6313 map->Insert(result); | 6435 map->Insert(result); |
6314 places->Add(result); | 6436 places->Add(result); |
6315 | 6437 |
6316 if (FLAG_trace_optimization) { | 6438 if (FLAG_trace_optimization) { |
6317 OS::Print("numbering %s as %" Pd "\n", | 6439 OS::Print("numbering %s as %" Pd "\n", |
6318 result->ToCString(), | 6440 result->ToCString(), |
6319 result->id()); | 6441 result->id()); |
6320 } | 6442 } |
6321 } | 6443 } |
6322 | 6444 |
6323 instr->set_place_id(result->id()); | 6445 instr->set_place_id(result->id()); |
6324 } | 6446 } |
6325 } | 6447 } |
6326 | 6448 |
6327 if ((mode == kOptimizeLoads) && !has_loads) { | 6449 if ((mode == kOptimizeLoads) && !has_loads) { |
6328 return NULL; | 6450 return NULL; |
6329 } | 6451 } |
6330 if ((mode == kOptimizeStores) && !has_stores) { | 6452 if ((mode == kOptimizeStores) && !has_stores) { |
6331 return NULL; | 6453 return NULL; |
6332 } | 6454 } |
6333 | 6455 |
6334 PhiPlaceMoves* phi_moves = ComputePhiMoves(map, places); | 6456 PhiPlaceMoves* phi_moves = ComputePhiMoves(map, places); |
6335 | 6457 |
6336 // Build aliasing sets mapping aliases to loads. | 6458 // Build aliasing sets mapping aliases to loads. |
6337 AliasedSet* aliased_set = new AliasedSet(places, phi_moves); | 6459 AliasedSet* aliased_set = new(isolate) AliasedSet(isolate, places, phi_moves); |
6338 for (intptr_t i = 0; i < places->length(); i++) { | 6460 for (intptr_t i = 0; i < places->length(); i++) { |
6339 Place* place = (*places)[i]; | 6461 Place* place = (*places)[i]; |
6340 aliased_set->AddRepresentative(place); | 6462 aliased_set->AddRepresentative(place); |
6341 } | 6463 } |
6342 | 6464 |
6343 aliased_set->EnsureAliasingForUnknownIndices(); | 6465 aliased_set->EnsureAliasingForUnknownIndices(); |
6344 | 6466 |
6345 return aliased_set; | 6467 return aliased_set; |
6346 } | 6468 } |
6347 | 6469 |
(...skipping 12 matching lines...) Expand all Loading... |
6360 kill_(graph_->preorder().length()), | 6482 kill_(graph_->preorder().length()), |
6361 exposed_values_(graph_->preorder().length()), | 6483 exposed_values_(graph_->preorder().length()), |
6362 out_values_(graph_->preorder().length()), | 6484 out_values_(graph_->preorder().length()), |
6363 phis_(5), | 6485 phis_(5), |
6364 worklist_(5), | 6486 worklist_(5), |
6365 in_worklist_(NULL), | 6487 in_worklist_(NULL), |
6366 forwarded_(false) { | 6488 forwarded_(false) { |
6367 const intptr_t num_blocks = graph_->preorder().length(); | 6489 const intptr_t num_blocks = graph_->preorder().length(); |
6368 for (intptr_t i = 0; i < num_blocks; i++) { | 6490 for (intptr_t i = 0; i < num_blocks; i++) { |
6369 out_.Add(NULL); | 6491 out_.Add(NULL); |
6370 gen_.Add(new BitVector(aliased_set_->max_place_id())); | 6492 gen_.Add(new(isolate()) BitVector(aliased_set_->max_place_id())); |
6371 kill_.Add(new BitVector(aliased_set_->max_place_id())); | 6493 kill_.Add(new(isolate()) BitVector(aliased_set_->max_place_id())); |
6372 in_.Add(new BitVector(aliased_set_->max_place_id())); | 6494 in_.Add(new(isolate()) BitVector(aliased_set_->max_place_id())); |
6373 | 6495 |
6374 exposed_values_.Add(NULL); | 6496 exposed_values_.Add(NULL); |
6375 out_values_.Add(NULL); | 6497 out_values_.Add(NULL); |
6376 } | 6498 } |
6377 } | 6499 } |
6378 | 6500 |
| 6501 Isolate* isolate() const { return graph_->isolate(); } |
| 6502 |
6379 static bool OptimizeGraph(FlowGraph* graph) { | 6503 static bool OptimizeGraph(FlowGraph* graph) { |
6380 ASSERT(FLAG_load_cse); | 6504 ASSERT(FLAG_load_cse); |
6381 if (FLAG_trace_load_optimization) { | 6505 if (FLAG_trace_load_optimization) { |
6382 FlowGraphPrinter::PrintGraph("Before LoadOptimizer", graph); | 6506 FlowGraphPrinter::PrintGraph("Before LoadOptimizer", graph); |
6383 } | 6507 } |
6384 | 6508 |
6385 DirectChainedHashMap<PointerKeyValueTrait<Place> > map; | 6509 DirectChainedHashMap<PointerKeyValueTrait<Place> > map; |
6386 AliasedSet* aliased_set = NumberPlaces(graph, &map, kOptimizeLoads); | 6510 AliasedSet* aliased_set = NumberPlaces(graph, &map, kOptimizeLoads); |
6387 if ((aliased_set != NULL) && !aliased_set->IsEmpty()) { | 6511 if ((aliased_set != NULL) && !aliased_set->IsEmpty()) { |
6388 // If any loads were forwarded return true from Optimize to run load | 6512 // If any loads were forwarded return true from Optimize to run load |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6559 defn->ReplaceUsesWith(replacement); | 6683 defn->ReplaceUsesWith(replacement); |
6560 instr_it.RemoveCurrentFromGraph(); | 6684 instr_it.RemoveCurrentFromGraph(); |
6561 forwarded_ = true; | 6685 forwarded_ = true; |
6562 continue; | 6686 continue; |
6563 } else if (!kill->Contains(place_id)) { | 6687 } else if (!kill->Contains(place_id)) { |
6564 // This is an exposed load: it is the first representative of a | 6688 // This is an exposed load: it is the first representative of a |
6565 // given expression id and it is not killed on the path from | 6689 // given expression id and it is not killed on the path from |
6566 // the block entry. | 6690 // the block entry. |
6567 if (exposed_values == NULL) { | 6691 if (exposed_values == NULL) { |
6568 static const intptr_t kMaxExposedValuesInitialSize = 5; | 6692 static const intptr_t kMaxExposedValuesInitialSize = 5; |
6569 exposed_values = new ZoneGrowableArray<Definition*>( | 6693 exposed_values = new(isolate()) ZoneGrowableArray<Definition*>( |
6570 Utils::Minimum(kMaxExposedValuesInitialSize, | 6694 Utils::Minimum(kMaxExposedValuesInitialSize, |
6571 aliased_set_->max_place_id())); | 6695 aliased_set_->max_place_id())); |
6572 } | 6696 } |
6573 | 6697 |
6574 exposed_values->Add(defn); | 6698 exposed_values->Add(defn); |
6575 } | 6699 } |
6576 | 6700 |
6577 gen->Add(place_id); | 6701 gen->Add(place_id); |
6578 | 6702 |
6579 if (out_values == NULL) out_values = CreateBlockOutValues(); | 6703 if (out_values == NULL) out_values = CreateBlockOutValues(); |
(...skipping 27 matching lines...) Expand all Loading... |
6607 | 6731 |
6608 out->Remove(to); | 6732 out->Remove(to); |
6609 } | 6733 } |
6610 | 6734 |
6611 out->AddAll(forwarded_loads); | 6735 out->AddAll(forwarded_loads); |
6612 } | 6736 } |
6613 | 6737 |
6614 // Compute OUT sets by propagating them iteratively until fix point | 6738 // Compute OUT sets by propagating them iteratively until fix point |
6615 // is reached. | 6739 // is reached. |
6616 void ComputeOutSets() { | 6740 void ComputeOutSets() { |
6617 BitVector* temp = new BitVector(aliased_set_->max_place_id()); | 6741 BitVector* temp = new(isolate()) BitVector(aliased_set_->max_place_id()); |
6618 BitVector* forwarded_loads = new BitVector(aliased_set_->max_place_id()); | 6742 BitVector* forwarded_loads = |
6619 BitVector* temp_out = new BitVector(aliased_set_->max_place_id()); | 6743 new(isolate()) BitVector(aliased_set_->max_place_id()); |
| 6744 BitVector* temp_out = |
| 6745 new(isolate()) BitVector(aliased_set_->max_place_id()); |
6620 | 6746 |
6621 bool changed = true; | 6747 bool changed = true; |
6622 while (changed) { | 6748 while (changed) { |
6623 changed = false; | 6749 changed = false; |
6624 | 6750 |
6625 for (BlockIterator block_it = graph_->reverse_postorder_iterator(); | 6751 for (BlockIterator block_it = graph_->reverse_postorder_iterator(); |
6626 !block_it.Done(); | 6752 !block_it.Done(); |
6627 block_it.Advance()) { | 6753 block_it.Advance()) { |
6628 BlockEntryInstr* block = block_it.Current(); | 6754 BlockEntryInstr* block = block_it.Current(); |
6629 | 6755 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6661 if (!temp->Equals(*block_in) || (block_out == NULL)) { | 6787 if (!temp->Equals(*block_in) || (block_out == NULL)) { |
6662 // If IN set has changed propagate the change to OUT set. | 6788 // If IN set has changed propagate the change to OUT set. |
6663 block_in->CopyFrom(temp); | 6789 block_in->CopyFrom(temp); |
6664 | 6790 |
6665 temp->RemoveAll(block_kill); | 6791 temp->RemoveAll(block_kill); |
6666 temp->AddAll(block_gen); | 6792 temp->AddAll(block_gen); |
6667 | 6793 |
6668 if ((block_out == NULL) || !block_out->Equals(*temp)) { | 6794 if ((block_out == NULL) || !block_out->Equals(*temp)) { |
6669 if (block_out == NULL) { | 6795 if (block_out == NULL) { |
6670 block_out = out_[preorder_number] = | 6796 block_out = out_[preorder_number] = |
6671 new BitVector(aliased_set_->max_place_id()); | 6797 new(isolate()) BitVector(aliased_set_->max_place_id()); |
6672 } | 6798 } |
6673 block_out->CopyFrom(temp); | 6799 block_out->CopyFrom(temp); |
6674 changed = true; | 6800 changed = true; |
6675 } | 6801 } |
6676 } | 6802 } |
6677 } | 6803 } |
6678 } | 6804 } |
6679 } | 6805 } |
6680 | 6806 |
6681 // Compute out_values mappings by propagating them in reverse postorder once | 6807 // Compute out_values mappings by propagating them in reverse postorder once |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6714 out_values_[preorder_number] = block_out_values = | 6840 out_values_[preorder_number] = block_out_values = |
6715 CreateBlockOutValues(); | 6841 CreateBlockOutValues(); |
6716 } | 6842 } |
6717 | 6843 |
6718 if ((*block_out_values)[place_id] == NULL) { | 6844 if ((*block_out_values)[place_id] == NULL) { |
6719 ASSERT(block->PredecessorCount() > 0); | 6845 ASSERT(block->PredecessorCount() > 0); |
6720 Definition* in_value = can_merge_eagerly ? | 6846 Definition* in_value = can_merge_eagerly ? |
6721 MergeIncomingValues(block, place_id) : NULL; | 6847 MergeIncomingValues(block, place_id) : NULL; |
6722 if ((in_value == NULL) && | 6848 if ((in_value == NULL) && |
6723 (in_[preorder_number]->Contains(place_id))) { | 6849 (in_[preorder_number]->Contains(place_id))) { |
6724 PhiInstr* phi = new PhiInstr(block->AsJoinEntry(), | 6850 PhiInstr* phi = new(isolate()) PhiInstr(block->AsJoinEntry(), |
6725 block->PredecessorCount()); | 6851 block->PredecessorCount()); |
6726 phi->set_place_id(place_id); | 6852 phi->set_place_id(place_id); |
6727 pending_phis.Add(phi); | 6853 pending_phis.Add(phi); |
6728 in_value = phi; | 6854 in_value = phi; |
6729 } | 6855 } |
6730 (*block_out_values)[place_id] = in_value; | 6856 (*block_out_values)[place_id] = in_value; |
6731 } | 6857 } |
6732 } | 6858 } |
6733 | 6859 |
6734 // If the block has outgoing phi moves perform them. Use temporary list | 6860 // If the block has outgoing phi moves perform them. Use temporary list |
6735 // of values to ensure that cyclic moves are performed correctly. | 6861 // of values to ensure that cyclic moves are performed correctly. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6788 } | 6914 } |
6789 } | 6915 } |
6790 return true; | 6916 return true; |
6791 } | 6917 } |
6792 | 6918 |
6793 void MarkLoopInvariantLoads() { | 6919 void MarkLoopInvariantLoads() { |
6794 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = | 6920 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = |
6795 graph_->loop_headers(); | 6921 graph_->loop_headers(); |
6796 | 6922 |
6797 ZoneGrowableArray<BitVector*>* invariant_loads = | 6923 ZoneGrowableArray<BitVector*>* invariant_loads = |
6798 new ZoneGrowableArray<BitVector*>(loop_headers.length()); | 6924 new(isolate()) ZoneGrowableArray<BitVector*>(loop_headers.length()); |
6799 | 6925 |
6800 for (intptr_t i = 0; i < loop_headers.length(); i++) { | 6926 for (intptr_t i = 0; i < loop_headers.length(); i++) { |
6801 BlockEntryInstr* header = loop_headers[i]; | 6927 BlockEntryInstr* header = loop_headers[i]; |
6802 BlockEntryInstr* pre_header = FindPreHeader(header); | 6928 BlockEntryInstr* pre_header = FindPreHeader(header); |
6803 if (pre_header == NULL) { | 6929 if (pre_header == NULL) { |
6804 invariant_loads->Add(NULL); | 6930 invariant_loads->Add(NULL); |
6805 continue; | 6931 continue; |
6806 } | 6932 } |
6807 | 6933 |
6808 BitVector* loop_gen = new BitVector(aliased_set_->max_place_id()); | 6934 BitVector* loop_gen = |
| 6935 new(isolate()) BitVector(aliased_set_->max_place_id()); |
6809 for (BitVector::Iterator loop_it(header->loop_info()); | 6936 for (BitVector::Iterator loop_it(header->loop_info()); |
6810 !loop_it.Done(); | 6937 !loop_it.Done(); |
6811 loop_it.Advance()) { | 6938 loop_it.Advance()) { |
6812 const intptr_t preorder_number = loop_it.Current(); | 6939 const intptr_t preorder_number = loop_it.Current(); |
6813 loop_gen->AddAll(gen_[preorder_number]); | 6940 loop_gen->AddAll(gen_[preorder_number]); |
6814 } | 6941 } |
6815 | 6942 |
6816 for (BitVector::Iterator loop_it(header->loop_info()); | 6943 for (BitVector::Iterator loop_it(header->loop_info()); |
6817 !loop_it.Done(); | 6944 !loop_it.Done(); |
6818 loop_it.Advance()) { | 6945 loop_it.Advance()) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6854 incoming = kDifferentValuesMarker; | 6981 incoming = kDifferentValuesMarker; |
6855 } | 6982 } |
6856 } | 6983 } |
6857 | 6984 |
6858 if (incoming != kDifferentValuesMarker) { | 6985 if (incoming != kDifferentValuesMarker) { |
6859 ASSERT(incoming != NULL); | 6986 ASSERT(incoming != NULL); |
6860 return incoming; | 6987 return incoming; |
6861 } | 6988 } |
6862 | 6989 |
6863 // Incoming values are different. Phi is required to merge. | 6990 // Incoming values are different. Phi is required to merge. |
6864 PhiInstr* phi = new PhiInstr( | 6991 PhiInstr* phi = new(isolate()) PhiInstr( |
6865 block->AsJoinEntry(), block->PredecessorCount()); | 6992 block->AsJoinEntry(), block->PredecessorCount()); |
6866 phi->set_place_id(place_id); | 6993 phi->set_place_id(place_id); |
6867 FillPhiInputs(phi); | 6994 FillPhiInputs(phi); |
6868 return phi; | 6995 return phi; |
6869 } | 6996 } |
6870 | 6997 |
6871 void FillPhiInputs(PhiInstr* phi) { | 6998 void FillPhiInputs(PhiInstr* phi) { |
6872 BlockEntryInstr* block = phi->GetBlock(); | 6999 BlockEntryInstr* block = phi->GetBlock(); |
6873 const intptr_t place_id = phi->place_id(); | 7000 const intptr_t place_id = phi->place_id(); |
6874 | 7001 |
6875 for (intptr_t i = 0; i < block->PredecessorCount(); i++) { | 7002 for (intptr_t i = 0; i < block->PredecessorCount(); i++) { |
6876 BlockEntryInstr* pred = block->PredecessorAt(i); | 7003 BlockEntryInstr* pred = block->PredecessorAt(i); |
6877 ZoneGrowableArray<Definition*>* pred_out_values = | 7004 ZoneGrowableArray<Definition*>* pred_out_values = |
6878 out_values_[pred->preorder_number()]; | 7005 out_values_[pred->preorder_number()]; |
6879 ASSERT((*pred_out_values)[place_id] != NULL); | 7006 ASSERT((*pred_out_values)[place_id] != NULL); |
6880 | 7007 |
6881 // Sets of outgoing values are not linked into use lists so | 7008 // Sets of outgoing values are not linked into use lists so |
6882 // they might contain values that were replaced and removed | 7009 // they might contain values that were replaced and removed |
6883 // from the graph by this iteration. | 7010 // from the graph by this iteration. |
6884 // To prevent using them we additionally mark definitions themselves | 7011 // To prevent using them we additionally mark definitions themselves |
6885 // as replaced and store a pointer to the replacement. | 7012 // as replaced and store a pointer to the replacement. |
6886 Definition* replacement = (*pred_out_values)[place_id]->Replacement(); | 7013 Definition* replacement = (*pred_out_values)[place_id]->Replacement(); |
6887 Value* input = new Value(replacement); | 7014 Value* input = new(isolate()) Value(replacement); |
6888 phi->SetInputAt(i, input); | 7015 phi->SetInputAt(i, input); |
6889 replacement->AddInputUse(input); | 7016 replacement->AddInputUse(input); |
6890 } | 7017 } |
6891 | 7018 |
6892 phi->set_ssa_temp_index(graph_->alloc_ssa_temp_index()); | 7019 phi->set_ssa_temp_index(graph_->alloc_ssa_temp_index()); |
6893 phis_.Add(phi); // Postpone phi insertion until after load forwarding. | 7020 phis_.Add(phi); // Postpone phi insertion until after load forwarding. |
6894 | 7021 |
6895 if (FLAG_trace_load_optimization) { | 7022 if (FLAG_trace_load_optimization) { |
6896 OS::Print("created pending phi %s for %s at B%" Pd "\n", | 7023 OS::Print("created pending phi %s for %s at B%" Pd "\n", |
6897 phi->ToCString(), | 7024 phi->ToCString(), |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6950 // Eliminate it as redundant if this is the case. | 7077 // Eliminate it as redundant if this is the case. |
6951 // When analyzing phi operands assumes that only generated during | 7078 // When analyzing phi operands assumes that only generated during |
6952 // this load phase can be redundant. They can be distinguished because | 7079 // this load phase can be redundant. They can be distinguished because |
6953 // they are not marked alive. | 7080 // they are not marked alive. |
6954 // TODO(vegorov): move this into a separate phase over all phis. | 7081 // TODO(vegorov): move this into a separate phase over all phis. |
6955 bool EliminateRedundantPhi(PhiInstr* phi) { | 7082 bool EliminateRedundantPhi(PhiInstr* phi) { |
6956 Definition* value = NULL; // Possible value of this phi. | 7083 Definition* value = NULL; // Possible value of this phi. |
6957 | 7084 |
6958 worklist_.Clear(); | 7085 worklist_.Clear(); |
6959 if (in_worklist_ == NULL) { | 7086 if (in_worklist_ == NULL) { |
6960 in_worklist_ = new BitVector(graph_->current_ssa_temp_index()); | 7087 in_worklist_ = new(isolate()) BitVector(graph_->current_ssa_temp_index()); |
6961 } else { | 7088 } else { |
6962 in_worklist_->Clear(); | 7089 in_worklist_->Clear(); |
6963 } | 7090 } |
6964 | 7091 |
6965 worklist_.Add(phi); | 7092 worklist_.Add(phi); |
6966 in_worklist_->Add(phi->ssa_temp_index()); | 7093 in_worklist_->Add(phi->ssa_temp_index()); |
6967 | 7094 |
6968 for (intptr_t i = 0; i < worklist_.length(); i++) { | 7095 for (intptr_t i = 0; i < worklist_.length(); i++) { |
6969 PhiInstr* phi = worklist_[i]; | 7096 PhiInstr* phi = worklist_[i]; |
6970 | 7097 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7023 } | 7150 } |
7024 | 7151 |
7025 // Replace the given phi with another if they are equal. | 7152 // Replace the given phi with another if they are equal. |
7026 // Returns true if succeeds. | 7153 // Returns true if succeeds. |
7027 bool ReplacePhiWith(PhiInstr* phi, PhiInstr* replacement) { | 7154 bool ReplacePhiWith(PhiInstr* phi, PhiInstr* replacement) { |
7028 ASSERT(phi->InputCount() == replacement->InputCount()); | 7155 ASSERT(phi->InputCount() == replacement->InputCount()); |
7029 ASSERT(phi->block() == replacement->block()); | 7156 ASSERT(phi->block() == replacement->block()); |
7030 | 7157 |
7031 worklist_.Clear(); | 7158 worklist_.Clear(); |
7032 if (in_worklist_ == NULL) { | 7159 if (in_worklist_ == NULL) { |
7033 in_worklist_ = new BitVector(graph_->current_ssa_temp_index()); | 7160 in_worklist_ = new(isolate()) BitVector(graph_->current_ssa_temp_index()); |
7034 } else { | 7161 } else { |
7035 in_worklist_->Clear(); | 7162 in_worklist_->Clear(); |
7036 } | 7163 } |
7037 | 7164 |
7038 // During the comparison worklist contains pairs of phis to be compared. | 7165 // During the comparison worklist contains pairs of phis to be compared. |
7039 AddPhiPairToWorklist(phi, replacement); | 7166 AddPhiPairToWorklist(phi, replacement); |
7040 | 7167 |
7041 // Process the worklist. It might grow during each comparison step. | 7168 // Process the worklist. It might grow during each comparison step. |
7042 for (intptr_t i = 0; i < worklist_.length(); i += 2) { | 7169 for (intptr_t i = 0; i < worklist_.length(); i += 2) { |
7043 PhiInstr* a = worklist_[i]; | 7170 PhiInstr* a = worklist_[i]; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7112 if ((phi != NULL) && (!phi->HasUses() || !EmitPhi(phi))) { | 7239 if ((phi != NULL) && (!phi->HasUses() || !EmitPhi(phi))) { |
7113 for (intptr_t j = phi->InputCount() - 1; j >= 0; --j) { | 7240 for (intptr_t j = phi->InputCount() - 1; j >= 0; --j) { |
7114 phi->InputAt(j)->RemoveFromUseList(); | 7241 phi->InputAt(j)->RemoveFromUseList(); |
7115 } | 7242 } |
7116 } | 7243 } |
7117 } | 7244 } |
7118 } | 7245 } |
7119 | 7246 |
7120 ZoneGrowableArray<Definition*>* CreateBlockOutValues() { | 7247 ZoneGrowableArray<Definition*>* CreateBlockOutValues() { |
7121 ZoneGrowableArray<Definition*>* out = | 7248 ZoneGrowableArray<Definition*>* out = |
7122 new ZoneGrowableArray<Definition*>(aliased_set_->max_place_id()); | 7249 new(isolate()) ZoneGrowableArray<Definition*>( |
| 7250 aliased_set_->max_place_id()); |
7123 for (intptr_t i = 0; i < aliased_set_->max_place_id(); i++) { | 7251 for (intptr_t i = 0; i < aliased_set_->max_place_id(); i++) { |
7124 out->Add(NULL); | 7252 out->Add(NULL); |
7125 } | 7253 } |
7126 return out; | 7254 return out; |
7127 } | 7255 } |
7128 | 7256 |
7129 FlowGraph* graph_; | 7257 FlowGraph* graph_; |
7130 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map_; | 7258 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map_; |
7131 | 7259 |
7132 // Mapping between field offsets in words and expression ids of loads from | 7260 // Mapping between field offsets in words and expression ids of loads from |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7216 case Instruction::kStoreIndexed: | 7344 case Instruction::kStoreIndexed: |
7217 case Instruction::kStoreStaticField: | 7345 case Instruction::kStoreStaticField: |
7218 return true; | 7346 return true; |
7219 default: | 7347 default: |
7220 UNREACHABLE(); | 7348 UNREACHABLE(); |
7221 return false; | 7349 return false; |
7222 } | 7350 } |
7223 } | 7351 } |
7224 | 7352 |
7225 virtual void ComputeInitialSets() { | 7353 virtual void ComputeInitialSets() { |
7226 BitVector* all_places = new BitVector(aliased_set_->max_place_id()); | 7354 Isolate* isolate = graph_->isolate(); |
| 7355 BitVector* all_places = new(isolate) BitVector( |
| 7356 aliased_set_->max_place_id()); |
7227 all_places->SetAll(); | 7357 all_places->SetAll(); |
7228 for (BlockIterator block_it = graph_->postorder_iterator(); | 7358 for (BlockIterator block_it = graph_->postorder_iterator(); |
7229 !block_it.Done(); | 7359 !block_it.Done(); |
7230 block_it.Advance()) { | 7360 block_it.Advance()) { |
7231 BlockEntryInstr* block = block_it.Current(); | 7361 BlockEntryInstr* block = block_it.Current(); |
7232 const intptr_t postorder_number = block->postorder_number(); | 7362 const intptr_t postorder_number = block->postorder_number(); |
7233 | 7363 |
7234 BitVector* kill = kill_[postorder_number]; | 7364 BitVector* kill = kill_[postorder_number]; |
7235 BitVector* live_in = live_in_[postorder_number]; | 7365 BitVector* live_in = live_in_[postorder_number]; |
7236 BitVector* live_out = live_out_[postorder_number]; | 7366 BitVector* live_out = live_out_[postorder_number]; |
(...skipping 24 matching lines...) Expand all Loading... |
7261 "Removing dead store to place %" Pd " in block B%" Pd "\n", | 7391 "Removing dead store to place %" Pd " in block B%" Pd "\n", |
7262 instr->place_id(), block->block_id()); | 7392 instr->place_id(), block->block_id()); |
7263 } | 7393 } |
7264 instr_it.RemoveCurrentFromGraph(); | 7394 instr_it.RemoveCurrentFromGraph(); |
7265 } | 7395 } |
7266 } else if (!live_in->Contains(instr->place_id())) { | 7396 } else if (!live_in->Contains(instr->place_id())) { |
7267 // Mark this store as down-ward exposed: They are the only | 7397 // Mark this store as down-ward exposed: They are the only |
7268 // candidates for the global store elimination. | 7398 // candidates for the global store elimination. |
7269 if (exposed_stores == NULL) { | 7399 if (exposed_stores == NULL) { |
7270 const intptr_t kMaxExposedStoresInitialSize = 5; | 7400 const intptr_t kMaxExposedStoresInitialSize = 5; |
7271 exposed_stores = new ZoneGrowableArray<Instruction*>( | 7401 exposed_stores = new(isolate) ZoneGrowableArray<Instruction*>( |
7272 Utils::Minimum(kMaxExposedStoresInitialSize, | 7402 Utils::Minimum(kMaxExposedStoresInitialSize, |
7273 aliased_set_->max_place_id())); | 7403 aliased_set_->max_place_id())); |
7274 } | 7404 } |
7275 exposed_stores->Add(instr); | 7405 exposed_stores->Add(instr); |
7276 } | 7406 } |
7277 // Interfering stores kill only loads from the same place. | 7407 // Interfering stores kill only loads from the same place. |
7278 kill->Add(instr->place_id()); | 7408 kill->Add(instr->place_id()); |
7279 live_in->Remove(instr->place_id()); | 7409 live_in->Remove(instr->place_id()); |
7280 continue; | 7410 continue; |
7281 } | 7411 } |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7557 } | 7687 } |
7558 | 7688 |
7559 | 7689 |
7560 ConstantPropagator::ConstantPropagator( | 7690 ConstantPropagator::ConstantPropagator( |
7561 FlowGraph* graph, | 7691 FlowGraph* graph, |
7562 const GrowableArray<BlockEntryInstr*>& ignored) | 7692 const GrowableArray<BlockEntryInstr*>& ignored) |
7563 : FlowGraphVisitor(ignored), | 7693 : FlowGraphVisitor(ignored), |
7564 graph_(graph), | 7694 graph_(graph), |
7565 unknown_(Object::unknown_constant()), | 7695 unknown_(Object::unknown_constant()), |
7566 non_constant_(Object::non_constant()), | 7696 non_constant_(Object::non_constant()), |
7567 reachable_(new BitVector(graph->preorder().length())), | 7697 reachable_(new(graph->isolate()) BitVector(graph->preorder().length())), |
7568 definition_marks_(new BitVector(graph->max_virtual_register_number())), | 7698 definition_marks_(new(graph->isolate()) BitVector( |
| 7699 graph->max_virtual_register_number())), |
7569 block_worklist_(), | 7700 block_worklist_(), |
7570 definition_worklist_() {} | 7701 definition_worklist_() {} |
7571 | 7702 |
7572 | 7703 |
7573 void ConstantPropagator::Optimize(FlowGraph* graph) { | 7704 void ConstantPropagator::Optimize(FlowGraph* graph) { |
7574 GrowableArray<BlockEntryInstr*> ignored; | 7705 GrowableArray<BlockEntryInstr*> ignored; |
7575 ConstantPropagator cp(graph, ignored); | 7706 ConstantPropagator cp(graph, ignored); |
7576 cp.Analyze(); | 7707 cp.Analyze(); |
7577 cp.Transform(); | 7708 cp.Transform(); |
7578 } | 7709 } |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7764 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) { } | 7895 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) { } |
7765 | 7896 |
7766 | 7897 |
7767 // -------------------------------------------------------------------------- | 7898 // -------------------------------------------------------------------------- |
7768 // Analysis of definitions. Compute the constant value. If it has changed | 7899 // Analysis of definitions. Compute the constant value. If it has changed |
7769 // and the definition has input uses, add the definition to the definition | 7900 // and the definition has input uses, add the definition to the definition |
7770 // worklist so that the used can be processed. | 7901 // worklist so that the used can be processed. |
7771 void ConstantPropagator::VisitPhi(PhiInstr* instr) { | 7902 void ConstantPropagator::VisitPhi(PhiInstr* instr) { |
7772 // Compute the join over all the reachable predecessor values. | 7903 // Compute the join over all the reachable predecessor values. |
7773 JoinEntryInstr* block = instr->block(); | 7904 JoinEntryInstr* block = instr->block(); |
7774 Object& value = Object::ZoneHandle(Unknown()); | 7905 Object& value = Object::ZoneHandle(isolate(), Unknown()); |
7775 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { | 7906 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { |
7776 if (reachable_->Contains( | 7907 if (reachable_->Contains( |
7777 block->PredecessorAt(pred_idx)->preorder_number())) { | 7908 block->PredecessorAt(pred_idx)->preorder_number())) { |
7778 Join(&value, | 7909 Join(&value, |
7779 instr->InputAt(pred_idx)->definition()->constant_value()); | 7910 instr->InputAt(pred_idx)->definition()->constant_value()); |
7780 } | 7911 } |
7781 } | 7912 } |
7782 SetValue(instr, value); | 7913 SetValue(instr, value); |
7783 } | 7914 } |
7784 | 7915 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7881 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { | 8012 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { |
7882 instr->comparison()->Accept(this); | 8013 instr->comparison()->Accept(this); |
7883 const Object& value = instr->comparison()->constant_value(); | 8014 const Object& value = instr->comparison()->constant_value(); |
7884 if (IsNonConstant(value)) { | 8015 if (IsNonConstant(value)) { |
7885 SetValue(instr, non_constant_); | 8016 SetValue(instr, non_constant_); |
7886 } else if (IsConstant(value)) { | 8017 } else if (IsConstant(value)) { |
7887 ASSERT(!value.IsNull()); | 8018 ASSERT(!value.IsNull()); |
7888 ASSERT(value.IsBool()); | 8019 ASSERT(value.IsBool()); |
7889 bool result = Bool::Cast(value).value(); | 8020 bool result = Bool::Cast(value).value(); |
7890 SetValue(instr, | 8021 SetValue(instr, |
7891 Smi::Handle(Smi::New( | 8022 Smi::Handle(isolate(), Smi::New( |
7892 result ? instr->if_true() : instr->if_false()))); | 8023 result ? instr->if_true() : instr->if_false()))); |
7893 } | 8024 } |
7894 } | 8025 } |
7895 | 8026 |
7896 | 8027 |
7897 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { | 8028 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { |
7898 const Object& left = instr->left()->definition()->constant_value(); | 8029 const Object& left = instr->left()->definition()->constant_value(); |
7899 const Object& right = instr->right()->definition()->constant_value(); | 8030 const Object& right = instr->right()->definition()->constant_value(); |
7900 | 8031 |
7901 if (instr->left()->definition() == instr->right()->definition()) { | 8032 if (instr->left()->definition() == instr->right()->definition()) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7957 | 8088 |
7958 void ConstantPropagator::VisitTestSmi(TestSmiInstr* instr) { | 8089 void ConstantPropagator::VisitTestSmi(TestSmiInstr* instr) { |
7959 const Object& left = instr->left()->definition()->constant_value(); | 8090 const Object& left = instr->left()->definition()->constant_value(); |
7960 const Object& right = instr->right()->definition()->constant_value(); | 8091 const Object& right = instr->right()->definition()->constant_value(); |
7961 if (IsNonConstant(left) || IsNonConstant(right)) { | 8092 if (IsNonConstant(left) || IsNonConstant(right)) { |
7962 SetValue(instr, non_constant_); | 8093 SetValue(instr, non_constant_); |
7963 } else if (IsConstant(left) && IsConstant(right)) { | 8094 } else if (IsConstant(left) && IsConstant(right)) { |
7964 if (left.IsInteger() && right.IsInteger()) { | 8095 if (left.IsInteger() && right.IsInteger()) { |
7965 const bool result = CompareIntegers( | 8096 const bool result = CompareIntegers( |
7966 instr->kind(), | 8097 instr->kind(), |
7967 Integer::Handle(Integer::Cast(left).BitOp(Token::kBIT_AND, | 8098 Integer::Handle(isolate(), |
| 8099 Integer::Cast(left).BitOp(Token::kBIT_AND, |
7968 Integer::Cast(right))), | 8100 Integer::Cast(right))), |
7969 Smi::Handle(Smi::New(0))); | 8101 Smi::Handle(isolate(), Smi::New(0))); |
7970 SetValue(instr, result ? Bool::True() : Bool::False()); | 8102 SetValue(instr, result ? Bool::True() : Bool::False()); |
7971 } else { | 8103 } else { |
7972 SetValue(instr, non_constant_); | 8104 SetValue(instr, non_constant_); |
7973 } | 8105 } |
7974 } | 8106 } |
7975 } | 8107 } |
7976 | 8108 |
7977 | 8109 |
7978 void ConstantPropagator::VisitTestCids(TestCidsInstr* instr) { | 8110 void ConstantPropagator::VisitTestCids(TestCidsInstr* instr) { |
7979 SetValue(instr, non_constant_); | 8111 SetValue(instr, non_constant_); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8043 void ConstantPropagator::VisitStringFromCharCode( | 8175 void ConstantPropagator::VisitStringFromCharCode( |
8044 StringFromCharCodeInstr* instr) { | 8176 StringFromCharCodeInstr* instr) { |
8045 const Object& o = instr->char_code()->definition()->constant_value(); | 8177 const Object& o = instr->char_code()->definition()->constant_value(); |
8046 if (o.IsNull() || IsNonConstant(o)) { | 8178 if (o.IsNull() || IsNonConstant(o)) { |
8047 SetValue(instr, non_constant_); | 8179 SetValue(instr, non_constant_); |
8048 } else if (IsConstant(o)) { | 8180 } else if (IsConstant(o)) { |
8049 const intptr_t ch_code = Smi::Cast(o).Value(); | 8181 const intptr_t ch_code = Smi::Cast(o).Value(); |
8050 ASSERT(ch_code >= 0); | 8182 ASSERT(ch_code >= 0); |
8051 if (ch_code < Symbols::kMaxOneCharCodeSymbol) { | 8183 if (ch_code < Symbols::kMaxOneCharCodeSymbol) { |
8052 RawString** table = Symbols::PredefinedAddress(); | 8184 RawString** table = Symbols::PredefinedAddress(); |
8053 SetValue(instr, String::ZoneHandle(table[ch_code])); | 8185 SetValue(instr, String::ZoneHandle(isolate(), table[ch_code])); |
8054 } else { | 8186 } else { |
8055 SetValue(instr, non_constant_); | 8187 SetValue(instr, non_constant_); |
8056 } | 8188 } |
8057 } | 8189 } |
8058 } | 8190 } |
8059 | 8191 |
8060 | 8192 |
8061 void ConstantPropagator::VisitStringToCharCode(StringToCharCodeInstr* instr) { | 8193 void ConstantPropagator::VisitStringToCharCode(StringToCharCodeInstr* instr) { |
8062 const Object& o = instr->str()->definition()->constant_value(); | 8194 const Object& o = instr->str()->definition()->constant_value(); |
8063 if (o.IsNull() || IsNonConstant(o)) { | 8195 if (o.IsNull() || IsNonConstant(o)) { |
8064 SetValue(instr, non_constant_); | 8196 SetValue(instr, non_constant_); |
8065 } else if (IsConstant(o)) { | 8197 } else if (IsConstant(o)) { |
8066 const String& str = String::Cast(o); | 8198 const String& str = String::Cast(o); |
8067 const intptr_t result = (str.Length() == 1) ? str.CharAt(0) : -1; | 8199 const intptr_t result = (str.Length() == 1) ? str.CharAt(0) : -1; |
8068 SetValue(instr, Smi::ZoneHandle(Smi::New(result))); | 8200 SetValue(instr, Smi::ZoneHandle(isolate(), Smi::New(result))); |
8069 } | 8201 } |
8070 } | 8202 } |
8071 | 8203 |
8072 | 8204 |
8073 | 8205 |
8074 | 8206 |
8075 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) { | 8207 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) { |
8076 SetValue(instr, non_constant_); | 8208 SetValue(instr, non_constant_); |
8077 return; | 8209 return; |
8078 } | 8210 } |
8079 | 8211 |
8080 | 8212 |
8081 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { | 8213 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { |
8082 const Object& array_obj = instr->array()->definition()->constant_value(); | 8214 const Object& array_obj = instr->array()->definition()->constant_value(); |
8083 const Object& index_obj = instr->index()->definition()->constant_value(); | 8215 const Object& index_obj = instr->index()->definition()->constant_value(); |
8084 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) { | 8216 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) { |
8085 SetValue(instr, non_constant_); | 8217 SetValue(instr, non_constant_); |
8086 } else if (IsConstant(array_obj) && IsConstant(index_obj)) { | 8218 } else if (IsConstant(array_obj) && IsConstant(index_obj)) { |
8087 // Need index to be Smi and array to be either String or an immutable array. | 8219 // Need index to be Smi and array to be either String or an immutable array. |
8088 if (!index_obj.IsSmi()) { | 8220 if (!index_obj.IsSmi()) { |
8089 // Should not occur. | 8221 // Should not occur. |
8090 SetValue(instr, non_constant_); | 8222 SetValue(instr, non_constant_); |
8091 return; | 8223 return; |
8092 } | 8224 } |
8093 const intptr_t index = Smi::Cast(index_obj).Value(); | 8225 const intptr_t index = Smi::Cast(index_obj).Value(); |
8094 if (index >= 0) { | 8226 if (index >= 0) { |
8095 if (array_obj.IsString()) { | 8227 if (array_obj.IsString()) { |
8096 const String& str = String::Cast(array_obj); | 8228 const String& str = String::Cast(array_obj); |
8097 if (str.Length() > index) { | 8229 if (str.Length() > index) { |
8098 SetValue(instr, Smi::Handle(Smi::New(str.CharAt(index)))); | 8230 SetValue(instr, Smi::Handle(isolate(), Smi::New(str.CharAt(index)))); |
8099 return; | 8231 return; |
8100 } | 8232 } |
8101 } else if (array_obj.IsArray()) { | 8233 } else if (array_obj.IsArray()) { |
8102 const Array& a = Array::Cast(array_obj); | 8234 const Array& a = Array::Cast(array_obj); |
8103 if ((a.Length() > index) && a.IsImmutable()) { | 8235 if ((a.Length() > index) && a.IsImmutable()) { |
8104 Instance& result = Instance::Handle(); | 8236 Instance& result = Instance::Handle(isolate(), Instance::null()); |
8105 result ^= a.At(index); | 8237 result ^= a.At(index); |
8106 SetValue(instr, result); | 8238 SetValue(instr, result); |
8107 return; | 8239 return; |
8108 } | 8240 } |
8109 } | 8241 } |
8110 } | 8242 } |
8111 SetValue(instr, non_constant_); | 8243 SetValue(instr, non_constant_); |
8112 } | 8244 } |
8113 } | 8245 } |
8114 | 8246 |
8115 | 8247 |
8116 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { | 8248 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { |
8117 SetValue(instr, instr->value()->definition()->constant_value()); | 8249 SetValue(instr, instr->value()->definition()->constant_value()); |
8118 } | 8250 } |
8119 | 8251 |
8120 | 8252 |
8121 void ConstantPropagator::VisitStoreInstanceField( | 8253 void ConstantPropagator::VisitStoreInstanceField( |
8122 StoreInstanceFieldInstr* instr) { | 8254 StoreInstanceFieldInstr* instr) { |
8123 SetValue(instr, instr->value()->definition()->constant_value()); | 8255 SetValue(instr, instr->value()->definition()->constant_value()); |
8124 } | 8256 } |
8125 | 8257 |
8126 | 8258 |
8127 void ConstantPropagator::VisitLoadStaticField(LoadStaticFieldInstr* instr) { | 8259 void ConstantPropagator::VisitLoadStaticField(LoadStaticFieldInstr* instr) { |
8128 const Field& field = instr->StaticField(); | 8260 const Field& field = instr->StaticField(); |
8129 ASSERT(field.is_static()); | 8261 ASSERT(field.is_static()); |
8130 if (field.is_final()) { | 8262 if (field.is_final()) { |
8131 Instance& obj = Instance::Handle(field.value()); | 8263 Instance& obj = Instance::Handle(isolate(), field.value()); |
8132 ASSERT(obj.raw() != Object::sentinel().raw()); | 8264 ASSERT(obj.raw() != Object::sentinel().raw()); |
8133 ASSERT(obj.raw() != Object::transition_sentinel().raw()); | 8265 ASSERT(obj.raw() != Object::transition_sentinel().raw()); |
8134 if (obj.IsSmi() || obj.IsOld()) { | 8266 if (obj.IsSmi() || obj.IsOld()) { |
8135 SetValue(instr, obj); | 8267 SetValue(instr, obj); |
8136 return; | 8268 return; |
8137 } | 8269 } |
8138 } | 8270 } |
8139 SetValue(instr, non_constant_); | 8271 SetValue(instr, non_constant_); |
8140 } | 8272 } |
8141 | 8273 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8196 | 8328 |
8197 | 8329 |
8198 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) { | 8330 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) { |
8199 SetValue(instr, non_constant_); | 8331 SetValue(instr, non_constant_); |
8200 } | 8332 } |
8201 | 8333 |
8202 | 8334 |
8203 void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) { | 8335 void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) { |
8204 intptr_t cid = instr->object()->Type()->ToCid(); | 8336 intptr_t cid = instr->object()->Type()->ToCid(); |
8205 if (cid != kDynamicCid) { | 8337 if (cid != kDynamicCid) { |
8206 SetValue(instr, Smi::ZoneHandle(Smi::New(cid))); | 8338 SetValue(instr, Smi::ZoneHandle(isolate(), Smi::New(cid))); |
8207 return; | 8339 return; |
8208 } | 8340 } |
8209 const Object& object = instr->object()->definition()->constant_value(); | 8341 const Object& object = instr->object()->definition()->constant_value(); |
8210 if (IsConstant(object)) { | 8342 if (IsConstant(object)) { |
8211 SetValue(instr, Smi::ZoneHandle(Smi::New(object.GetClassId()))); | 8343 SetValue(instr, Smi::ZoneHandle(isolate(), Smi::New(object.GetClassId()))); |
8212 return; | 8344 return; |
8213 } | 8345 } |
8214 SetValue(instr, non_constant_); | 8346 SetValue(instr, non_constant_); |
8215 } | 8347 } |
8216 | 8348 |
8217 | 8349 |
8218 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { | 8350 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { |
8219 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && | 8351 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && |
8220 (instr->instance()->definition()->IsCreateArray())) { | 8352 (instr->instance()->definition()->IsCreateArray())) { |
8221 Value* num_elements = | 8353 Value* num_elements = |
8222 instr->instance()->definition()->AsCreateArray()->num_elements(); | 8354 instr->instance()->definition()->AsCreateArray()->num_elements(); |
8223 if (num_elements->BindsToConstant() && | 8355 if (num_elements->BindsToConstant() && |
8224 num_elements->BoundConstant().IsSmi()) { | 8356 num_elements->BoundConstant().IsSmi()) { |
8225 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); | 8357 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); |
8226 const Object& result = Smi::ZoneHandle(Smi::New(length)); | 8358 const Object& result = Smi::ZoneHandle(isolate(), Smi::New(length)); |
8227 SetValue(instr, result); | 8359 SetValue(instr, result); |
8228 return; | 8360 return; |
8229 } | 8361 } |
8230 } | 8362 } |
8231 | 8363 |
8232 if (instr->IsImmutableLengthLoad()) { | 8364 if (instr->IsImmutableLengthLoad()) { |
8233 ConstantInstr* constant = instr->instance()->definition()->AsConstant(); | 8365 ConstantInstr* constant = instr->instance()->definition()->AsConstant(); |
8234 if (constant != NULL) { | 8366 if (constant != NULL) { |
8235 if (constant->value().IsString()) { | 8367 if (constant->value().IsString()) { |
8236 SetValue(instr, Smi::ZoneHandle( | 8368 SetValue(instr, Smi::ZoneHandle(isolate(), |
8237 Smi::New(String::Cast(constant->value()).Length()))); | 8369 Smi::New(String::Cast(constant->value()).Length()))); |
8238 return; | 8370 return; |
8239 } | 8371 } |
8240 if (constant->value().IsArray()) { | 8372 if (constant->value().IsArray()) { |
8241 SetValue(instr, Smi::ZoneHandle( | 8373 SetValue(instr, Smi::ZoneHandle(isolate(), |
8242 Smi::New(Array::Cast(constant->value()).Length()))); | 8374 Smi::New(Array::Cast(constant->value()).Length()))); |
8243 return; | 8375 return; |
8244 } | 8376 } |
8245 } | 8377 } |
8246 } | 8378 } |
8247 SetValue(instr, non_constant_); | 8379 SetValue(instr, non_constant_); |
8248 } | 8380 } |
8249 | 8381 |
8250 | 8382 |
8251 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) { | 8383 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) { |
8252 const Object& object = | 8384 const Object& object = |
8253 instr->instantiator()->definition()->constant_value(); | 8385 instr->instantiator()->definition()->constant_value(); |
8254 if (IsNonConstant(object)) { | 8386 if (IsNonConstant(object)) { |
8255 SetValue(instr, non_constant_); | 8387 SetValue(instr, non_constant_); |
8256 return; | 8388 return; |
8257 } | 8389 } |
8258 if (IsConstant(object)) { | 8390 if (IsConstant(object)) { |
8259 if (instr->type().IsTypeParameter()) { | 8391 if (instr->type().IsTypeParameter()) { |
8260 if (object.IsNull()) { | 8392 if (object.IsNull()) { |
8261 SetValue(instr, Type::ZoneHandle(Type::DynamicType())); | 8393 SetValue(instr, Type::ZoneHandle(isolate(), Type::DynamicType())); |
8262 return; | 8394 return; |
8263 } | 8395 } |
8264 // We could try to instantiate the type parameter and return it if no | 8396 // We could try to instantiate the type parameter and return it if no |
8265 // malformed error is reported. | 8397 // malformed error is reported. |
8266 } | 8398 } |
8267 SetValue(instr, non_constant_); | 8399 SetValue(instr, non_constant_); |
8268 } | 8400 } |
8269 } | 8401 } |
8270 | 8402 |
8271 | 8403 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8323 case Token::kMOD: | 8455 case Token::kMOD: |
8324 // Check right value for zero. | 8456 // Check right value for zero. |
8325 if (right_int.AsInt64Value() == 0) { | 8457 if (right_int.AsInt64Value() == 0) { |
8326 SetValue(instr, non_constant_); | 8458 SetValue(instr, non_constant_); |
8327 break; | 8459 break; |
8328 } | 8460 } |
8329 // Fall through. | 8461 // Fall through. |
8330 case Token::kADD: | 8462 case Token::kADD: |
8331 case Token::kSUB: | 8463 case Token::kSUB: |
8332 case Token::kMUL: { | 8464 case Token::kMUL: { |
8333 Instance& result = Integer::ZoneHandle( | 8465 Instance& result = Integer::ZoneHandle(isolate(), |
8334 left_int.ArithmeticOp(op_kind, right_int)); | 8466 left_int.ArithmeticOp(op_kind, right_int)); |
8335 result = result.CheckAndCanonicalize(NULL); | 8467 result = result.CheckAndCanonicalize(NULL); |
8336 ASSERT(!result.IsNull()); | 8468 ASSERT(!result.IsNull()); |
8337 SetValue(instr, result); | 8469 SetValue(instr, result); |
8338 break; | 8470 break; |
8339 } | 8471 } |
8340 case Token::kSHL: | 8472 case Token::kSHL: |
8341 case Token::kSHR: | 8473 case Token::kSHR: |
8342 if (left.IsSmi() && right.IsSmi()) { | 8474 if (left.IsSmi() && right.IsSmi()) { |
8343 Instance& result = Integer::ZoneHandle( | 8475 Instance& result = Integer::ZoneHandle(isolate(), |
8344 Smi::Cast(left_int).ShiftOp(op_kind, Smi::Cast(right_int))); | 8476 Smi::Cast(left_int).ShiftOp(op_kind, Smi::Cast(right_int))); |
8345 result = result.CheckAndCanonicalize(NULL); | 8477 result = result.CheckAndCanonicalize(NULL); |
8346 ASSERT(!result.IsNull()); | 8478 ASSERT(!result.IsNull()); |
8347 SetValue(instr, result); | 8479 SetValue(instr, result); |
8348 } else { | 8480 } else { |
8349 SetValue(instr, non_constant_); | 8481 SetValue(instr, non_constant_); |
8350 } | 8482 } |
8351 break; | 8483 break; |
8352 case Token::kBIT_AND: | 8484 case Token::kBIT_AND: |
8353 case Token::kBIT_OR: | 8485 case Token::kBIT_OR: |
8354 case Token::kBIT_XOR: { | 8486 case Token::kBIT_XOR: { |
8355 Instance& result = Integer::ZoneHandle( | 8487 Instance& result = Integer::ZoneHandle(isolate(), |
8356 left_int.BitOp(op_kind, right_int)); | 8488 left_int.BitOp(op_kind, right_int)); |
8357 result = result.CheckAndCanonicalize(NULL); | 8489 result = result.CheckAndCanonicalize(NULL); |
8358 ASSERT(!result.IsNull()); | 8490 ASSERT(!result.IsNull()); |
8359 SetValue(instr, result); | 8491 SetValue(instr, result); |
8360 break; | 8492 break; |
8361 } | 8493 } |
8362 case Token::kDIV: | 8494 case Token::kDIV: |
8363 SetValue(instr, non_constant_); | 8495 SetValue(instr, non_constant_); |
8364 break; | 8496 break; |
8365 default: | 8497 default: |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8424 } else if (IsConstant(value)) { | 8556 } else if (IsConstant(value)) { |
8425 // TODO(kmillikin): Handle unary operations. | 8557 // TODO(kmillikin): Handle unary operations. |
8426 SetValue(instr, non_constant_); | 8558 SetValue(instr, non_constant_); |
8427 } | 8559 } |
8428 } | 8560 } |
8429 | 8561 |
8430 | 8562 |
8431 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { | 8563 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { |
8432 const Object& value = instr->value()->definition()->constant_value(); | 8564 const Object& value = instr->value()->definition()->constant_value(); |
8433 if (IsConstant(value) && value.IsInteger()) { | 8565 if (IsConstant(value) && value.IsInteger()) { |
8434 SetValue(instr, Double::Handle( | 8566 SetValue(instr, Double::Handle(isolate(), |
8435 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); | 8567 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); |
8436 } else if (IsNonConstant(value)) { | 8568 } else if (IsNonConstant(value)) { |
8437 SetValue(instr, non_constant_); | 8569 SetValue(instr, non_constant_); |
8438 } | 8570 } |
8439 } | 8571 } |
8440 | 8572 |
8441 | 8573 |
8442 void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) { | 8574 void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) { |
8443 // TODO(kmillikin): Handle conversion. | 8575 // TODO(kmillikin): Handle conversion. |
8444 SetValue(instr, non_constant_); | 8576 SetValue(instr, non_constant_); |
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8887 current = current->next()->AsGoto()->successor(); | 9019 current = current->next()->AsGoto()->successor(); |
8888 } | 9020 } |
8889 return current; | 9021 return current; |
8890 } | 9022 } |
8891 | 9023 |
8892 | 9024 |
8893 void ConstantPropagator::EliminateRedundantBranches() { | 9025 void ConstantPropagator::EliminateRedundantBranches() { |
8894 // Canonicalize branches that have no side-effects and where true- and | 9026 // Canonicalize branches that have no side-effects and where true- and |
8895 // false-targets are the same. | 9027 // false-targets are the same. |
8896 bool changed = false; | 9028 bool changed = false; |
8897 BitVector* empty_blocks = new BitVector(graph_->preorder().length()); | 9029 BitVector* empty_blocks = |
| 9030 new(graph_->isolate()) BitVector(graph_->preorder().length()); |
8898 for (BlockIterator b = graph_->postorder_iterator(); | 9031 for (BlockIterator b = graph_->postorder_iterator(); |
8899 !b.Done(); | 9032 !b.Done(); |
8900 b.Advance()) { | 9033 b.Advance()) { |
8901 BlockEntryInstr* block = b.Current(); | 9034 BlockEntryInstr* block = b.Current(); |
8902 BranchInstr* branch = block->last_instruction()->AsBranch(); | 9035 BranchInstr* branch = block->last_instruction()->AsBranch(); |
8903 empty_blocks->Clear(); | 9036 empty_blocks->Clear(); |
8904 if ((branch != NULL) && branch->Effects().IsNone()) { | 9037 if ((branch != NULL) && branch->Effects().IsNone()) { |
8905 ASSERT(branch->previous() != NULL); // Not already eliminated. | 9038 ASSERT(branch->previous() != NULL); // Not already eliminated. |
8906 BlockEntryInstr* if_true = | 9039 BlockEntryInstr* if_true = |
8907 FindFirstNonEmptySuccessor(branch->true_successor(), empty_blocks); | 9040 FindFirstNonEmptySuccessor(branch->true_successor(), empty_blocks); |
8908 BlockEntryInstr* if_false = | 9041 BlockEntryInstr* if_false = |
8909 FindFirstNonEmptySuccessor(branch->false_successor(), empty_blocks); | 9042 FindFirstNonEmptySuccessor(branch->false_successor(), empty_blocks); |
8910 if (if_true == if_false) { | 9043 if (if_true == if_false) { |
8911 // Replace the branch with a jump to the common successor. | 9044 // Replace the branch with a jump to the common successor. |
8912 // Drop the comparison, which does not have side effects | 9045 // Drop the comparison, which does not have side effects |
8913 JoinEntryInstr* join = if_true->AsJoinEntry(); | 9046 JoinEntryInstr* join = if_true->AsJoinEntry(); |
8914 if (join->phis() == NULL) { | 9047 if (join->phis() == NULL) { |
8915 GotoInstr* jump = new GotoInstr(if_true->AsJoinEntry()); | 9048 GotoInstr* jump = |
8916 jump->InheritDeoptTarget(branch); | 9049 new(graph_->isolate()) GotoInstr(if_true->AsJoinEntry()); |
| 9050 jump->InheritDeoptTarget(isolate(), branch); |
8917 | 9051 |
8918 Instruction* previous = branch->previous(); | 9052 Instruction* previous = branch->previous(); |
8919 branch->set_previous(NULL); | 9053 branch->set_previous(NULL); |
8920 previous->LinkTo(jump); | 9054 previous->LinkTo(jump); |
8921 | 9055 |
8922 // Remove uses from branch and all the empty blocks that | 9056 // Remove uses from branch and all the empty blocks that |
8923 // are now unreachable. | 9057 // are now unreachable. |
8924 branch->UnuseAllInputs(); | 9058 branch->UnuseAllInputs(); |
8925 for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) { | 9059 for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) { |
8926 BlockEntryInstr* empty_block = graph_->preorder()[it.Current()]; | 9060 BlockEntryInstr* empty_block = graph_->preorder()[it.Current()]; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9051 if (branch != NULL) { | 9185 if (branch != NULL) { |
9052 TargetEntryInstr* if_true = branch->true_successor(); | 9186 TargetEntryInstr* if_true = branch->true_successor(); |
9053 TargetEntryInstr* if_false = branch->false_successor(); | 9187 TargetEntryInstr* if_false = branch->false_successor(); |
9054 JoinEntryInstr* join = NULL; | 9188 JoinEntryInstr* join = NULL; |
9055 Instruction* next = NULL; | 9189 Instruction* next = NULL; |
9056 | 9190 |
9057 if (!reachable_->Contains(if_true->preorder_number())) { | 9191 if (!reachable_->Contains(if_true->preorder_number())) { |
9058 ASSERT(reachable_->Contains(if_false->preorder_number())); | 9192 ASSERT(reachable_->Contains(if_false->preorder_number())); |
9059 ASSERT(if_false->parallel_move() == NULL); | 9193 ASSERT(if_false->parallel_move() == NULL); |
9060 ASSERT(if_false->loop_info() == NULL); | 9194 ASSERT(if_false->loop_info() == NULL); |
9061 join = new JoinEntryInstr(if_false->block_id(), if_false->try_index()); | 9195 join = new(isolate()) JoinEntryInstr(if_false->block_id(), |
9062 join->InheritDeoptTarget(if_false); | 9196 if_false->try_index()); |
| 9197 join->InheritDeoptTarget(isolate(), if_false); |
9063 if_false->UnuseAllInputs(); | 9198 if_false->UnuseAllInputs(); |
9064 next = if_false->next(); | 9199 next = if_false->next(); |
9065 } else if (!reachable_->Contains(if_false->preorder_number())) { | 9200 } else if (!reachable_->Contains(if_false->preorder_number())) { |
9066 ASSERT(if_true->parallel_move() == NULL); | 9201 ASSERT(if_true->parallel_move() == NULL); |
9067 ASSERT(if_true->loop_info() == NULL); | 9202 ASSERT(if_true->loop_info() == NULL); |
9068 join = new JoinEntryInstr(if_true->block_id(), if_true->try_index()); | 9203 join = new(isolate()) JoinEntryInstr(if_true->block_id(), |
9069 join->InheritDeoptTarget(if_true); | 9204 if_true->try_index()); |
| 9205 join->InheritDeoptTarget(isolate(), if_true); |
9070 if_true->UnuseAllInputs(); | 9206 if_true->UnuseAllInputs(); |
9071 next = if_true->next(); | 9207 next = if_true->next(); |
9072 } | 9208 } |
9073 | 9209 |
9074 if (join != NULL) { | 9210 if (join != NULL) { |
9075 // Replace the branch with a jump to the reachable successor. | 9211 // Replace the branch with a jump to the reachable successor. |
9076 // Drop the comparison, which does not have side effects as long | 9212 // Drop the comparison, which does not have side effects as long |
9077 // as it is a strict compare (the only one we can determine is | 9213 // as it is a strict compare (the only one we can determine is |
9078 // constant with the current analysis). | 9214 // constant with the current analysis). |
9079 GotoInstr* jump = new GotoInstr(join); | 9215 GotoInstr* jump = new(isolate()) GotoInstr(join); |
9080 jump->InheritDeoptTarget(branch); | 9216 jump->InheritDeoptTarget(isolate(), branch); |
9081 | 9217 |
9082 Instruction* previous = branch->previous(); | 9218 Instruction* previous = branch->previous(); |
9083 branch->set_previous(NULL); | 9219 branch->set_previous(NULL); |
9084 previous->LinkTo(jump); | 9220 previous->LinkTo(jump); |
9085 | 9221 |
9086 // Replace the false target entry with the new join entry. We will | 9222 // Replace the false target entry with the new join entry. We will |
9087 // recompute the dominators after this pass. | 9223 // recompute the dominators after this pass. |
9088 join->LinkTo(next); | 9224 join->LinkTo(next); |
9089 branch->UnuseAllInputs(); | 9225 branch->UnuseAllInputs(); |
9090 } | 9226 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9145 (right == NULL) ? NULL : right->definition()->AsConstant(); | 9281 (right == NULL) ? NULL : right->definition()->AsConstant(); |
9146 return (phi != NULL) && | 9282 return (phi != NULL) && |
9147 (constant != NULL) && | 9283 (constant != NULL) && |
9148 (phi->GetBlock() == block) && | 9284 (phi->GetBlock() == block) && |
9149 PhiHasSingleUse(phi, left) && | 9285 PhiHasSingleUse(phi, left) && |
9150 (block->next() == branch) && | 9286 (block->next() == branch) && |
9151 (block->phis()->length() == 1); | 9287 (block->phis()->length() == 1); |
9152 } | 9288 } |
9153 | 9289 |
9154 | 9290 |
9155 JoinEntryInstr* BranchSimplifier::ToJoinEntry(TargetEntryInstr* target) { | 9291 JoinEntryInstr* BranchSimplifier::ToJoinEntry(Isolate* isolate, |
| 9292 TargetEntryInstr* target) { |
9156 // Convert a target block into a join block. Branches will be duplicated | 9293 // Convert a target block into a join block. Branches will be duplicated |
9157 // so the former true and false targets become joins of the control flows | 9294 // so the former true and false targets become joins of the control flows |
9158 // from all the duplicated branches. | 9295 // from all the duplicated branches. |
9159 JoinEntryInstr* join = | 9296 JoinEntryInstr* join = |
9160 new JoinEntryInstr(target->block_id(), target->try_index()); | 9297 new(isolate) JoinEntryInstr(target->block_id(), target->try_index()); |
9161 join->InheritDeoptTarget(target); | 9298 join->InheritDeoptTarget(isolate, target); |
9162 join->LinkTo(target->next()); | 9299 join->LinkTo(target->next()); |
9163 join->set_last_instruction(target->last_instruction()); | 9300 join->set_last_instruction(target->last_instruction()); |
9164 target->UnuseAllInputs(); | 9301 target->UnuseAllInputs(); |
9165 return join; | 9302 return join; |
9166 } | 9303 } |
9167 | 9304 |
9168 | 9305 |
9169 BranchInstr* BranchSimplifier::CloneBranch(BranchInstr* branch, | 9306 BranchInstr* BranchSimplifier::CloneBranch(Isolate* isolate, |
| 9307 BranchInstr* branch, |
9170 Value* new_left, | 9308 Value* new_left, |
9171 Value* new_right) { | 9309 Value* new_right) { |
9172 ComparisonInstr* comparison = branch->comparison(); | 9310 ComparisonInstr* comparison = branch->comparison(); |
9173 ComparisonInstr* new_comparison = | 9311 ComparisonInstr* new_comparison = |
9174 comparison->CopyWithNewOperands(new_left, new_right); | 9312 comparison->CopyWithNewOperands(new_left, new_right); |
9175 BranchInstr* new_branch = new BranchInstr(new_comparison); | 9313 BranchInstr* new_branch = new(isolate) BranchInstr(new_comparison); |
9176 new_branch->set_is_checked(branch->is_checked()); | 9314 new_branch->set_is_checked(branch->is_checked()); |
9177 return new_branch; | 9315 return new_branch; |
9178 } | 9316 } |
9179 | 9317 |
9180 | 9318 |
9181 void BranchSimplifier::Simplify(FlowGraph* flow_graph) { | 9319 void BranchSimplifier::Simplify(FlowGraph* flow_graph) { |
9182 // Optimize some branches that test the value of a phi. When it is safe | 9320 // Optimize some branches that test the value of a phi. When it is safe |
9183 // to do so, push the branch to each of the predecessor blocks. This is | 9321 // to do so, push the branch to each of the predecessor blocks. This is |
9184 // an optimization when (a) it can avoid materializing a boolean object at | 9322 // an optimization when (a) it can avoid materializing a boolean object at |
9185 // the phi only to test its value, and (b) it can expose opportunities for | 9323 // the phi only to test its value, and (b) it can expose opportunities for |
9186 // constant propagation and unreachable code elimination. This | 9324 // constant propagation and unreachable code elimination. This |
9187 // optimization is intended to run after inlining which creates | 9325 // optimization is intended to run after inlining which creates |
9188 // opportunities for optimization (a) and before constant folding which | 9326 // opportunities for optimization (a) and before constant folding which |
9189 // can perform optimization (b). | 9327 // can perform optimization (b). |
9190 | 9328 |
9191 // Begin with a worklist of join blocks ending in branches. They are | 9329 // Begin with a worklist of join blocks ending in branches. They are |
9192 // candidates for the pattern below. | 9330 // candidates for the pattern below. |
| 9331 Isolate* isolate = flow_graph->isolate(); |
9193 const GrowableArray<BlockEntryInstr*>& postorder = flow_graph->postorder(); | 9332 const GrowableArray<BlockEntryInstr*>& postorder = flow_graph->postorder(); |
9194 GrowableArray<BlockEntryInstr*> worklist(postorder.length()); | 9333 GrowableArray<BlockEntryInstr*> worklist(postorder.length()); |
9195 for (BlockIterator it(postorder); !it.Done(); it.Advance()) { | 9334 for (BlockIterator it(postorder); !it.Done(); it.Advance()) { |
9196 BlockEntryInstr* block = it.Current(); | 9335 BlockEntryInstr* block = it.Current(); |
9197 if (block->IsJoinEntry() && block->last_instruction()->IsBranch()) { | 9336 if (block->IsJoinEntry() && block->last_instruction()->IsBranch()) { |
9198 worklist.Add(block); | 9337 worklist.Add(block); |
9199 } | 9338 } |
9200 } | 9339 } |
9201 | 9340 |
9202 // Rewrite until no more instance of the pattern exists. | 9341 // Rewrite until no more instance of the pattern exists. |
9203 bool changed = false; | 9342 bool changed = false; |
9204 while (!worklist.is_empty()) { | 9343 while (!worklist.is_empty()) { |
9205 // All blocks in the worklist are join blocks (ending with a branch). | 9344 // All blocks in the worklist are join blocks (ending with a branch). |
9206 JoinEntryInstr* block = worklist.RemoveLast()->AsJoinEntry(); | 9345 JoinEntryInstr* block = worklist.RemoveLast()->AsJoinEntry(); |
9207 ASSERT(block != NULL); | 9346 ASSERT(block != NULL); |
9208 | 9347 |
9209 if (Match(block)) { | 9348 if (Match(block)) { |
9210 changed = true; | 9349 changed = true; |
9211 | 9350 |
9212 // The branch will be copied and pushed to all the join's | 9351 // The branch will be copied and pushed to all the join's |
9213 // predecessors. Convert the true and false target blocks into join | 9352 // predecessors. Convert the true and false target blocks into join |
9214 // blocks to join the control flows from all of the true | 9353 // blocks to join the control flows from all of the true |
9215 // (respectively, false) targets of the copied branches. | 9354 // (respectively, false) targets of the copied branches. |
9216 // | 9355 // |
9217 // The converted join block will have no phis, so it cannot be another | 9356 // The converted join block will have no phis, so it cannot be another |
9218 // instance of the pattern. There is thus no need to add it to the | 9357 // instance of the pattern. There is thus no need to add it to the |
9219 // worklist. | 9358 // worklist. |
9220 BranchInstr* branch = block->last_instruction()->AsBranch(); | 9359 BranchInstr* branch = block->last_instruction()->AsBranch(); |
9221 ASSERT(branch != NULL); | 9360 ASSERT(branch != NULL); |
9222 JoinEntryInstr* join_true = ToJoinEntry(branch->true_successor()); | 9361 JoinEntryInstr* join_true = |
9223 JoinEntryInstr* join_false = ToJoinEntry(branch->false_successor()); | 9362 ToJoinEntry(isolate, branch->true_successor()); |
| 9363 JoinEntryInstr* join_false = |
| 9364 ToJoinEntry(isolate, branch->false_successor()); |
9224 | 9365 |
9225 ComparisonInstr* comparison = branch->comparison(); | 9366 ComparisonInstr* comparison = branch->comparison(); |
9226 PhiInstr* phi = comparison->left()->definition()->AsPhi(); | 9367 PhiInstr* phi = comparison->left()->definition()->AsPhi(); |
9227 ConstantInstr* constant = comparison->right()->definition()->AsConstant(); | 9368 ConstantInstr* constant = comparison->right()->definition()->AsConstant(); |
9228 ASSERT(constant != NULL); | 9369 ASSERT(constant != NULL); |
9229 // Copy the constant and branch and push it to all the predecessors. | 9370 // Copy the constant and branch and push it to all the predecessors. |
9230 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) { | 9371 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) { |
9231 GotoInstr* old_goto = | 9372 GotoInstr* old_goto = |
9232 block->PredecessorAt(i)->last_instruction()->AsGoto(); | 9373 block->PredecessorAt(i)->last_instruction()->AsGoto(); |
9233 ASSERT(old_goto != NULL); | 9374 ASSERT(old_goto != NULL); |
9234 | 9375 |
9235 // Replace the goto in each predecessor with a rewritten branch, | 9376 // Replace the goto in each predecessor with a rewritten branch, |
9236 // rewritten to use the corresponding phi input instead of the phi. | 9377 // rewritten to use the corresponding phi input instead of the phi. |
9237 Value* new_left = phi->InputAt(i)->Copy(); | 9378 Value* new_left = phi->InputAt(i)->Copy(isolate); |
9238 Value* new_right = new Value(constant); | 9379 Value* new_right = new(isolate) Value(constant); |
9239 BranchInstr* new_branch = CloneBranch(branch, new_left, new_right); | 9380 BranchInstr* new_branch = |
| 9381 CloneBranch(isolate, branch, new_left, new_right); |
9240 if (branch->env() == NULL) { | 9382 if (branch->env() == NULL) { |
9241 new_branch->InheritDeoptTarget(old_goto); | 9383 new_branch->InheritDeoptTarget(isolate, old_goto); |
9242 } else { | 9384 } else { |
9243 // Take the environment from the branch if it has one. | 9385 // Take the environment from the branch if it has one. |
9244 new_branch->InheritDeoptTarget(branch); | 9386 new_branch->InheritDeoptTarget(isolate, branch); |
9245 // InheritDeoptTarget gave the new branch's comparison the same | 9387 // InheritDeoptTarget gave the new branch's comparison the same |
9246 // deopt id that it gave the new branch. The id should be the | 9388 // deopt id that it gave the new branch. The id should be the |
9247 // deopt id of the original comparison. | 9389 // deopt id of the original comparison. |
9248 new_branch->comparison()->SetDeoptId(comparison->GetDeoptId()); | 9390 new_branch->comparison()->SetDeoptId(comparison->GetDeoptId()); |
9249 // The phi can be used in the branch's environment. Rename such | 9391 // The phi can be used in the branch's environment. Rename such |
9250 // uses. | 9392 // uses. |
9251 for (Environment::DeepIterator it(new_branch->env()); | 9393 for (Environment::DeepIterator it(new_branch->env()); |
9252 !it.Done(); | 9394 !it.Done(); |
9253 it.Advance()) { | 9395 it.Advance()) { |
9254 Value* use = it.CurrentValue(); | 9396 Value* use = it.CurrentValue(); |
(...skipping 12 matching lines...) Expand all Loading... |
9267 | 9409 |
9268 // Update the predecessor block. We may have created another | 9410 // Update the predecessor block. We may have created another |
9269 // instance of the pattern so add it to the worklist if necessary. | 9411 // instance of the pattern so add it to the worklist if necessary. |
9270 BlockEntryInstr* branch_block = new_branch->GetBlock(); | 9412 BlockEntryInstr* branch_block = new_branch->GetBlock(); |
9271 branch_block->set_last_instruction(new_branch); | 9413 branch_block->set_last_instruction(new_branch); |
9272 if (branch_block->IsJoinEntry()) worklist.Add(branch_block); | 9414 if (branch_block->IsJoinEntry()) worklist.Add(branch_block); |
9273 | 9415 |
9274 // Connect the branch to the true and false joins, via empty target | 9416 // Connect the branch to the true and false joins, via empty target |
9275 // blocks. | 9417 // blocks. |
9276 TargetEntryInstr* true_target = | 9418 TargetEntryInstr* true_target = |
9277 new TargetEntryInstr(flow_graph->max_block_id() + 1, | 9419 new(isolate) TargetEntryInstr(flow_graph->max_block_id() + 1, |
9278 block->try_index()); | 9420 block->try_index()); |
9279 true_target->InheritDeoptTarget(join_true); | 9421 true_target->InheritDeoptTarget(isolate, join_true); |
9280 TargetEntryInstr* false_target = | 9422 TargetEntryInstr* false_target = |
9281 new TargetEntryInstr(flow_graph->max_block_id() + 2, | 9423 new(isolate) TargetEntryInstr(flow_graph->max_block_id() + 2, |
9282 block->try_index()); | 9424 block->try_index()); |
9283 false_target->InheritDeoptTarget(join_false); | 9425 false_target->InheritDeoptTarget(isolate, join_false); |
9284 flow_graph->set_max_block_id(flow_graph->max_block_id() + 2); | 9426 flow_graph->set_max_block_id(flow_graph->max_block_id() + 2); |
9285 *new_branch->true_successor_address() = true_target; | 9427 *new_branch->true_successor_address() = true_target; |
9286 *new_branch->false_successor_address() = false_target; | 9428 *new_branch->false_successor_address() = false_target; |
9287 GotoInstr* goto_true = new GotoInstr(join_true); | 9429 GotoInstr* goto_true = new(isolate) GotoInstr(join_true); |
9288 goto_true->InheritDeoptTarget(join_true); | 9430 goto_true->InheritDeoptTarget(isolate, join_true); |
9289 true_target->LinkTo(goto_true); | 9431 true_target->LinkTo(goto_true); |
9290 true_target->set_last_instruction(goto_true); | 9432 true_target->set_last_instruction(goto_true); |
9291 GotoInstr* goto_false = new GotoInstr(join_false); | 9433 GotoInstr* goto_false = new(isolate) GotoInstr(join_false); |
9292 goto_false->InheritDeoptTarget(join_false); | 9434 goto_false->InheritDeoptTarget(isolate, join_false); |
9293 false_target->LinkTo(goto_false); | 9435 false_target->LinkTo(goto_false); |
9294 false_target->set_last_instruction(goto_false); | 9436 false_target->set_last_instruction(goto_false); |
9295 } | 9437 } |
9296 // When all predecessors have been rewritten, the original block is | 9438 // When all predecessors have been rewritten, the original block is |
9297 // unreachable from the graph. | 9439 // unreachable from the graph. |
9298 phi->UnuseAllInputs(); | 9440 phi->UnuseAllInputs(); |
9299 branch->UnuseAllInputs(); | 9441 branch->UnuseAllInputs(); |
9300 block->UnuseAllInputs(); | 9442 block->UnuseAllInputs(); |
9301 ASSERT(!phi->HasUses()); | 9443 ASSERT(!phi->HasUses()); |
9302 } | 9444 } |
(...skipping 23 matching lines...) Expand all Loading... |
9326 | 9468 |
9327 if ((block->next() == instr) && | 9469 if ((block->next() == instr) && |
9328 (instr->next() == block->last_instruction())) { | 9470 (instr->next() == block->last_instruction())) { |
9329 before->previous()->LinkTo(instr); | 9471 before->previous()->LinkTo(instr); |
9330 instr->LinkTo(before); | 9472 instr->LinkTo(before); |
9331 } | 9473 } |
9332 } | 9474 } |
9333 | 9475 |
9334 | 9476 |
9335 void IfConverter::Simplify(FlowGraph* flow_graph) { | 9477 void IfConverter::Simplify(FlowGraph* flow_graph) { |
| 9478 Isolate* isolate = flow_graph->isolate(); |
9336 bool changed = false; | 9479 bool changed = false; |
9337 | 9480 |
9338 const GrowableArray<BlockEntryInstr*>& postorder = flow_graph->postorder(); | 9481 const GrowableArray<BlockEntryInstr*>& postorder = flow_graph->postorder(); |
9339 for (BlockIterator it(postorder); !it.Done(); it.Advance()) { | 9482 for (BlockIterator it(postorder); !it.Done(); it.Advance()) { |
9340 BlockEntryInstr* block = it.Current(); | 9483 BlockEntryInstr* block = it.Current(); |
9341 JoinEntryInstr* join = block->AsJoinEntry(); | 9484 JoinEntryInstr* join = block->AsJoinEntry(); |
9342 | 9485 |
9343 // Detect diamond control flow pattern which materializes a value depending | 9486 // Detect diamond control flow pattern which materializes a value depending |
9344 // on the result of the comparison: | 9487 // on the result of the comparison: |
9345 // | 9488 // |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9379 ComparisonInstr* comparison = branch->comparison(); | 9522 ComparisonInstr* comparison = branch->comparison(); |
9380 | 9523 |
9381 // Check if the platform supports efficient branchless IfThenElseInstr | 9524 // Check if the platform supports efficient branchless IfThenElseInstr |
9382 // for the given combination of comparison and values flowing from | 9525 // for the given combination of comparison and values flowing from |
9383 // false and true paths. | 9526 // false and true paths. |
9384 if (IfThenElseInstr::Supports(comparison, v1, v2)) { | 9527 if (IfThenElseInstr::Supports(comparison, v1, v2)) { |
9385 Value* if_true = (pred1 == branch->true_successor()) ? v1 : v2; | 9528 Value* if_true = (pred1 == branch->true_successor()) ? v1 : v2; |
9386 Value* if_false = (pred2 == branch->true_successor()) ? v1 : v2; | 9529 Value* if_false = (pred2 == branch->true_successor()) ? v1 : v2; |
9387 | 9530 |
9388 ComparisonInstr* new_comparison = | 9531 ComparisonInstr* new_comparison = |
9389 comparison->CopyWithNewOperands(comparison->left()->Copy(), | 9532 comparison->CopyWithNewOperands( |
9390 comparison->right()->Copy()); | 9533 comparison->left()->Copy(isolate), |
9391 IfThenElseInstr* if_then_else = new IfThenElseInstr( | 9534 comparison->right()->Copy(isolate)); |
| 9535 IfThenElseInstr* if_then_else = new(isolate) IfThenElseInstr( |
9392 new_comparison, | 9536 new_comparison, |
9393 if_true->Copy(), | 9537 if_true->Copy(isolate), |
9394 if_false->Copy()); | 9538 if_false->Copy(isolate)); |
9395 flow_graph->InsertBefore(branch, | 9539 flow_graph->InsertBefore(branch, |
9396 if_then_else, | 9540 if_then_else, |
9397 NULL, | 9541 NULL, |
9398 FlowGraph::kValue); | 9542 FlowGraph::kValue); |
9399 | 9543 |
9400 phi->ReplaceUsesWith(if_then_else); | 9544 phi->ReplaceUsesWith(if_then_else); |
9401 | 9545 |
9402 // Connect IfThenElseInstr to the first instruction in the merge block | 9546 // Connect IfThenElseInstr to the first instruction in the merge block |
9403 // effectively eliminating diamond control flow. | 9547 // effectively eliminating diamond control flow. |
9404 // Current block as well as pred1 and pred2 blocks are no longer in | 9548 // Current block as well as pred1 and pred2 blocks are no longer in |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9619 | 9763 |
9620 | 9764 |
9621 // Insert MaterializeObject instruction for the given allocation before | 9765 // Insert MaterializeObject instruction for the given allocation before |
9622 // the given instruction that can deoptimize. | 9766 // the given instruction that can deoptimize. |
9623 void AllocationSinking::CreateMaterializationAt( | 9767 void AllocationSinking::CreateMaterializationAt( |
9624 Instruction* exit, | 9768 Instruction* exit, |
9625 AllocateObjectInstr* alloc, | 9769 AllocateObjectInstr* alloc, |
9626 const Class& cls, | 9770 const Class& cls, |
9627 const ZoneGrowableArray<const Object*>& slots) { | 9771 const ZoneGrowableArray<const Object*>& slots) { |
9628 ZoneGrowableArray<Value*>* values = | 9772 ZoneGrowableArray<Value*>* values = |
9629 new ZoneGrowableArray<Value*>(slots.length()); | 9773 new(isolate()) ZoneGrowableArray<Value*>(slots.length()); |
9630 | 9774 |
9631 // Insert load instruction for every field. | 9775 // Insert load instruction for every field. |
9632 for (intptr_t i = 0; i < slots.length(); i++) { | 9776 for (intptr_t i = 0; i < slots.length(); i++) { |
9633 LoadFieldInstr* load = slots[i]->IsField() | 9777 LoadFieldInstr* load = slots[i]->IsField() |
9634 ? new LoadFieldInstr(new Value(alloc), | 9778 ? new(isolate()) LoadFieldInstr( |
9635 &Field::Cast(*slots[i]), | 9779 new(isolate()) Value(alloc), |
9636 AbstractType::ZoneHandle(), | 9780 &Field::Cast(*slots[i]), |
9637 alloc->token_pos()) | 9781 AbstractType::ZoneHandle(isolate(), AbstractType::null()), |
9638 : new LoadFieldInstr(new Value(alloc), | 9782 alloc->token_pos()) |
9639 Smi::Cast(*slots[i]).Value(), | 9783 : new(isolate()) LoadFieldInstr( |
9640 AbstractType::ZoneHandle(), | 9784 new(isolate()) Value(alloc), |
9641 alloc->token_pos()); | 9785 Smi::Cast(*slots[i]).Value(), |
| 9786 AbstractType::ZoneHandle(isolate(), AbstractType::null()), |
| 9787 alloc->token_pos()); |
9642 flow_graph_->InsertBefore( | 9788 flow_graph_->InsertBefore( |
9643 exit, load, NULL, FlowGraph::kValue); | 9789 exit, load, NULL, FlowGraph::kValue); |
9644 values->Add(new Value(load)); | 9790 values->Add(new(isolate()) Value(load)); |
9645 } | 9791 } |
9646 | 9792 |
9647 MaterializeObjectInstr* mat = new MaterializeObjectInstr(cls, slots, values); | 9793 MaterializeObjectInstr* mat = |
| 9794 new(isolate()) MaterializeObjectInstr(cls, slots, values); |
9648 flow_graph_->InsertBefore(exit, mat, NULL, FlowGraph::kValue); | 9795 flow_graph_->InsertBefore(exit, mat, NULL, FlowGraph::kValue); |
9649 | 9796 |
9650 // Replace all mentions of this allocation with a newly inserted | 9797 // Replace all mentions of this allocation with a newly inserted |
9651 // MaterializeObject instruction. | 9798 // MaterializeObject instruction. |
9652 // We must preserve the identity: all mentions are replaced by the same | 9799 // We must preserve the identity: all mentions are replaced by the same |
9653 // materialization. | 9800 // materialization. |
9654 for (Environment::DeepIterator env_it(exit->env()); | 9801 for (Environment::DeepIterator env_it(exit->env()); |
9655 !env_it.Done(); | 9802 !env_it.Done(); |
9656 env_it.Advance()) { | 9803 env_it.Advance()) { |
9657 Value* use = env_it.CurrentValue(); | 9804 Value* use = env_it.CurrentValue(); |
9658 if (use->definition() == alloc) { | 9805 if (use->definition() == alloc) { |
9659 use->RemoveFromUseList(); | 9806 use->RemoveFromUseList(); |
9660 use->set_definition(mat); | 9807 use->set_definition(mat); |
9661 mat->AddEnvUse(use); | 9808 mat->AddEnvUse(use); |
9662 } | 9809 } |
9663 } | 9810 } |
9664 | 9811 |
9665 // Record inserted materialization. | 9812 // Record inserted materialization. |
9666 materializations_.Add(mat); | 9813 materializations_.Add(mat); |
9667 } | 9814 } |
9668 | 9815 |
9669 | 9816 |
9670 void AllocationSinking::InsertMaterializations(AllocateObjectInstr* alloc) { | 9817 void AllocationSinking::InsertMaterializations(AllocateObjectInstr* alloc) { |
9671 // Collect all fields that are written for this instance. | 9818 // Collect all fields that are written for this instance. |
9672 ZoneGrowableArray<const Object*>* slots = | 9819 ZoneGrowableArray<const Object*>* slots = |
9673 new ZoneGrowableArray<const Object*>(5); | 9820 new(isolate()) ZoneGrowableArray<const Object*>(5); |
9674 | 9821 |
9675 for (Value* use = alloc->input_use_list(); | 9822 for (Value* use = alloc->input_use_list(); |
9676 use != NULL; | 9823 use != NULL; |
9677 use = use->next_use()) { | 9824 use = use->next_use()) { |
9678 StoreInstanceFieldInstr* store = use->instruction()->AsStoreInstanceField(); | 9825 StoreInstanceFieldInstr* store = use->instruction()->AsStoreInstanceField(); |
9679 if (!store->field().IsNull()) { | 9826 if (!store->field().IsNull()) { |
9680 AddSlot(slots, store->field()); | 9827 AddSlot(slots, store->field()); |
9681 } else { | 9828 } else { |
9682 AddSlot(slots, Smi::ZoneHandle(Smi::New(store->offset_in_bytes()))); | 9829 AddSlot(slots, Smi::ZoneHandle(isolate(), |
| 9830 Smi::New(store->offset_in_bytes()))); |
9683 } | 9831 } |
9684 } | 9832 } |
9685 | 9833 |
9686 if (alloc->ArgumentCount() > 0) { | 9834 if (alloc->ArgumentCount() > 0) { |
9687 ASSERT(alloc->ArgumentCount() == 1); | 9835 ASSERT(alloc->ArgumentCount() == 1); |
9688 intptr_t type_args_offset = alloc->cls().type_arguments_field_offset(); | 9836 intptr_t type_args_offset = alloc->cls().type_arguments_field_offset(); |
9689 AddSlot(slots, Smi::ZoneHandle(Smi::New(type_args_offset))); | 9837 AddSlot(slots, Smi::ZoneHandle(isolate(), Smi::New(type_args_offset))); |
9690 } | 9838 } |
9691 | 9839 |
9692 // Collect all instructions that mention this object in the environment. | 9840 // Collect all instructions that mention this object in the environment. |
9693 GrowableArray<Instruction*> exits(10); | 9841 GrowableArray<Instruction*> exits(10); |
9694 for (Value* use = alloc->env_use_list(); | 9842 for (Value* use = alloc->env_use_list(); |
9695 use != NULL; | 9843 use != NULL; |
9696 use = use->next_use()) { | 9844 use = use->next_use()) { |
9697 AddInstruction(&exits, use->instruction()); | 9845 AddInstruction(&exits, use->instruction()); |
9698 } | 9846 } |
9699 | 9847 |
9700 // Insert materializations at environment uses. | 9848 // Insert materializations at environment uses. |
9701 for (intptr_t i = 0; i < exits.length(); i++) { | 9849 for (intptr_t i = 0; i < exits.length(); i++) { |
9702 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); | 9850 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); |
9703 } | 9851 } |
9704 } | 9852 } |
9705 | 9853 |
9706 | 9854 |
9707 } // namespace dart | 9855 } // namespace dart |
OLD | NEW |