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

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

Issue 298913007: Use isolate when allocation Zone objects and handles: focus on FlowGraphOptimizer, next inliner. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698