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

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

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

Powered by Google App Engine
This is Rietveld 408576698