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

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

Issue 868913002: Add Zone-based handle allocation interface and reduce use of Isolate-based interfaces. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 11 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
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 29 matching lines...) Expand all
40 "Optimize left shift to truncate if possible"); 40 "Optimize left shift to truncate if possible");
41 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); 41 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis.");
42 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32) 42 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32)
43 DEFINE_FLAG(bool, trace_smi_widening, false, "Trace Smi->Int32 widening pass."); 43 DEFINE_FLAG(bool, trace_smi_widening, false, "Trace Smi->Int32 widening pass.");
44 #endif 44 #endif
45 DECLARE_FLAG(bool, enable_type_checks); 45 DECLARE_FLAG(bool, enable_type_checks);
46 DECLARE_FLAG(bool, source_lines); 46 DECLARE_FLAG(bool, source_lines);
47 DECLARE_FLAG(bool, trace_type_check_elimination); 47 DECLARE_FLAG(bool, trace_type_check_elimination);
48 DECLARE_FLAG(bool, warn_on_javascript_compatibility); 48 DECLARE_FLAG(bool, warn_on_javascript_compatibility);
49 49
50 // Quick access to the locally defined isolate() method. 50 // Quick access to the current isolate and zone.
51 #define I (isolate()) 51 #define I (isolate())
52 #define Z (zone())
52 53
53 static bool ShouldInlineSimd() { 54 static bool ShouldInlineSimd() {
54 return FlowGraphCompiler::SupportsUnboxedSimd128(); 55 return FlowGraphCompiler::SupportsUnboxedSimd128();
55 } 56 }
56 57
57 58
58 static bool CanUnboxDouble() { 59 static bool CanUnboxDouble() {
59 return FlowGraphCompiler::SupportsUnboxedDoubles(); 60 return FlowGraphCompiler::SupportsUnboxedDoubles();
60 } 61 }
61 62
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 } 171 }
171 } 172 }
172 173
173 for (intptr_t i = 0; i < class_ids.length(); i++) { 174 for (intptr_t i = 0; i < class_ids.length(); i++) {
174 if (class_ids[i] == kDynamicCid) { 175 if (class_ids[i] == kDynamicCid) {
175 // Not all cid-s known. 176 // Not all cid-s known.
176 return false; 177 return false;
177 } 178 }
178 } 179 }
179 180
180 const Array& args_desc_array = Array::Handle(I, 181 const Array& args_desc_array = Array::Handle(Z,
181 ArgumentsDescriptor::New(call->ArgumentCount(), call->argument_names())); 182 ArgumentsDescriptor::New(call->ArgumentCount(), call->argument_names()));
182 ArgumentsDescriptor args_desc(args_desc_array); 183 ArgumentsDescriptor args_desc(args_desc_array);
183 const Class& receiver_class = Class::Handle(I, 184 const Class& receiver_class = Class::Handle(Z,
184 isolate()->class_table()->At(class_ids[0])); 185 isolate()->class_table()->At(class_ids[0]));
185 const Function& function = Function::Handle(I, 186 const Function& function = Function::Handle(Z,
186 Resolver::ResolveDynamicForReceiverClass( 187 Resolver::ResolveDynamicForReceiverClass(
187 receiver_class, 188 receiver_class,
188 call->function_name(), 189 call->function_name(),
189 args_desc)); 190 args_desc));
190 if (function.IsNull()) { 191 if (function.IsNull()) {
191 return false; 192 return false;
192 } 193 }
193 // Create new ICData, do not modify the one attached to the instruction 194 // Create new ICData, do not modify the one attached to the instruction
194 // since it is attached to the assembly instruction itself. 195 // since it is attached to the assembly instruction itself.
195 // TODO(srdjan): Prevent modification of ICData object that is 196 // TODO(srdjan): Prevent modification of ICData object that is
196 // referenced in assembly code. 197 // referenced in assembly code.
197 ICData& ic_data = ICData::ZoneHandle(I, ICData::New( 198 ICData& ic_data = ICData::ZoneHandle(Z, ICData::New(
198 flow_graph_->parsed_function()->function(), 199 flow_graph_->parsed_function()->function(),
199 call->function_name(), 200 call->function_name(),
200 args_desc_array, 201 args_desc_array,
201 call->deopt_id(), 202 call->deopt_id(),
202 class_ids.length())); 203 class_ids.length()));
203 if (class_ids.length() > 1) { 204 if (class_ids.length() > 1) {
204 ic_data.AddCheck(class_ids, function); 205 ic_data.AddCheck(class_ids, function);
205 } else { 206 } else {
206 ASSERT(class_ids.length() == 1); 207 ASSERT(class_ids.length() == 1);
207 ic_data.AddReceiverCheck(class_ids[0], function); 208 ic_data.AddReceiverCheck(class_ids[0], function);
208 } 209 }
209 call->set_ic_data(&ic_data); 210 call->set_ic_data(&ic_data);
210 return true; 211 return true;
211 } 212 }
212 213
213 214
214 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data, 215 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data,
215 intptr_t cid) { 216 intptr_t cid) {
216 ASSERT(ic_data.NumArgsTested() == 1); 217 ASSERT(ic_data.NumArgsTested() == 1);
217 218
218 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) { 219 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) {
219 return ic_data; // Nothing to do 220 return ic_data; // Nothing to do
220 } 221 }
221 222
222 const Function& function = 223 const Function& function =
223 Function::Handle(I, ic_data.GetTargetForReceiverClassId(cid)); 224 Function::Handle(Z, ic_data.GetTargetForReceiverClassId(cid));
224 // TODO(fschneider): Try looking up the function on the class if it is 225 // TODO(fschneider): Try looking up the function on the class if it is
225 // not found in the ICData. 226 // not found in the ICData.
226 if (!function.IsNull()) { 227 if (!function.IsNull()) {
227 const ICData& new_ic_data = ICData::ZoneHandle(I, ICData::New( 228 const ICData& new_ic_data = ICData::ZoneHandle(Z, ICData::New(
228 Function::Handle(I, ic_data.owner()), 229 Function::Handle(Z, ic_data.owner()),
229 String::Handle(I, ic_data.target_name()), 230 String::Handle(Z, ic_data.target_name()),
230 Object::empty_array(), // Dummy argument descriptor. 231 Object::empty_array(), // Dummy argument descriptor.
231 ic_data.deopt_id(), 232 ic_data.deopt_id(),
232 ic_data.NumArgsTested())); 233 ic_data.NumArgsTested()));
233 new_ic_data.SetDeoptReasons(ic_data.DeoptReasons()); 234 new_ic_data.SetDeoptReasons(ic_data.DeoptReasons());
234 new_ic_data.AddReceiverCheck(cid, function); 235 new_ic_data.AddReceiverCheck(cid, function);
235 return new_ic_data; 236 return new_ic_data;
236 } 237 }
237 238
238 return ic_data; 239 return ic_data;
239 } 240 }
(...skipping 12 matching lines...) Expand all
252 } 253 }
253 254
254 const ICData& ic_data = TrySpecializeICData(call->ic_data(), receiver_cid); 255 const ICData& ic_data = TrySpecializeICData(call->ic_data(), receiver_cid);
255 if (ic_data.raw() == call->ic_data().raw()) { 256 if (ic_data.raw() == call->ic_data().raw()) {
256 // No specialization. 257 // No specialization.
257 return; 258 return;
258 } 259 }
259 260
260 const bool with_checks = false; 261 const bool with_checks = false;
261 PolymorphicInstanceCallInstr* specialized = 262 PolymorphicInstanceCallInstr* specialized =
262 new(I) PolymorphicInstanceCallInstr(call->instance_call(), 263 new(Z) PolymorphicInstanceCallInstr(call->instance_call(),
263 ic_data, 264 ic_data,
264 with_checks); 265 with_checks);
265 call->ReplaceWith(specialized, current_iterator()); 266 call->ReplaceWith(specialized, current_iterator());
266 } 267 }
267 268
268 269
269 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) { 270 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) {
270 BinarySmiOpInstr* instr = d->AsBinarySmiOp(); 271 BinarySmiOpInstr* instr = d->AsBinarySmiOp();
271 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) { 272 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) {
272 return instr; 273 return instr;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) { 306 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) {
306 smi_shift_left = AsSmiShiftLeftInstruction(right_instr); 307 smi_shift_left = AsSmiShiftLeftInstruction(right_instr);
307 } 308 }
308 if (smi_shift_left == NULL) return; 309 if (smi_shift_left == NULL) return;
309 310
310 // Pattern recognized. 311 // Pattern recognized.
311 smi_shift_left->mark_truncating(); 312 smi_shift_left->mark_truncating();
312 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); 313 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp());
313 if (bit_and_instr->IsBinaryMintOp()) { 314 if (bit_and_instr->IsBinaryMintOp()) {
314 // Replace Mint op with Smi op. 315 // Replace Mint op with Smi op.
315 BinarySmiOpInstr* smi_op = new(I) BinarySmiOpInstr( 316 BinarySmiOpInstr* smi_op = new(Z) BinarySmiOpInstr(
316 Token::kBIT_AND, 317 Token::kBIT_AND,
317 new(I) Value(left_instr), 318 new(Z) Value(left_instr),
318 new(I) Value(right_instr), 319 new(Z) Value(right_instr),
319 Isolate::kNoDeoptId); // BIT_AND cannot deoptimize. 320 Isolate::kNoDeoptId); // BIT_AND cannot deoptimize.
320 bit_and_instr->ReplaceWith(smi_op, current_iterator()); 321 bit_and_instr->ReplaceWith(smi_op, current_iterator());
321 } 322 }
322 } 323 }
323 324
324 325
325 326
326 // Used by TryMergeDivMod. 327 // Used by TryMergeDivMod.
327 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction, 328 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction,
328 // and the using instruction. This is an intermediate step before merging. 329 // and the using instruction. This is an intermediate step before merging.
329 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr, 330 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr,
330 intptr_t ix, 331 intptr_t ix,
331 intptr_t cid) { 332 intptr_t cid) {
332 const intptr_t index_scale = Instance::ElementSizeFor(cid); 333 const intptr_t index_scale = Instance::ElementSizeFor(cid);
333 ConstantInstr* index_instr = 334 ConstantInstr* index_instr =
334 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(ix))); 335 flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(ix)));
335 LoadIndexedInstr* load = 336 LoadIndexedInstr* load =
336 new(I) LoadIndexedInstr(new(I) Value(instr), 337 new(Z) LoadIndexedInstr(new(Z) Value(instr),
337 new(I) Value(index_instr), 338 new(Z) Value(index_instr),
338 index_scale, 339 index_scale,
339 cid, 340 cid,
340 Isolate::kNoDeoptId, 341 Isolate::kNoDeoptId,
341 instr->token_pos()); 342 instr->token_pos());
342 instr->ReplaceUsesWith(load); 343 instr->ReplaceUsesWith(load);
343 flow_graph()->InsertAfter(instr, load, NULL, FlowGraph::kValue); 344 flow_graph()->InsertAfter(instr, load, NULL, FlowGraph::kValue);
344 } 345 }
345 346
346 347
347 void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr, 348 void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr,
348 intptr_t index, 349 intptr_t index,
349 Representation rep, 350 Representation rep,
350 intptr_t cid) { 351 intptr_t cid) {
351 ExtractNthOutputInstr* extract = 352 ExtractNthOutputInstr* extract =
352 new(I) ExtractNthOutputInstr(new(I) Value(instr), index, rep, cid); 353 new(Z) ExtractNthOutputInstr(new(Z) Value(instr), index, rep, cid);
353 instr->ReplaceUsesWith(extract); 354 instr->ReplaceUsesWith(extract);
354 flow_graph()->InsertAfter(instr, extract, NULL, FlowGraph::kValue); 355 flow_graph()->InsertAfter(instr, extract, NULL, FlowGraph::kValue);
355 } 356 }
356 357
357 358
358 // Dart: 359 // Dart:
359 // var x = d % 10; 360 // var x = d % 10;
360 // var y = d ~/ 10; 361 // var y = d ~/ 10;
361 // var z = x + y; 362 // var z = x + y;
362 // 363 //
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 AppendExtractNthOutputForMerged( 404 AppendExtractNthOutputForMerged(
404 curr_instr, 405 curr_instr,
405 MergedMathInstr::OutputIndexOf(curr_instr->op_kind()), 406 MergedMathInstr::OutputIndexOf(curr_instr->op_kind()),
406 kTagged, kSmiCid); 407 kTagged, kSmiCid);
407 ASSERT(other_binop->HasUses()); 408 ASSERT(other_binop->HasUses());
408 AppendExtractNthOutputForMerged( 409 AppendExtractNthOutputForMerged(
409 other_binop, 410 other_binop,
410 MergedMathInstr::OutputIndexOf(other_binop->op_kind()), 411 MergedMathInstr::OutputIndexOf(other_binop->op_kind()),
411 kTagged, kSmiCid); 412 kTagged, kSmiCid);
412 413
413 ZoneGrowableArray<Value*>* args = new(I) ZoneGrowableArray<Value*>(2); 414 ZoneGrowableArray<Value*>* args = new(Z) ZoneGrowableArray<Value*>(2);
414 args->Add(new(I) Value(curr_instr->left()->definition())); 415 args->Add(new(Z) Value(curr_instr->left()->definition()));
415 args->Add(new(I) Value(curr_instr->right()->definition())); 416 args->Add(new(Z) Value(curr_instr->right()->definition()));
416 417
417 // Replace with TruncDivMod. 418 // Replace with TruncDivMod.
418 MergedMathInstr* div_mod = new(I) MergedMathInstr( 419 MergedMathInstr* div_mod = new(Z) MergedMathInstr(
419 args, 420 args,
420 curr_instr->deopt_id(), 421 curr_instr->deopt_id(),
421 MergedMathInstr::kTruncDivMod); 422 MergedMathInstr::kTruncDivMod);
422 curr_instr->ReplaceWith(div_mod, current_iterator()); 423 curr_instr->ReplaceWith(div_mod, current_iterator());
423 other_binop->ReplaceUsesWith(div_mod); 424 other_binop->ReplaceUsesWith(div_mod);
424 other_binop->RemoveFromGraph(); 425 other_binop->RemoveFromGraph();
425 // Only one merge possible. Because canonicalization happens later, 426 // Only one merge possible. Because canonicalization happens later,
426 // more candidates are possible. 427 // more candidates are possible.
427 // TODO(srdjan): Allow merging of trunc-div/mod into truncDivMod. 428 // TODO(srdjan): Allow merging of trunc-div/mod into truncDivMod.
428 break; 429 break;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 (*merge_candidates)[k] = NULL; // Clear it. 464 (*merge_candidates)[k] = NULL; // Clear it.
464 ASSERT(curr_instr->HasUses()); 465 ASSERT(curr_instr->HasUses());
465 AppendExtractNthOutputForMerged(curr_instr, 466 AppendExtractNthOutputForMerged(curr_instr,
466 MergedMathInstr::OutputIndexOf(kind), 467 MergedMathInstr::OutputIndexOf(kind),
467 kUnboxedDouble, kDoubleCid); 468 kUnboxedDouble, kDoubleCid);
468 ASSERT(other_op->HasUses()); 469 ASSERT(other_op->HasUses());
469 AppendExtractNthOutputForMerged( 470 AppendExtractNthOutputForMerged(
470 other_op, 471 other_op,
471 MergedMathInstr::OutputIndexOf(other_kind), 472 MergedMathInstr::OutputIndexOf(other_kind),
472 kUnboxedDouble, kDoubleCid); 473 kUnboxedDouble, kDoubleCid);
473 ZoneGrowableArray<Value*>* args = new(I) ZoneGrowableArray<Value*>(1); 474 ZoneGrowableArray<Value*>* args = new(Z) ZoneGrowableArray<Value*>(1);
474 args->Add(new(I) Value(curr_instr->value()->definition())); 475 args->Add(new(Z) Value(curr_instr->value()->definition()));
475 // Replace with SinCos. 476 // Replace with SinCos.
476 MergedMathInstr* sin_cos = 477 MergedMathInstr* sin_cos =
477 new(I) MergedMathInstr(args, 478 new(Z) MergedMathInstr(args,
478 curr_instr->DeoptimizationTarget(), 479 curr_instr->DeoptimizationTarget(),
479 MergedMathInstr::kSinCos); 480 MergedMathInstr::kSinCos);
480 curr_instr->ReplaceWith(sin_cos, current_iterator()); 481 curr_instr->ReplaceWith(sin_cos, current_iterator());
481 other_op->ReplaceUsesWith(sin_cos); 482 other_op->ReplaceUsesWith(sin_cos);
482 other_op->RemoveFromGraph(); 483 other_op->RemoveFromGraph();
483 // Only one merge possible. Because canonicalization happens later, 484 // Only one merge possible. Because canonicalization happens later,
484 // more candidates are possible. 485 // more candidates are possible.
485 // TODO(srdjan): Allow merging of sin/cos into sincos. 486 // TODO(srdjan): Allow merging of sin/cos into sincos.
486 break; 487 break;
487 } 488 }
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 phi->block()->PredecessorAt(use->use_index())->last_instruction(); 629 phi->block()->PredecessorAt(use->use_index())->last_instruction();
629 deopt_target = NULL; 630 deopt_target = NULL;
630 } else { 631 } else {
631 deopt_target = insert_before = use->instruction(); 632 deopt_target = insert_before = use->instruction();
632 } 633 }
633 634
634 Definition* converted = NULL; 635 Definition* converted = NULL;
635 if (IsUnboxedInteger(from) && IsUnboxedInteger(to)) { 636 if (IsUnboxedInteger(from) && IsUnboxedInteger(to)) {
636 const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != NULL) ? 637 const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != NULL) ?
637 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; 638 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
638 converted = new(I) UnboxedIntConverterInstr(from, 639 converted = new(Z) UnboxedIntConverterInstr(from,
639 to, 640 to,
640 use->CopyWithType(), 641 use->CopyWithType(),
641 deopt_id); 642 deopt_id);
642 } else if ((from == kUnboxedInt32) && (to == kUnboxedDouble)) { 643 } else if ((from == kUnboxedInt32) && (to == kUnboxedDouble)) {
643 converted = new Int32ToDoubleInstr(use->CopyWithType()); 644 converted = new Int32ToDoubleInstr(use->CopyWithType());
644 } else if ((from == kUnboxedMint) && 645 } else if ((from == kUnboxedMint) &&
645 (to == kUnboxedDouble) && 646 (to == kUnboxedDouble) &&
646 CanConvertUnboxedMintToDouble()) { 647 CanConvertUnboxedMintToDouble()) {
647 const intptr_t deopt_id = (deopt_target != NULL) ? 648 const intptr_t deopt_id = (deopt_target != NULL) ?
648 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; 649 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
(...skipping 10 matching lines...) Expand all
659 // Insert two "dummy" conversion instructions with the correct 660 // Insert two "dummy" conversion instructions with the correct
660 // "from" and "to" representation. The inserted instructions will 661 // "from" and "to" representation. The inserted instructions will
661 // trigger a deoptimization if executed. See #12417 for a discussion. 662 // trigger a deoptimization if executed. See #12417 for a discussion.
662 const intptr_t deopt_id = (deopt_target != NULL) ? 663 const intptr_t deopt_id = (deopt_target != NULL) ?
663 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; 664 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
664 ASSERT(Boxing::Supports(from)); 665 ASSERT(Boxing::Supports(from));
665 ASSERT(Boxing::Supports(to)); 666 ASSERT(Boxing::Supports(to));
666 Definition* boxed = BoxInstr::Create(from, use->CopyWithType()); 667 Definition* boxed = BoxInstr::Create(from, use->CopyWithType());
667 use->BindTo(boxed); 668 use->BindTo(boxed);
668 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); 669 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue);
669 converted = UnboxInstr::Create(to, new(I) Value(boxed), deopt_id); 670 converted = UnboxInstr::Create(to, new(Z) Value(boxed), deopt_id);
670 } 671 }
671 ASSERT(converted != NULL); 672 ASSERT(converted != NULL);
672 InsertBefore(insert_before, converted, use->instruction()->env(), 673 InsertBefore(insert_before, converted, use->instruction()->env(),
673 FlowGraph::kValue); 674 FlowGraph::kValue);
674 if (is_environment_use) { 675 if (is_environment_use) {
675 use->BindToEnvironment(converted); 676 use->BindToEnvironment(converted);
676 } else { 677 } else {
677 use->BindTo(converted); 678 use->BindTo(converted);
678 } 679 }
679 680
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
1010 call->ReplaceWith(replacement, current_iterator()); 1011 call->ReplaceWith(replacement, current_iterator());
1011 } 1012 }
1012 1013
1013 1014
1014 void FlowGraphOptimizer::AddCheckSmi(Definition* to_check, 1015 void FlowGraphOptimizer::AddCheckSmi(Definition* to_check,
1015 intptr_t deopt_id, 1016 intptr_t deopt_id,
1016 Environment* deopt_environment, 1017 Environment* deopt_environment,
1017 Instruction* insert_before) { 1018 Instruction* insert_before) {
1018 if (to_check->Type()->ToCid() != kSmiCid) { 1019 if (to_check->Type()->ToCid() != kSmiCid) {
1019 InsertBefore(insert_before, 1020 InsertBefore(insert_before,
1020 new(I) CheckSmiInstr(new(I) Value(to_check), 1021 new(Z) CheckSmiInstr(new(Z) Value(to_check),
1021 deopt_id, 1022 deopt_id,
1022 insert_before->token_pos()), 1023 insert_before->token_pos()),
1023 deopt_environment, 1024 deopt_environment,
1024 FlowGraph::kEffect); 1025 FlowGraph::kEffect);
1025 } 1026 }
1026 } 1027 }
1027 1028
1028 1029
1029 Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check, 1030 Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check,
1030 const ICData& unary_checks, 1031 const ICData& unary_checks,
1031 intptr_t deopt_id, 1032 intptr_t deopt_id,
1032 intptr_t token_pos) { 1033 intptr_t token_pos) {
1033 if ((unary_checks.NumberOfUsedChecks() == 1) && 1034 if ((unary_checks.NumberOfUsedChecks() == 1) &&
1034 unary_checks.HasReceiverClassId(kSmiCid)) { 1035 unary_checks.HasReceiverClassId(kSmiCid)) {
1035 return new(I) CheckSmiInstr(new(I) Value(to_check), 1036 return new(Z) CheckSmiInstr(new(Z) Value(to_check),
1036 deopt_id, 1037 deopt_id,
1037 token_pos); 1038 token_pos);
1038 } 1039 }
1039 return new(I) CheckClassInstr( 1040 return new(Z) CheckClassInstr(
1040 new(I) Value(to_check), deopt_id, unary_checks, token_pos); 1041 new(Z) Value(to_check), deopt_id, unary_checks, token_pos);
1041 } 1042 }
1042 1043
1043 1044
1044 void FlowGraphOptimizer::AddCheckClass(Definition* to_check, 1045 void FlowGraphOptimizer::AddCheckClass(Definition* to_check,
1045 const ICData& unary_checks, 1046 const ICData& unary_checks,
1046 intptr_t deopt_id, 1047 intptr_t deopt_id,
1047 Environment* deopt_environment, 1048 Environment* deopt_environment,
1048 Instruction* insert_before) { 1049 Instruction* insert_before) {
1049 // Type propagation has not run yet, we cannot eliminate the check. 1050 // Type propagation has not run yet, we cannot eliminate the check.
1050 Instruction* check = GetCheckClass( 1051 Instruction* check = GetCheckClass(
1051 to_check, unary_checks, deopt_id, insert_before->token_pos()); 1052 to_check, unary_checks, deopt_id, insert_before->token_pos());
1052 InsertBefore(insert_before, check, deopt_environment, FlowGraph::kEffect); 1053 InsertBefore(insert_before, check, deopt_environment, FlowGraph::kEffect);
1053 } 1054 }
1054 1055
1055 1056
1056 void FlowGraphOptimizer::AddReceiverCheck(InstanceCallInstr* call) { 1057 void FlowGraphOptimizer::AddReceiverCheck(InstanceCallInstr* call) {
1057 AddCheckClass(call->ArgumentAt(0), 1058 AddCheckClass(call->ArgumentAt(0),
1058 ICData::ZoneHandle(I, call->ic_data()->AsUnaryClassChecks()), 1059 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()),
1059 call->deopt_id(), 1060 call->deopt_id(),
1060 call->env(), 1061 call->env(),
1061 call); 1062 call);
1062 } 1063 }
1063 1064
1064 1065
1065 static bool ArgIsAlways(intptr_t cid, 1066 static bool ArgIsAlways(intptr_t cid,
1066 const ICData& ic_data, 1067 const ICData& ic_data,
1067 intptr_t arg_number) { 1068 intptr_t arg_number) {
1068 ASSERT(ic_data.NumArgsTested() > arg_number); 1069 ASSERT(ic_data.NumArgsTested() > arg_number);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1163 break; 1164 break;
1164 } 1165 }
1165 return kIllegalCid; 1166 return kIllegalCid;
1166 } 1167 }
1167 1168
1168 1169
1169 bool FlowGraphOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) { 1170 bool FlowGraphOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) {
1170 // Check for monomorphic IC data. 1171 // Check for monomorphic IC data.
1171 if (!call->HasICData()) return false; 1172 if (!call->HasICData()) return false;
1172 const ICData& ic_data = 1173 const ICData& ic_data =
1173 ICData::Handle(I, call->ic_data()->AsUnaryClassChecks()); 1174 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks());
1174 if (ic_data.NumberOfChecks() != 1) { 1175 if (ic_data.NumberOfChecks() != 1) {
1175 return false; 1176 return false;
1176 } 1177 }
1177 return TryReplaceInstanceCallWithInline(call); 1178 return TryReplaceInstanceCallWithInline(call);
1178 } 1179 }
1179 1180
1180 1181
1181 bool FlowGraphOptimizer::InlineSetIndexed( 1182 bool FlowGraphOptimizer::InlineSetIndexed(
1182 MethodRecognizer::Kind kind, 1183 MethodRecognizer::Kind kind,
1183 const Function& target, 1184 const Function& target,
1184 Instruction* call, 1185 Instruction* call,
1185 Definition* receiver, 1186 Definition* receiver,
1186 intptr_t token_pos, 1187 intptr_t token_pos,
1187 const ICData& value_check, 1188 const ICData& value_check,
1188 TargetEntryInstr** entry, 1189 TargetEntryInstr** entry,
1189 Definition** last) { 1190 Definition** last) {
1190 intptr_t array_cid = MethodKindToCid(kind); 1191 intptr_t array_cid = MethodKindToCid(kind);
1191 ASSERT(array_cid != kIllegalCid); 1192 ASSERT(array_cid != kIllegalCid);
1192 1193
1193 Definition* array = receiver; 1194 Definition* array = receiver;
1194 Definition* index = call->ArgumentAt(1); 1195 Definition* index = call->ArgumentAt(1);
1195 Definition* stored_value = call->ArgumentAt(2); 1196 Definition* stored_value = call->ArgumentAt(2);
1196 1197
1197 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), 1198 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
1198 call->GetBlock()->try_index()); 1199 call->GetBlock()->try_index());
1199 (*entry)->InheritDeoptTarget(I, call); 1200 (*entry)->InheritDeoptTarget(I, call);
1200 Instruction* cursor = *entry; 1201 Instruction* cursor = *entry;
1201 if (FLAG_enable_type_checks) { 1202 if (FLAG_enable_type_checks) {
1202 // Only type check for the value. A type check for the index is not 1203 // Only type check for the value. A type check for the index is not
1203 // needed here because we insert a deoptimizing smi-check for the case 1204 // needed here because we insert a deoptimizing smi-check for the case
1204 // the index is not a smi. 1205 // the index is not a smi.
1205 const AbstractType& value_type = 1206 const AbstractType& value_type =
1206 AbstractType::ZoneHandle(I, target.ParameterTypeAt(2)); 1207 AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2));
1207 Definition* instantiator = NULL; 1208 Definition* instantiator = NULL;
1208 Definition* type_args = NULL; 1209 Definition* type_args = NULL;
1209 switch (array_cid) { 1210 switch (array_cid) {
1210 case kArrayCid: 1211 case kArrayCid:
1211 case kGrowableObjectArrayCid: { 1212 case kGrowableObjectArrayCid: {
1212 const Class& instantiator_class = Class::Handle(I, target.Owner()); 1213 const Class& instantiator_class = Class::Handle(Z, target.Owner());
1213 intptr_t type_arguments_field_offset = 1214 intptr_t type_arguments_field_offset =
1214 instantiator_class.type_arguments_field_offset(); 1215 instantiator_class.type_arguments_field_offset();
1215 LoadFieldInstr* load_type_args = 1216 LoadFieldInstr* load_type_args =
1216 new(I) LoadFieldInstr(new(I) Value(array), 1217 new(Z) LoadFieldInstr(new(Z) Value(array),
1217 type_arguments_field_offset, 1218 type_arguments_field_offset,
1218 Type::ZoneHandle(I), // No type. 1219 Type::ZoneHandle(Z), // No type.
1219 call->token_pos()); 1220 call->token_pos());
1220 cursor = flow_graph()->AppendTo(cursor, 1221 cursor = flow_graph()->AppendTo(cursor,
1221 load_type_args, 1222 load_type_args,
1222 NULL, 1223 NULL,
1223 FlowGraph::kValue); 1224 FlowGraph::kValue);
1224 1225
1225 instantiator = array; 1226 instantiator = array;
1226 type_args = load_type_args; 1227 type_args = load_type_args;
1227 break; 1228 break;
1228 } 1229 }
(...skipping 30 matching lines...) Expand all
1259 ASSERT((array_cid != kTypedDataFloat64x2ArrayCid) || 1260 ASSERT((array_cid != kTypedDataFloat64x2ArrayCid) ||
1260 value_type.IsFloat64x2Type()); 1261 value_type.IsFloat64x2Type());
1261 ASSERT(value_type.IsInstantiated()); 1262 ASSERT(value_type.IsInstantiated());
1262 break; 1263 break;
1263 } 1264 }
1264 default: 1265 default:
1265 // TODO(fschneider): Add support for other array types. 1266 // TODO(fschneider): Add support for other array types.
1266 UNREACHABLE(); 1267 UNREACHABLE();
1267 } 1268 }
1268 AssertAssignableInstr* assert_value = 1269 AssertAssignableInstr* assert_value =
1269 new(I) AssertAssignableInstr(token_pos, 1270 new(Z) AssertAssignableInstr(token_pos,
1270 new(I) Value(stored_value), 1271 new(Z) Value(stored_value),
1271 new(I) Value(instantiator), 1272 new(Z) Value(instantiator),
1272 new(I) Value(type_args), 1273 new(Z) Value(type_args),
1273 value_type, 1274 value_type,
1274 Symbols::Value(), 1275 Symbols::Value(),
1275 call->deopt_id()); 1276 call->deopt_id());
1276 cursor = flow_graph()->AppendTo(cursor, 1277 cursor = flow_graph()->AppendTo(cursor,
1277 assert_value, 1278 assert_value,
1278 call->env(), 1279 call->env(),
1279 FlowGraph::kValue); 1280 FlowGraph::kValue);
1280 } 1281 }
1281 1282
1282 array_cid = PrepareInlineIndexedOp(call, 1283 array_cid = PrepareInlineIndexedOp(call,
(...skipping 20 matching lines...) Expand all
1303 Instruction* check = GetCheckClass( 1304 Instruction* check = GetCheckClass(
1304 stored_value, value_check, call->deopt_id(), call->token_pos()); 1305 stored_value, value_check, call->deopt_id(), call->token_pos());
1305 cursor = flow_graph()->AppendTo(cursor, 1306 cursor = flow_graph()->AppendTo(cursor,
1306 check, 1307 check,
1307 call->env(), 1308 call->env(),
1308 FlowGraph::kEffect); 1309 FlowGraph::kEffect);
1309 } 1310 }
1310 1311
1311 if (array_cid == kTypedDataFloat32ArrayCid) { 1312 if (array_cid == kTypedDataFloat32ArrayCid) {
1312 stored_value = 1313 stored_value =
1313 new(I) DoubleToFloatInstr( 1314 new(Z) DoubleToFloatInstr(
1314 new(I) Value(stored_value), call->deopt_id()); 1315 new(Z) Value(stored_value), call->deopt_id());
1315 cursor = flow_graph()->AppendTo(cursor, 1316 cursor = flow_graph()->AppendTo(cursor,
1316 stored_value, 1317 stored_value,
1317 NULL, 1318 NULL,
1318 FlowGraph::kValue); 1319 FlowGraph::kValue);
1319 } else if (array_cid == kTypedDataInt32ArrayCid) { 1320 } else if (array_cid == kTypedDataInt32ArrayCid) {
1320 stored_value = new(I) UnboxInt32Instr( 1321 stored_value = new(Z) UnboxInt32Instr(
1321 UnboxInt32Instr::kTruncate, 1322 UnboxInt32Instr::kTruncate,
1322 new(I) Value(stored_value), 1323 new(Z) Value(stored_value),
1323 call->deopt_id()); 1324 call->deopt_id());
1324 cursor = flow_graph()->AppendTo(cursor, 1325 cursor = flow_graph()->AppendTo(cursor,
1325 stored_value, 1326 stored_value,
1326 call->env(), 1327 call->env(),
1327 FlowGraph::kValue); 1328 FlowGraph::kValue);
1328 } else if (array_cid == kTypedDataUint32ArrayCid) { 1329 } else if (array_cid == kTypedDataUint32ArrayCid) {
1329 stored_value = new(I) UnboxUint32Instr( 1330 stored_value = new(Z) UnboxUint32Instr(
1330 new(I) Value(stored_value), 1331 new(Z) Value(stored_value),
1331 call->deopt_id()); 1332 call->deopt_id());
1332 ASSERT(stored_value->AsUnboxInteger()->is_truncating()); 1333 ASSERT(stored_value->AsUnboxInteger()->is_truncating());
1333 cursor = flow_graph()->AppendTo(cursor, 1334 cursor = flow_graph()->AppendTo(cursor,
1334 stored_value, 1335 stored_value,
1335 call->env(), 1336 call->env(),
1336 FlowGraph::kValue); 1337 FlowGraph::kValue);
1337 } 1338 }
1338 1339
1339 const intptr_t index_scale = Instance::ElementSizeFor(array_cid); 1340 const intptr_t index_scale = Instance::ElementSizeFor(array_cid);
1340 *last = new(I) StoreIndexedInstr(new(I) Value(array), 1341 *last = new(Z) StoreIndexedInstr(new(Z) Value(array),
1341 new(I) Value(index), 1342 new(Z) Value(index),
1342 new(I) Value(stored_value), 1343 new(Z) Value(stored_value),
1343 needs_store_barrier, 1344 needs_store_barrier,
1344 index_scale, 1345 index_scale,
1345 array_cid, 1346 array_cid,
1346 call->deopt_id(), 1347 call->deopt_id(),
1347 call->token_pos()); 1348 call->token_pos());
1348 flow_graph()->AppendTo(cursor, 1349 flow_graph()->AppendTo(cursor,
1349 *last, 1350 *last,
1350 call->env(), 1351 call->env(),
1351 FlowGraph::kEffect); 1352 FlowGraph::kEffect);
1352 return true; 1353 return true;
1353 } 1354 }
1354 1355
1355 1356
1356 bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid, 1357 bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid,
1357 const Function& target, 1358 const Function& target,
1358 Instruction* call, 1359 Instruction* call,
1359 Definition* receiver, 1360 Definition* receiver,
1360 intptr_t token_pos, 1361 intptr_t token_pos,
1361 const ICData& ic_data, 1362 const ICData& ic_data,
1362 TargetEntryInstr** entry, 1363 TargetEntryInstr** entry,
1363 Definition** last) { 1364 Definition** last) {
1364 ICData& value_check = ICData::ZoneHandle(I); 1365 ICData& value_check = ICData::ZoneHandle(Z);
1365 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target); 1366 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target);
1366 switch (kind) { 1367 switch (kind) {
1367 // Recognized [] operators. 1368 // Recognized [] operators.
1368 case MethodRecognizer::kImmutableArrayGetIndexed: 1369 case MethodRecognizer::kImmutableArrayGetIndexed:
1369 case MethodRecognizer::kObjectArrayGetIndexed: 1370 case MethodRecognizer::kObjectArrayGetIndexed:
1370 case MethodRecognizer::kGrowableArrayGetIndexed: 1371 case MethodRecognizer::kGrowableArrayGetIndexed:
1371 case MethodRecognizer::kInt8ArrayGetIndexed: 1372 case MethodRecognizer::kInt8ArrayGetIndexed:
1372 case MethodRecognizer::kUint8ArrayGetIndexed: 1373 case MethodRecognizer::kUint8ArrayGetIndexed:
1373 case MethodRecognizer::kUint8ClampedArrayGetIndexed: 1374 case MethodRecognizer::kUint8ClampedArrayGetIndexed:
1374 case MethodRecognizer::kExternalUint8ArrayGetIndexed: 1375 case MethodRecognizer::kExternalUint8ArrayGetIndexed:
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
1598 1599
1599 1600
1600 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, 1601 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call,
1601 intptr_t array_cid, 1602 intptr_t array_cid,
1602 Definition** array, 1603 Definition** array,
1603 Definition* index, 1604 Definition* index,
1604 Instruction** cursor) { 1605 Instruction** cursor) {
1605 // Insert index smi check. 1606 // Insert index smi check.
1606 *cursor = flow_graph()->AppendTo( 1607 *cursor = flow_graph()->AppendTo(
1607 *cursor, 1608 *cursor,
1608 new(I) CheckSmiInstr(new(I) Value(index), 1609 new(Z) CheckSmiInstr(new(Z) Value(index),
1609 call->deopt_id(), 1610 call->deopt_id(),
1610 call->token_pos()), 1611 call->token_pos()),
1611 call->env(), 1612 call->env(),
1612 FlowGraph::kEffect); 1613 FlowGraph::kEffect);
1613 1614
1614 // Insert array length load and bounds check. 1615 // Insert array length load and bounds check.
1615 LoadFieldInstr* length = 1616 LoadFieldInstr* length =
1616 new(I) LoadFieldInstr( 1617 new(Z) LoadFieldInstr(
1617 new(I) Value(*array), 1618 new(Z) Value(*array),
1618 CheckArrayBoundInstr::LengthOffsetFor(array_cid), 1619 CheckArrayBoundInstr::LengthOffsetFor(array_cid),
1619 Type::ZoneHandle(I, Type::SmiType()), 1620 Type::ZoneHandle(Z, Type::SmiType()),
1620 call->token_pos()); 1621 call->token_pos());
1621 length->set_is_immutable( 1622 length->set_is_immutable(
1622 CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid)); 1623 CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid));
1623 length->set_result_cid(kSmiCid); 1624 length->set_result_cid(kSmiCid);
1624 length->set_recognized_kind( 1625 length->set_recognized_kind(
1625 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); 1626 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
1626 *cursor = flow_graph()->AppendTo(*cursor, 1627 *cursor = flow_graph()->AppendTo(*cursor,
1627 length, 1628 length,
1628 NULL, 1629 NULL,
1629 FlowGraph::kValue); 1630 FlowGraph::kValue);
1630 1631
1631 *cursor = flow_graph()->AppendTo(*cursor, 1632 *cursor = flow_graph()->AppendTo(*cursor,
1632 new(I) CheckArrayBoundInstr( 1633 new(Z) CheckArrayBoundInstr(
1633 new(I) Value(length), 1634 new(Z) Value(length),
1634 new(I) Value(index), 1635 new(Z) Value(index),
1635 call->deopt_id()), 1636 call->deopt_id()),
1636 call->env(), 1637 call->env(),
1637 FlowGraph::kEffect); 1638 FlowGraph::kEffect);
1638 1639
1639 if (array_cid == kGrowableObjectArrayCid) { 1640 if (array_cid == kGrowableObjectArrayCid) {
1640 // Insert data elements load. 1641 // Insert data elements load.
1641 LoadFieldInstr* elements = 1642 LoadFieldInstr* elements =
1642 new(I) LoadFieldInstr( 1643 new(Z) LoadFieldInstr(
1643 new(I) Value(*array), 1644 new(Z) Value(*array),
1644 GrowableObjectArray::data_offset(), 1645 GrowableObjectArray::data_offset(),
1645 Type::ZoneHandle(I, Type::DynamicType()), 1646 Type::ZoneHandle(Z, Type::DynamicType()),
1646 call->token_pos()); 1647 call->token_pos());
1647 elements->set_result_cid(kArrayCid); 1648 elements->set_result_cid(kArrayCid);
1648 *cursor = flow_graph()->AppendTo(*cursor, 1649 *cursor = flow_graph()->AppendTo(*cursor,
1649 elements, 1650 elements,
1650 NULL, 1651 NULL,
1651 FlowGraph::kValue); 1652 FlowGraph::kValue);
1652 // Load from the data from backing store which is a fixed-length array. 1653 // Load from the data from backing store which is a fixed-length array.
1653 *array = elements; 1654 *array = elements;
1654 array_cid = kArrayCid; 1655 array_cid = kArrayCid;
1655 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { 1656 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
1656 LoadUntaggedInstr* elements = 1657 LoadUntaggedInstr* elements =
1657 new(I) LoadUntaggedInstr(new(I) Value(*array), 1658 new(Z) LoadUntaggedInstr(new(Z) Value(*array),
1658 ExternalTypedData::data_offset()); 1659 ExternalTypedData::data_offset());
1659 *cursor = flow_graph()->AppendTo(*cursor, 1660 *cursor = flow_graph()->AppendTo(*cursor,
1660 elements, 1661 elements,
1661 NULL, 1662 NULL,
1662 FlowGraph::kValue); 1663 FlowGraph::kValue);
1663 *array = elements; 1664 *array = elements;
1664 } 1665 }
1665 return array_cid; 1666 return array_cid;
1666 } 1667 }
1667 1668
1668 1669
1669 bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind, 1670 bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind,
1670 Instruction* call, 1671 Instruction* call,
1671 Definition* receiver, 1672 Definition* receiver,
1672 TargetEntryInstr** entry, 1673 TargetEntryInstr** entry,
1673 Definition** last) { 1674 Definition** last) {
1674 intptr_t array_cid = MethodKindToCid(kind); 1675 intptr_t array_cid = MethodKindToCid(kind);
1675 ASSERT(array_cid != kIllegalCid); 1676 ASSERT(array_cid != kIllegalCid);
1676 1677
1677 Definition* array = receiver; 1678 Definition* array = receiver;
1678 Definition* index = call->ArgumentAt(1); 1679 Definition* index = call->ArgumentAt(1);
1679 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), 1680 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
1680 call->GetBlock()->try_index()); 1681 call->GetBlock()->try_index());
1681 (*entry)->InheritDeoptTarget(I, call); 1682 (*entry)->InheritDeoptTarget(I, call);
1682 Instruction* cursor = *entry; 1683 Instruction* cursor = *entry;
1683 1684
1684 array_cid = PrepareInlineIndexedOp(call, 1685 array_cid = PrepareInlineIndexedOp(call,
1685 array_cid, 1686 array_cid,
1686 &array, 1687 &array,
1687 index, 1688 index,
1688 &cursor); 1689 &cursor);
1689 1690
1690 intptr_t deopt_id = Isolate::kNoDeoptId; 1691 intptr_t deopt_id = Isolate::kNoDeoptId;
1691 if ((array_cid == kTypedDataInt32ArrayCid) || 1692 if ((array_cid == kTypedDataInt32ArrayCid) ||
1692 (array_cid == kTypedDataUint32ArrayCid)) { 1693 (array_cid == kTypedDataUint32ArrayCid)) {
1693 // Deoptimization may be needed if result does not always fit in a Smi. 1694 // Deoptimization may be needed if result does not always fit in a Smi.
1694 deopt_id = (kSmiBits >= 32) ? Isolate::kNoDeoptId : call->deopt_id(); 1695 deopt_id = (kSmiBits >= 32) ? Isolate::kNoDeoptId : call->deopt_id();
1695 } 1696 }
1696 1697
1697 // Array load and return. 1698 // Array load and return.
1698 intptr_t index_scale = Instance::ElementSizeFor(array_cid); 1699 intptr_t index_scale = Instance::ElementSizeFor(array_cid);
1699 *last = new(I) LoadIndexedInstr(new(I) Value(array), 1700 *last = new(Z) LoadIndexedInstr(new(Z) Value(array),
1700 new(I) Value(index), 1701 new(Z) Value(index),
1701 index_scale, 1702 index_scale,
1702 array_cid, 1703 array_cid,
1703 deopt_id, 1704 deopt_id,
1704 call->token_pos()); 1705 call->token_pos());
1705 cursor = flow_graph()->AppendTo( 1706 cursor = flow_graph()->AppendTo(
1706 cursor, 1707 cursor,
1707 *last, 1708 *last,
1708 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, 1709 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL,
1709 FlowGraph::kValue); 1710 FlowGraph::kValue);
1710 1711
1711 if (array_cid == kTypedDataFloat32ArrayCid) { 1712 if (array_cid == kTypedDataFloat32ArrayCid) {
1712 *last = new(I) FloatToDoubleInstr(new(I) Value(*last), deopt_id); 1713 *last = new(Z) FloatToDoubleInstr(new(Z) Value(*last), deopt_id);
1713 flow_graph()->AppendTo(cursor, 1714 flow_graph()->AppendTo(cursor,
1714 *last, 1715 *last,
1715 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, 1716 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL,
1716 FlowGraph::kValue); 1717 FlowGraph::kValue);
1717 } 1718 }
1718 return true; 1719 return true;
1719 } 1720 }
1720 1721
1721 1722
1722 // Return true if d is a string of length one (a constant or result from 1723 // Return true if d is a string of length one (a constant or result from
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1755 right = temp; 1756 right = temp;
1756 } 1757 }
1757 if (IsLengthOneString(left)) { 1758 if (IsLengthOneString(left)) {
1758 // Optimize if left is a string with length one (either constant or 1759 // Optimize if left is a string with length one (either constant or
1759 // result of string-from-char-code. 1760 // result of string-from-char-code.
1760 if (left->IsConstant()) { 1761 if (left->IsConstant()) {
1761 ConstantInstr* left_const = left->AsConstant(); 1762 ConstantInstr* left_const = left->AsConstant();
1762 const String& str = String::Cast(left_const->value()); 1763 const String& str = String::Cast(left_const->value());
1763 ASSERT(str.Length() == 1); 1764 ASSERT(str.Length() == 1);
1764 ConstantInstr* char_code_left = flow_graph()->GetConstant( 1765 ConstantInstr* char_code_left = flow_graph()->GetConstant(
1765 Smi::ZoneHandle(I, Smi::New(static_cast<intptr_t>(str.CharAt(0))))); 1766 Smi::ZoneHandle(Z, Smi::New(static_cast<intptr_t>(str.CharAt(0)))));
1766 left_val = new(I) Value(char_code_left); 1767 left_val = new(Z) Value(char_code_left);
1767 } else if (left->IsStringFromCharCode()) { 1768 } else if (left->IsStringFromCharCode()) {
1768 // Use input of string-from-charcode as left value. 1769 // Use input of string-from-charcode as left value.
1769 StringFromCharCodeInstr* instr = left->AsStringFromCharCode(); 1770 StringFromCharCodeInstr* instr = left->AsStringFromCharCode();
1770 left_val = new(I) Value(instr->char_code()->definition()); 1771 left_val = new(Z) Value(instr->char_code()->definition());
1771 to_remove_left = instr; 1772 to_remove_left = instr;
1772 } else { 1773 } else {
1773 // IsLengthOneString(left) should have been false. 1774 // IsLengthOneString(left) should have been false.
1774 UNREACHABLE(); 1775 UNREACHABLE();
1775 } 1776 }
1776 1777
1777 Definition* to_remove_right = NULL; 1778 Definition* to_remove_right = NULL;
1778 Value* right_val = NULL; 1779 Value* right_val = NULL;
1779 if (right->IsStringFromCharCode()) { 1780 if (right->IsStringFromCharCode()) {
1780 // Skip string-from-char-code, and use its input as right value. 1781 // Skip string-from-char-code, and use its input as right value.
1781 StringFromCharCodeInstr* right_instr = right->AsStringFromCharCode(); 1782 StringFromCharCodeInstr* right_instr = right->AsStringFromCharCode();
1782 right_val = new(I) Value(right_instr->char_code()->definition()); 1783 right_val = new(Z) Value(right_instr->char_code()->definition());
1783 to_remove_right = right_instr; 1784 to_remove_right = right_instr;
1784 } else { 1785 } else {
1785 const ICData& unary_checks_1 = 1786 const ICData& unary_checks_1 =
1786 ICData::ZoneHandle(I, call->ic_data()->AsUnaryClassChecksForArgNr(1)); 1787 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecksForArgNr(1));
1787 AddCheckClass(right, 1788 AddCheckClass(right,
1788 unary_checks_1, 1789 unary_checks_1,
1789 call->deopt_id(), 1790 call->deopt_id(),
1790 call->env(), 1791 call->env(),
1791 call); 1792 call);
1792 // String-to-char-code instructions returns -1 (illegal charcode) if 1793 // String-to-char-code instructions returns -1 (illegal charcode) if
1793 // string is not of length one. 1794 // string is not of length one.
1794 StringToCharCodeInstr* char_code_right = 1795 StringToCharCodeInstr* char_code_right =
1795 new(I) StringToCharCodeInstr(new(I) Value(right), kOneByteStringCid); 1796 new(Z) StringToCharCodeInstr(new(Z) Value(right), kOneByteStringCid);
1796 InsertBefore(call, char_code_right, call->env(), FlowGraph::kValue); 1797 InsertBefore(call, char_code_right, call->env(), FlowGraph::kValue);
1797 right_val = new(I) Value(char_code_right); 1798 right_val = new(Z) Value(char_code_right);
1798 } 1799 }
1799 1800
1800 // Comparing char-codes instead of strings. 1801 // Comparing char-codes instead of strings.
1801 EqualityCompareInstr* comp = 1802 EqualityCompareInstr* comp =
1802 new(I) EqualityCompareInstr(call->token_pos(), 1803 new(Z) EqualityCompareInstr(call->token_pos(),
1803 op_kind, 1804 op_kind,
1804 left_val, 1805 left_val,
1805 right_val, 1806 right_val,
1806 kSmiCid, 1807 kSmiCid,
1807 call->deopt_id()); 1808 call->deopt_id());
1808 ReplaceCall(call, comp); 1809 ReplaceCall(call, comp);
1809 1810
1810 // Remove dead instructions. 1811 // Remove dead instructions.
1811 if ((to_remove_left != NULL) && 1812 if ((to_remove_left != NULL) &&
1812 (to_remove_left->input_use_list() == NULL)) { 1813 (to_remove_left->input_use_list() == NULL)) {
(...skipping 24 matching lines...) Expand all
1837 1838
1838 intptr_t cid = kIllegalCid; 1839 intptr_t cid = kIllegalCid;
1839 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { 1840 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) {
1840 if (TryStringLengthOneEquality(call, op_kind)) { 1841 if (TryStringLengthOneEquality(call, op_kind)) {
1841 return true; 1842 return true;
1842 } else { 1843 } else {
1843 return false; 1844 return false;
1844 } 1845 }
1845 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { 1846 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1846 InsertBefore(call, 1847 InsertBefore(call,
1847 new(I) CheckSmiInstr(new(I) Value(left), 1848 new(Z) CheckSmiInstr(new(Z) Value(left),
1848 call->deopt_id(), 1849 call->deopt_id(),
1849 call->token_pos()), 1850 call->token_pos()),
1850 call->env(), 1851 call->env(),
1851 FlowGraph::kEffect); 1852 FlowGraph::kEffect);
1852 InsertBefore(call, 1853 InsertBefore(call,
1853 new(I) CheckSmiInstr(new(I) Value(right), 1854 new(Z) CheckSmiInstr(new(Z) Value(right),
1854 call->deopt_id(), 1855 call->deopt_id(),
1855 call->token_pos()), 1856 call->token_pos()),
1856 call->env(), 1857 call->env(),
1857 FlowGraph::kEffect); 1858 FlowGraph::kEffect);
1858 cid = kSmiCid; 1859 cid = kSmiCid;
1859 } else if (HasTwoMintOrSmi(ic_data) && 1860 } else if (HasTwoMintOrSmi(ic_data) &&
1860 FlowGraphCompiler::SupportsUnboxedMints()) { 1861 FlowGraphCompiler::SupportsUnboxedMints()) {
1861 cid = kMintCid; 1862 cid = kMintCid;
1862 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) { 1863 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) {
1863 // Use double comparison. 1864 // Use double comparison.
1864 if (SmiFitsInDouble()) { 1865 if (SmiFitsInDouble()) {
1865 cid = kDoubleCid; 1866 cid = kDoubleCid;
1866 } else { 1867 } else {
1867 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { 1868 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) {
1868 // We cannot use double comparison on two smis. Need polymorphic 1869 // We cannot use double comparison on two smis. Need polymorphic
1869 // call. 1870 // call.
1870 return false; 1871 return false;
1871 } else { 1872 } else {
1872 InsertBefore(call, 1873 InsertBefore(call,
1873 new(I) CheckEitherNonSmiInstr( 1874 new(Z) CheckEitherNonSmiInstr(
1874 new(I) Value(left), 1875 new(Z) Value(left),
1875 new(I) Value(right), 1876 new(Z) Value(right),
1876 call->deopt_id()), 1877 call->deopt_id()),
1877 call->env(), 1878 call->env(),
1878 FlowGraph::kEffect); 1879 FlowGraph::kEffect);
1879 cid = kDoubleCid; 1880 cid = kDoubleCid;
1880 } 1881 }
1881 } 1882 }
1882 } else { 1883 } else {
1883 // Check if ICDData contains checks with Smi/Null combinations. In that case 1884 // Check if ICDData contains checks with Smi/Null combinations. In that case
1884 // we can still emit the optimized Smi equality operation but need to add 1885 // we can still emit the optimized Smi equality operation but need to add
1885 // checks for null or Smi. 1886 // checks for null or Smi.
1886 GrowableArray<intptr_t> smi_or_null(2); 1887 GrowableArray<intptr_t> smi_or_null(2);
1887 smi_or_null.Add(kSmiCid); 1888 smi_or_null.Add(kSmiCid);
1888 smi_or_null.Add(kNullCid); 1889 smi_or_null.Add(kNullCid);
1889 if (ICDataHasOnlyReceiverArgumentClassIds(ic_data, 1890 if (ICDataHasOnlyReceiverArgumentClassIds(ic_data,
1890 smi_or_null, 1891 smi_or_null,
1891 smi_or_null)) { 1892 smi_or_null)) {
1892 const ICData& unary_checks_0 = 1893 const ICData& unary_checks_0 =
1893 ICData::ZoneHandle(I, call->ic_data()->AsUnaryClassChecks()); 1894 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
1894 AddCheckClass(left, 1895 AddCheckClass(left,
1895 unary_checks_0, 1896 unary_checks_0,
1896 call->deopt_id(), 1897 call->deopt_id(),
1897 call->env(), 1898 call->env(),
1898 call); 1899 call);
1899 1900
1900 const ICData& unary_checks_1 = 1901 const ICData& unary_checks_1 =
1901 ICData::ZoneHandle(I, call->ic_data()->AsUnaryClassChecksForArgNr(1)); 1902 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecksForArgNr(1));
1902 AddCheckClass(right, 1903 AddCheckClass(right,
1903 unary_checks_1, 1904 unary_checks_1,
1904 call->deopt_id(), 1905 call->deopt_id(),
1905 call->env(), 1906 call->env(),
1906 call); 1907 call);
1907 cid = kSmiCid; 1908 cid = kSmiCid;
1908 } else { 1909 } else {
1909 // Shortcut for equality with null. 1910 // Shortcut for equality with null.
1910 ConstantInstr* right_const = right->AsConstant(); 1911 ConstantInstr* right_const = right->AsConstant();
1911 ConstantInstr* left_const = left->AsConstant(); 1912 ConstantInstr* left_const = left->AsConstant();
1912 if ((right_const != NULL && right_const->value().IsNull()) || 1913 if ((right_const != NULL && right_const->value().IsNull()) ||
1913 (left_const != NULL && left_const->value().IsNull())) { 1914 (left_const != NULL && left_const->value().IsNull())) {
1914 StrictCompareInstr* comp = 1915 StrictCompareInstr* comp =
1915 new(I) StrictCompareInstr(call->token_pos(), 1916 new(Z) StrictCompareInstr(call->token_pos(),
1916 Token::kEQ_STRICT, 1917 Token::kEQ_STRICT,
1917 new(I) Value(left), 1918 new(Z) Value(left),
1918 new(I) Value(right), 1919 new(Z) Value(right),
1919 false); // No number check. 1920 false); // No number check.
1920 ReplaceCall(call, comp); 1921 ReplaceCall(call, comp);
1921 return true; 1922 return true;
1922 } 1923 }
1923 return false; 1924 return false;
1924 } 1925 }
1925 } 1926 }
1926 ASSERT(cid != kIllegalCid); 1927 ASSERT(cid != kIllegalCid);
1927 EqualityCompareInstr* comp = new(I) EqualityCompareInstr(call->token_pos(), 1928 EqualityCompareInstr* comp = new(Z) EqualityCompareInstr(call->token_pos(),
1928 op_kind, 1929 op_kind,
1929 new(I) Value(left), 1930 new(Z) Value(left),
1930 new(I) Value(right), 1931 new(Z) Value(right),
1931 cid, 1932 cid,
1932 call->deopt_id()); 1933 call->deopt_id());
1933 ReplaceCall(call, comp); 1934 ReplaceCall(call, comp);
1934 return true; 1935 return true;
1935 } 1936 }
1936 1937
1937 1938
1938 bool FlowGraphOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call, 1939 bool FlowGraphOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call,
1939 Token::Kind op_kind) { 1940 Token::Kind op_kind) {
1940 const ICData& ic_data = *call->ic_data(); 1941 const ICData& ic_data = *call->ic_data();
1941 ASSERT(ic_data.NumArgsTested() == 2); 1942 ASSERT(ic_data.NumArgsTested() == 2);
1942 1943
1943 ASSERT(call->ArgumentCount() == 2); 1944 ASSERT(call->ArgumentCount() == 2);
1944 Definition* left = call->ArgumentAt(0); 1945 Definition* left = call->ArgumentAt(0);
1945 Definition* right = call->ArgumentAt(1); 1946 Definition* right = call->ArgumentAt(1);
1946 1947
1947 intptr_t cid = kIllegalCid; 1948 intptr_t cid = kIllegalCid;
1948 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 1949 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1949 InsertBefore(call, 1950 InsertBefore(call,
1950 new(I) CheckSmiInstr(new(I) Value(left), 1951 new(Z) CheckSmiInstr(new(Z) Value(left),
1951 call->deopt_id(), 1952 call->deopt_id(),
1952 call->token_pos()), 1953 call->token_pos()),
1953 call->env(), 1954 call->env(),
1954 FlowGraph::kEffect); 1955 FlowGraph::kEffect);
1955 InsertBefore(call, 1956 InsertBefore(call,
1956 new(I) CheckSmiInstr(new(I) Value(right), 1957 new(Z) CheckSmiInstr(new(Z) Value(right),
1957 call->deopt_id(), 1958 call->deopt_id(),
1958 call->token_pos()), 1959 call->token_pos()),
1959 call->env(), 1960 call->env(),
1960 FlowGraph::kEffect); 1961 FlowGraph::kEffect);
1961 cid = kSmiCid; 1962 cid = kSmiCid;
1962 } else if (HasTwoMintOrSmi(ic_data) && 1963 } else if (HasTwoMintOrSmi(ic_data) &&
1963 FlowGraphCompiler::SupportsUnboxedMints()) { 1964 FlowGraphCompiler::SupportsUnboxedMints()) {
1964 cid = kMintCid; 1965 cid = kMintCid;
1965 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) { 1966 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) {
1966 // Use double comparison. 1967 // Use double comparison.
1967 if (SmiFitsInDouble()) { 1968 if (SmiFitsInDouble()) {
1968 cid = kDoubleCid; 1969 cid = kDoubleCid;
1969 } else { 1970 } else {
1970 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { 1971 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) {
1971 // We cannot use double comparison on two smis. Need polymorphic 1972 // We cannot use double comparison on two smis. Need polymorphic
1972 // call. 1973 // call.
1973 return false; 1974 return false;
1974 } else { 1975 } else {
1975 InsertBefore(call, 1976 InsertBefore(call,
1976 new(I) CheckEitherNonSmiInstr( 1977 new(Z) CheckEitherNonSmiInstr(
1977 new(I) Value(left), 1978 new(Z) Value(left),
1978 new(I) Value(right), 1979 new(Z) Value(right),
1979 call->deopt_id()), 1980 call->deopt_id()),
1980 call->env(), 1981 call->env(),
1981 FlowGraph::kEffect); 1982 FlowGraph::kEffect);
1982 cid = kDoubleCid; 1983 cid = kDoubleCid;
1983 } 1984 }
1984 } 1985 }
1985 } else { 1986 } else {
1986 return false; 1987 return false;
1987 } 1988 }
1988 ASSERT(cid != kIllegalCid); 1989 ASSERT(cid != kIllegalCid);
1989 RelationalOpInstr* comp = new(I) RelationalOpInstr(call->token_pos(), 1990 RelationalOpInstr* comp = new(Z) RelationalOpInstr(call->token_pos(),
1990 op_kind, 1991 op_kind,
1991 new(I) Value(left), 1992 new(Z) Value(left),
1992 new(I) Value(right), 1993 new(Z) Value(right),
1993 cid, 1994 cid,
1994 call->deopt_id()); 1995 call->deopt_id());
1995 ReplaceCall(call, comp); 1996 ReplaceCall(call, comp);
1996 return true; 1997 return true;
1997 } 1998 }
1998 1999
1999 2000
2000 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, 2001 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
2001 Token::Kind op_kind) { 2002 Token::Kind op_kind) {
2002 intptr_t operands_type = kIllegalCid; 2003 intptr_t operands_type = kIllegalCid;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2062 // Left shift may overflow from smi into mint or big ints. 2063 // Left shift may overflow from smi into mint or big ints.
2063 // Don't generate smi code if the IC data is marked because 2064 // Don't generate smi code if the IC data is marked because
2064 // of an overflow. 2065 // of an overflow.
2065 if (ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) { 2066 if (ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) {
2066 return false; 2067 return false;
2067 } 2068 }
2068 operands_type = ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp) 2069 operands_type = ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp)
2069 ? kMintCid 2070 ? kMintCid
2070 : kSmiCid; 2071 : kSmiCid;
2071 } else if (HasTwoMintOrSmi(ic_data) && 2072 } else if (HasTwoMintOrSmi(ic_data) &&
2072 HasOnlyOneSmi(ICData::Handle(I, 2073 HasOnlyOneSmi(ICData::Handle(Z,
2073 ic_data.AsUnaryClassChecksForArgNr(1)))) { 2074 ic_data.AsUnaryClassChecksForArgNr(1)))) {
2074 // Don't generate mint code if the IC data is marked because of an 2075 // Don't generate mint code if the IC data is marked because of an
2075 // overflow. 2076 // overflow.
2076 if (ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) { 2077 if (ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) {
2077 return false; 2078 return false;
2078 } 2079 }
2079 // Check for smi/mint << smi or smi/mint >> smi. 2080 // Check for smi/mint << smi or smi/mint >> smi.
2080 operands_type = kMintCid; 2081 operands_type = kMintCid;
2081 } else { 2082 } else {
2082 return false; 2083 return false;
(...skipping 19 matching lines...) Expand all
2102 Definition* right = call->ArgumentAt(1); 2103 Definition* right = call->ArgumentAt(1);
2103 if (operands_type == kDoubleCid) { 2104 if (operands_type == kDoubleCid) {
2104 if (!CanUnboxDouble()) { 2105 if (!CanUnboxDouble()) {
2105 return false; 2106 return false;
2106 } 2107 }
2107 // Check that either left or right are not a smi. Result of a 2108 // Check that either left or right are not a smi. Result of a
2108 // binary operation with two smis is a smi not a double, except '/' which 2109 // binary operation with two smis is a smi not a double, except '/' which
2109 // returns a double for two smis. 2110 // returns a double for two smis.
2110 if (op_kind != Token::kDIV) { 2111 if (op_kind != Token::kDIV) {
2111 InsertBefore(call, 2112 InsertBefore(call,
2112 new(I) CheckEitherNonSmiInstr( 2113 new(Z) CheckEitherNonSmiInstr(
2113 new(I) Value(left), 2114 new(Z) Value(left),
2114 new(I) Value(right), 2115 new(Z) Value(right),
2115 call->deopt_id()), 2116 call->deopt_id()),
2116 call->env(), 2117 call->env(),
2117 FlowGraph::kEffect); 2118 FlowGraph::kEffect);
2118 } 2119 }
2119 2120
2120 BinaryDoubleOpInstr* double_bin_op = 2121 BinaryDoubleOpInstr* double_bin_op =
2121 new(I) BinaryDoubleOpInstr(op_kind, 2122 new(Z) BinaryDoubleOpInstr(op_kind,
2122 new(I) Value(left), 2123 new(Z) Value(left),
2123 new(I) Value(right), 2124 new(Z) Value(right),
2124 call->deopt_id(), call->token_pos()); 2125 call->deopt_id(), call->token_pos());
2125 ReplaceCall(call, double_bin_op); 2126 ReplaceCall(call, double_bin_op);
2126 } else if (operands_type == kMintCid) { 2127 } else if (operands_type == kMintCid) {
2127 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; 2128 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false;
2128 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { 2129 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) {
2129 ShiftMintOpInstr* shift_op = 2130 ShiftMintOpInstr* shift_op =
2130 new(I) ShiftMintOpInstr( 2131 new(Z) ShiftMintOpInstr(
2131 op_kind, new(I) Value(left), new(I) Value(right), 2132 op_kind, new(Z) Value(left), new(Z) Value(right),
2132 call->deopt_id()); 2133 call->deopt_id());
2133 ReplaceCall(call, shift_op); 2134 ReplaceCall(call, shift_op);
2134 } else { 2135 } else {
2135 BinaryMintOpInstr* bin_op = 2136 BinaryMintOpInstr* bin_op =
2136 new(I) BinaryMintOpInstr( 2137 new(Z) BinaryMintOpInstr(
2137 op_kind, new(I) Value(left), new(I) Value(right), 2138 op_kind, new(Z) Value(left), new(Z) Value(right),
2138 call->deopt_id()); 2139 call->deopt_id());
2139 ReplaceCall(call, bin_op); 2140 ReplaceCall(call, bin_op);
2140 } 2141 }
2141 } else if (operands_type == kFloat32x4Cid) { 2142 } else if (operands_type == kFloat32x4Cid) {
2142 return InlineFloat32x4BinaryOp(call, op_kind); 2143 return InlineFloat32x4BinaryOp(call, op_kind);
2143 } else if (operands_type == kInt32x4Cid) { 2144 } else if (operands_type == kInt32x4Cid) {
2144 return InlineInt32x4BinaryOp(call, op_kind); 2145 return InlineInt32x4BinaryOp(call, op_kind);
2145 } else if (operands_type == kFloat64x2Cid) { 2146 } else if (operands_type == kFloat64x2Cid) {
2146 return InlineFloat64x2BinaryOp(call, op_kind); 2147 return InlineFloat64x2BinaryOp(call, op_kind);
2147 } else if (op_kind == Token::kMOD) { 2148 } else if (op_kind == Token::kMOD) {
2148 ASSERT(operands_type == kSmiCid); 2149 ASSERT(operands_type == kSmiCid);
2149 if (right->IsConstant()) { 2150 if (right->IsConstant()) {
2150 const Object& obj = right->AsConstant()->value(); 2151 const Object& obj = right->AsConstant()->value();
2151 if (obj.IsSmi() && Utils::IsPowerOfTwo(Smi::Cast(obj).Value())) { 2152 if (obj.IsSmi() && Utils::IsPowerOfTwo(Smi::Cast(obj).Value())) {
2152 // Insert smi check and attach a copy of the original environment 2153 // Insert smi check and attach a copy of the original environment
2153 // because the smi operation can still deoptimize. 2154 // because the smi operation can still deoptimize.
2154 InsertBefore(call, 2155 InsertBefore(call,
2155 new(I) CheckSmiInstr(new(I) Value(left), 2156 new(Z) CheckSmiInstr(new(Z) Value(left),
2156 call->deopt_id(), 2157 call->deopt_id(),
2157 call->token_pos()), 2158 call->token_pos()),
2158 call->env(), 2159 call->env(),
2159 FlowGraph::kEffect); 2160 FlowGraph::kEffect);
2160 ConstantInstr* constant = 2161 ConstantInstr* constant =
2161 flow_graph()->GetConstant(Smi::Handle(I, 2162 flow_graph()->GetConstant(Smi::Handle(Z,
2162 Smi::New(Smi::Cast(obj).Value() - 1))); 2163 Smi::New(Smi::Cast(obj).Value() - 1)));
2163 BinarySmiOpInstr* bin_op = 2164 BinarySmiOpInstr* bin_op =
2164 new(I) BinarySmiOpInstr(Token::kBIT_AND, 2165 new(Z) BinarySmiOpInstr(Token::kBIT_AND,
2165 new(I) Value(left), 2166 new(Z) Value(left),
2166 new(I) Value(constant), 2167 new(Z) Value(constant),
2167 call->deopt_id()); 2168 call->deopt_id());
2168 ReplaceCall(call, bin_op); 2169 ReplaceCall(call, bin_op);
2169 return true; 2170 return true;
2170 } 2171 }
2171 } 2172 }
2172 // Insert two smi checks and attach a copy of the original 2173 // Insert two smi checks and attach a copy of the original
2173 // environment because the smi operation can still deoptimize. 2174 // environment because the smi operation can still deoptimize.
2174 AddCheckSmi(left, call->deopt_id(), call->env(), call); 2175 AddCheckSmi(left, call->deopt_id(), call->env(), call);
2175 AddCheckSmi(right, call->deopt_id(), call->env(), call); 2176 AddCheckSmi(right, call->deopt_id(), call->env(), call);
2176 BinarySmiOpInstr* bin_op = 2177 BinarySmiOpInstr* bin_op =
2177 new(I) BinarySmiOpInstr(op_kind, 2178 new(Z) BinarySmiOpInstr(op_kind,
2178 new(I) Value(left), 2179 new(Z) Value(left),
2179 new(I) Value(right), 2180 new(Z) Value(right),
2180 call->deopt_id()); 2181 call->deopt_id());
2181 ReplaceCall(call, bin_op); 2182 ReplaceCall(call, bin_op);
2182 } else { 2183 } else {
2183 ASSERT(operands_type == kSmiCid); 2184 ASSERT(operands_type == kSmiCid);
2184 // Insert two smi checks and attach a copy of the original 2185 // Insert two smi checks and attach a copy of the original
2185 // environment because the smi operation can still deoptimize. 2186 // environment because the smi operation can still deoptimize.
2186 AddCheckSmi(left, call->deopt_id(), call->env(), call); 2187 AddCheckSmi(left, call->deopt_id(), call->env(), call);
2187 AddCheckSmi(right, call->deopt_id(), call->env(), call); 2188 AddCheckSmi(right, call->deopt_id(), call->env(), call);
2188 if (left->IsConstant() && 2189 if (left->IsConstant() &&
2189 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { 2190 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) {
2190 // Constant should be on the right side. 2191 // Constant should be on the right side.
2191 Definition* temp = left; 2192 Definition* temp = left;
2192 left = right; 2193 left = right;
2193 right = temp; 2194 right = temp;
2194 } 2195 }
2195 BinarySmiOpInstr* bin_op = 2196 BinarySmiOpInstr* bin_op =
2196 new(I) BinarySmiOpInstr( 2197 new(Z) BinarySmiOpInstr(
2197 op_kind, 2198 op_kind,
2198 new(I) Value(left), 2199 new(Z) Value(left),
2199 new(I) Value(right), 2200 new(Z) Value(right),
2200 call->deopt_id()); 2201 call->deopt_id());
2201 ReplaceCall(call, bin_op); 2202 ReplaceCall(call, bin_op);
2202 } 2203 }
2203 return true; 2204 return true;
2204 } 2205 }
2205 2206
2206 2207
2207 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, 2208 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call,
2208 Token::Kind op_kind) { 2209 Token::Kind op_kind) {
2209 ASSERT(call->ArgumentCount() == 1); 2210 ASSERT(call->ArgumentCount() == 1);
2210 Definition* input = call->ArgumentAt(0); 2211 Definition* input = call->ArgumentAt(0);
2211 Definition* unary_op = NULL; 2212 Definition* unary_op = NULL;
2212 if (HasOnlyOneSmi(*call->ic_data())) { 2213 if (HasOnlyOneSmi(*call->ic_data())) {
2213 InsertBefore(call, 2214 InsertBefore(call,
2214 new(I) CheckSmiInstr(new(I) Value(input), 2215 new(Z) CheckSmiInstr(new(Z) Value(input),
2215 call->deopt_id(), 2216 call->deopt_id(),
2216 call->token_pos()), 2217 call->token_pos()),
2217 call->env(), 2218 call->env(),
2218 FlowGraph::kEffect); 2219 FlowGraph::kEffect);
2219 unary_op = new(I) UnarySmiOpInstr( 2220 unary_op = new(Z) UnarySmiOpInstr(
2220 op_kind, new(I) Value(input), call->deopt_id()); 2221 op_kind, new(Z) Value(input), call->deopt_id());
2221 } else if ((op_kind == Token::kBIT_NOT) && 2222 } else if ((op_kind == Token::kBIT_NOT) &&
2222 HasOnlySmiOrMint(*call->ic_data()) && 2223 HasOnlySmiOrMint(*call->ic_data()) &&
2223 FlowGraphCompiler::SupportsUnboxedMints()) { 2224 FlowGraphCompiler::SupportsUnboxedMints()) {
2224 unary_op = new(I) UnaryMintOpInstr( 2225 unary_op = new(Z) UnaryMintOpInstr(
2225 op_kind, new(I) Value(input), call->deopt_id()); 2226 op_kind, new(Z) Value(input), call->deopt_id());
2226 } else if (HasOnlyOneDouble(*call->ic_data()) && 2227 } else if (HasOnlyOneDouble(*call->ic_data()) &&
2227 (op_kind == Token::kNEGATE) && 2228 (op_kind == Token::kNEGATE) &&
2228 CanUnboxDouble()) { 2229 CanUnboxDouble()) {
2229 AddReceiverCheck(call); 2230 AddReceiverCheck(call);
2230 unary_op = new(I) UnaryDoubleOpInstr( 2231 unary_op = new(Z) UnaryDoubleOpInstr(
2231 Token::kNEGATE, new(I) Value(input), call->deopt_id()); 2232 Token::kNEGATE, new(Z) Value(input), call->deopt_id());
2232 } else { 2233 } else {
2233 return false; 2234 return false;
2234 } 2235 }
2235 ASSERT(unary_op != NULL); 2236 ASSERT(unary_op != NULL);
2236 ReplaceCall(call, unary_op); 2237 ReplaceCall(call, unary_op);
2237 return true; 2238 return true;
2238 } 2239 }
2239 2240
2240 2241
2241 // Using field class 2242 // Using field class
(...skipping 18 matching lines...) Expand all
2260 bool FlowGraphOptimizer::InstanceCallNeedsClassCheck( 2261 bool FlowGraphOptimizer::InstanceCallNeedsClassCheck(
2261 InstanceCallInstr* call, RawFunction::Kind kind) const { 2262 InstanceCallInstr* call, RawFunction::Kind kind) const {
2262 if (!FLAG_use_cha) return true; 2263 if (!FLAG_use_cha) return true;
2263 Definition* callee_receiver = call->ArgumentAt(0); 2264 Definition* callee_receiver = call->ArgumentAt(0);
2264 ASSERT(callee_receiver != NULL); 2265 ASSERT(callee_receiver != NULL);
2265 const Function& function = flow_graph_->parsed_function()->function(); 2266 const Function& function = flow_graph_->parsed_function()->function();
2266 if (function.IsDynamicFunction() && 2267 if (function.IsDynamicFunction() &&
2267 callee_receiver->IsParameter() && 2268 callee_receiver->IsParameter() &&
2268 (callee_receiver->AsParameter()->index() == 0)) { 2269 (callee_receiver->AsParameter()->index() == 0)) {
2269 const String& name = (kind == RawFunction::kMethodExtractor) 2270 const String& name = (kind == RawFunction::kMethodExtractor)
2270 ? String::Handle(I, Field::NameFromGetter(call->function_name())) 2271 ? String::Handle(Z, Field::NameFromGetter(call->function_name()))
2271 : call->function_name(); 2272 : call->function_name();
2272 return isolate()->cha()->HasOverride(Class::Handle(I, function.Owner()), 2273 return isolate()->cha()->HasOverride(Class::Handle(Z, function.Owner()),
2273 name); 2274 name);
2274 } 2275 }
2275 return true; 2276 return true;
2276 } 2277 }
2277 2278
2278 2279
2279 void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { 2280 void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) {
2280 ASSERT(call->HasICData()); 2281 ASSERT(call->HasICData());
2281 const ICData& ic_data = *call->ic_data(); 2282 const ICData& ic_data = *call->ic_data();
2282 ASSERT(ic_data.HasOneTarget()); 2283 ASSERT(ic_data.HasOneTarget());
2283 Function& target = Function::Handle(I); 2284 Function& target = Function::Handle(Z);
2284 GrowableArray<intptr_t> class_ids; 2285 GrowableArray<intptr_t> class_ids;
2285 ic_data.GetCheckAt(0, &class_ids, &target); 2286 ic_data.GetCheckAt(0, &class_ids, &target);
2286 ASSERT(class_ids.length() == 1); 2287 ASSERT(class_ids.length() == 1);
2287 // Inline implicit instance getter. 2288 // Inline implicit instance getter.
2288 const String& field_name = 2289 const String& field_name =
2289 String::Handle(I, Field::NameFromGetter(call->function_name())); 2290 String::Handle(Z, Field::NameFromGetter(call->function_name()));
2290 const Field& field = 2291 const Field& field =
2291 Field::ZoneHandle(I, GetField(class_ids[0], field_name)); 2292 Field::ZoneHandle(Z, GetField(class_ids[0], field_name));
2292 ASSERT(!field.IsNull()); 2293 ASSERT(!field.IsNull());
2293 2294
2294 if (InstanceCallNeedsClassCheck(call, RawFunction::kImplicitGetter)) { 2295 if (InstanceCallNeedsClassCheck(call, RawFunction::kImplicitGetter)) {
2295 AddReceiverCheck(call); 2296 AddReceiverCheck(call);
2296 } 2297 }
2297 LoadFieldInstr* load = new(I) LoadFieldInstr( 2298 LoadFieldInstr* load = new(Z) LoadFieldInstr(
2298 new(I) Value(call->ArgumentAt(0)), 2299 new(Z) Value(call->ArgumentAt(0)),
2299 &field, 2300 &field,
2300 AbstractType::ZoneHandle(I, field.type()), 2301 AbstractType::ZoneHandle(Z, field.type()),
2301 call->token_pos()); 2302 call->token_pos());
2302 load->set_is_immutable(field.is_final()); 2303 load->set_is_immutable(field.is_final());
2303 if (field.guarded_cid() != kIllegalCid) { 2304 if (field.guarded_cid() != kIllegalCid) {
2304 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { 2305 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) {
2305 load->set_result_cid(field.guarded_cid()); 2306 load->set_result_cid(field.guarded_cid());
2306 } 2307 }
2307 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); 2308 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field);
2308 } 2309 }
2309 2310
2310 // Discard the environment from the original instruction because the load 2311 // Discard the environment from the original instruction because the load
(...skipping 12 matching lines...) Expand all
2323 } 2324 }
2324 2325
2325 2326
2326 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, 2327 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call,
2327 MethodRecognizer::Kind getter) { 2328 MethodRecognizer::Kind getter) {
2328 if (!ShouldInlineSimd()) { 2329 if (!ShouldInlineSimd()) {
2329 return false; 2330 return false;
2330 } 2331 }
2331 AddCheckClass(call->ArgumentAt(0), 2332 AddCheckClass(call->ArgumentAt(0),
2332 ICData::ZoneHandle( 2333 ICData::ZoneHandle(
2333 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 2334 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
2334 call->deopt_id(), 2335 call->deopt_id(),
2335 call->env(), 2336 call->env(),
2336 call); 2337 call);
2337 intptr_t mask = 0; 2338 intptr_t mask = 0;
2338 if ((getter == MethodRecognizer::kFloat32x4Shuffle) || 2339 if ((getter == MethodRecognizer::kFloat32x4Shuffle) ||
2339 (getter == MethodRecognizer::kFloat32x4ShuffleMix)) { 2340 (getter == MethodRecognizer::kFloat32x4ShuffleMix)) {
2340 // Extract shuffle mask. 2341 // Extract shuffle mask.
2341 Definition* mask_definition = NULL; 2342 Definition* mask_definition = NULL;
2342 if (getter == MethodRecognizer::kFloat32x4Shuffle) { 2343 if (getter == MethodRecognizer::kFloat32x4Shuffle) {
2343 ASSERT(call->ArgumentCount() == 2); 2344 ASSERT(call->ArgumentCount() == 2);
(...skipping 13 matching lines...) Expand all
2357 return false; 2358 return false;
2358 } 2359 }
2359 ASSERT(constant_mask.IsSmi()); 2360 ASSERT(constant_mask.IsSmi());
2360 mask = Smi::Cast(constant_mask).Value(); 2361 mask = Smi::Cast(constant_mask).Value();
2361 if ((mask < 0) || (mask > 255)) { 2362 if ((mask < 0) || (mask > 255)) {
2362 // Not a valid mask. 2363 // Not a valid mask.
2363 return false; 2364 return false;
2364 } 2365 }
2365 } 2366 }
2366 if (getter == MethodRecognizer::kFloat32x4GetSignMask) { 2367 if (getter == MethodRecognizer::kFloat32x4GetSignMask) {
2367 Simd32x4GetSignMaskInstr* instr = new(I) Simd32x4GetSignMaskInstr( 2368 Simd32x4GetSignMaskInstr* instr = new(Z) Simd32x4GetSignMaskInstr(
2368 getter, 2369 getter,
2369 new(I) Value(call->ArgumentAt(0)), 2370 new(Z) Value(call->ArgumentAt(0)),
2370 call->deopt_id()); 2371 call->deopt_id());
2371 ReplaceCall(call, instr); 2372 ReplaceCall(call, instr);
2372 return true; 2373 return true;
2373 } else if (getter == MethodRecognizer::kFloat32x4ShuffleMix) { 2374 } else if (getter == MethodRecognizer::kFloat32x4ShuffleMix) {
2374 Simd32x4ShuffleMixInstr* instr = new(I) Simd32x4ShuffleMixInstr( 2375 Simd32x4ShuffleMixInstr* instr = new(Z) Simd32x4ShuffleMixInstr(
2375 getter, 2376 getter,
2376 new(I) Value(call->ArgumentAt(0)), 2377 new(Z) Value(call->ArgumentAt(0)),
2377 new(I) Value(call->ArgumentAt(1)), 2378 new(Z) Value(call->ArgumentAt(1)),
2378 mask, 2379 mask,
2379 call->deopt_id()); 2380 call->deopt_id());
2380 ReplaceCall(call, instr); 2381 ReplaceCall(call, instr);
2381 return true; 2382 return true;
2382 } else { 2383 } else {
2383 ASSERT((getter == MethodRecognizer::kFloat32x4Shuffle) || 2384 ASSERT((getter == MethodRecognizer::kFloat32x4Shuffle) ||
2384 (getter == MethodRecognizer::kFloat32x4ShuffleX) || 2385 (getter == MethodRecognizer::kFloat32x4ShuffleX) ||
2385 (getter == MethodRecognizer::kFloat32x4ShuffleY) || 2386 (getter == MethodRecognizer::kFloat32x4ShuffleY) ||
2386 (getter == MethodRecognizer::kFloat32x4ShuffleZ) || 2387 (getter == MethodRecognizer::kFloat32x4ShuffleZ) ||
2387 (getter == MethodRecognizer::kFloat32x4ShuffleW)); 2388 (getter == MethodRecognizer::kFloat32x4ShuffleW));
2388 Simd32x4ShuffleInstr* instr = new(I) Simd32x4ShuffleInstr( 2389 Simd32x4ShuffleInstr* instr = new(Z) Simd32x4ShuffleInstr(
2389 getter, 2390 getter,
2390 new(I) Value(call->ArgumentAt(0)), 2391 new(Z) Value(call->ArgumentAt(0)),
2391 mask, 2392 mask,
2392 call->deopt_id()); 2393 call->deopt_id());
2393 ReplaceCall(call, instr); 2394 ReplaceCall(call, instr);
2394 return true; 2395 return true;
2395 } 2396 }
2396 UNREACHABLE(); 2397 UNREACHABLE();
2397 return false; 2398 return false;
2398 } 2399 }
2399 2400
2400 2401
2401 bool FlowGraphOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call, 2402 bool FlowGraphOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call,
2402 MethodRecognizer::Kind getter) { 2403 MethodRecognizer::Kind getter) {
2403 if (!ShouldInlineSimd()) { 2404 if (!ShouldInlineSimd()) {
2404 return false; 2405 return false;
2405 } 2406 }
2406 AddCheckClass(call->ArgumentAt(0), 2407 AddCheckClass(call->ArgumentAt(0),
2407 ICData::ZoneHandle( 2408 ICData::ZoneHandle(
2408 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 2409 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
2409 call->deopt_id(), 2410 call->deopt_id(),
2410 call->env(), 2411 call->env(),
2411 call); 2412 call);
2412 if ((getter == MethodRecognizer::kFloat64x2GetX) || 2413 if ((getter == MethodRecognizer::kFloat64x2GetX) ||
2413 (getter == MethodRecognizer::kFloat64x2GetY)) { 2414 (getter == MethodRecognizer::kFloat64x2GetY)) {
2414 Simd64x2ShuffleInstr* instr = new(I) Simd64x2ShuffleInstr( 2415 Simd64x2ShuffleInstr* instr = new(Z) Simd64x2ShuffleInstr(
2415 getter, 2416 getter,
2416 new(I) Value(call->ArgumentAt(0)), 2417 new(Z) Value(call->ArgumentAt(0)),
2417 0, 2418 0,
2418 call->deopt_id()); 2419 call->deopt_id());
2419 ReplaceCall(call, instr); 2420 ReplaceCall(call, instr);
2420 return true; 2421 return true;
2421 } 2422 }
2422 UNREACHABLE(); 2423 UNREACHABLE();
2423 return false; 2424 return false;
2424 } 2425 }
2425 2426
2426 2427
2427 bool FlowGraphOptimizer::InlineInt32x4Getter(InstanceCallInstr* call, 2428 bool FlowGraphOptimizer::InlineInt32x4Getter(InstanceCallInstr* call,
2428 MethodRecognizer::Kind getter) { 2429 MethodRecognizer::Kind getter) {
2429 if (!ShouldInlineSimd()) { 2430 if (!ShouldInlineSimd()) {
2430 return false; 2431 return false;
2431 } 2432 }
2432 AddCheckClass(call->ArgumentAt(0), 2433 AddCheckClass(call->ArgumentAt(0),
2433 ICData::ZoneHandle( 2434 ICData::ZoneHandle(
2434 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 2435 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
2435 call->deopt_id(), 2436 call->deopt_id(),
2436 call->env(), 2437 call->env(),
2437 call); 2438 call);
2438 intptr_t mask = 0; 2439 intptr_t mask = 0;
2439 if ((getter == MethodRecognizer::kInt32x4Shuffle) || 2440 if ((getter == MethodRecognizer::kInt32x4Shuffle) ||
2440 (getter == MethodRecognizer::kInt32x4ShuffleMix)) { 2441 (getter == MethodRecognizer::kInt32x4ShuffleMix)) {
2441 // Extract shuffle mask. 2442 // Extract shuffle mask.
2442 Definition* mask_definition = NULL; 2443 Definition* mask_definition = NULL;
2443 if (getter == MethodRecognizer::kInt32x4Shuffle) { 2444 if (getter == MethodRecognizer::kInt32x4Shuffle) {
2444 ASSERT(call->ArgumentCount() == 2); 2445 ASSERT(call->ArgumentCount() == 2);
(...skipping 13 matching lines...) Expand all
2458 return false; 2459 return false;
2459 } 2460 }
2460 ASSERT(constant_mask.IsSmi()); 2461 ASSERT(constant_mask.IsSmi());
2461 mask = Smi::Cast(constant_mask).Value(); 2462 mask = Smi::Cast(constant_mask).Value();
2462 if ((mask < 0) || (mask > 255)) { 2463 if ((mask < 0) || (mask > 255)) {
2463 // Not a valid mask. 2464 // Not a valid mask.
2464 return false; 2465 return false;
2465 } 2466 }
2466 } 2467 }
2467 if (getter == MethodRecognizer::kInt32x4GetSignMask) { 2468 if (getter == MethodRecognizer::kInt32x4GetSignMask) {
2468 Simd32x4GetSignMaskInstr* instr = new(I) Simd32x4GetSignMaskInstr( 2469 Simd32x4GetSignMaskInstr* instr = new(Z) Simd32x4GetSignMaskInstr(
2469 getter, 2470 getter,
2470 new(I) Value(call->ArgumentAt(0)), 2471 new(Z) Value(call->ArgumentAt(0)),
2471 call->deopt_id()); 2472 call->deopt_id());
2472 ReplaceCall(call, instr); 2473 ReplaceCall(call, instr);
2473 return true; 2474 return true;
2474 } else if (getter == MethodRecognizer::kInt32x4ShuffleMix) { 2475 } else if (getter == MethodRecognizer::kInt32x4ShuffleMix) {
2475 Simd32x4ShuffleMixInstr* instr = new(I) Simd32x4ShuffleMixInstr( 2476 Simd32x4ShuffleMixInstr* instr = new(Z) Simd32x4ShuffleMixInstr(
2476 getter, 2477 getter,
2477 new(I) Value(call->ArgumentAt(0)), 2478 new(Z) Value(call->ArgumentAt(0)),
2478 new(I) Value(call->ArgumentAt(1)), 2479 new(Z) Value(call->ArgumentAt(1)),
2479 mask, 2480 mask,
2480 call->deopt_id()); 2481 call->deopt_id());
2481 ReplaceCall(call, instr); 2482 ReplaceCall(call, instr);
2482 return true; 2483 return true;
2483 } else if (getter == MethodRecognizer::kInt32x4Shuffle) { 2484 } else if (getter == MethodRecognizer::kInt32x4Shuffle) {
2484 Simd32x4ShuffleInstr* instr = new(I) Simd32x4ShuffleInstr( 2485 Simd32x4ShuffleInstr* instr = new(Z) Simd32x4ShuffleInstr(
2485 getter, 2486 getter,
2486 new(I) Value(call->ArgumentAt(0)), 2487 new(Z) Value(call->ArgumentAt(0)),
2487 mask, 2488 mask,
2488 call->deopt_id()); 2489 call->deopt_id());
2489 ReplaceCall(call, instr); 2490 ReplaceCall(call, instr);
2490 return true; 2491 return true;
2491 } else { 2492 } else {
2492 Int32x4GetFlagInstr* instr = new(I) Int32x4GetFlagInstr( 2493 Int32x4GetFlagInstr* instr = new(Z) Int32x4GetFlagInstr(
2493 getter, 2494 getter,
2494 new(I) Value(call->ArgumentAt(0)), 2495 new(Z) Value(call->ArgumentAt(0)),
2495 call->deopt_id()); 2496 call->deopt_id());
2496 ReplaceCall(call, instr); 2497 ReplaceCall(call, instr);
2497 return true; 2498 return true;
2498 } 2499 }
2499 } 2500 }
2500 2501
2501 2502
2502 bool FlowGraphOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, 2503 bool FlowGraphOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call,
2503 Token::Kind op_kind) { 2504 Token::Kind op_kind) {
2504 if (!ShouldInlineSimd()) { 2505 if (!ShouldInlineSimd()) {
2505 return false; 2506 return false;
2506 } 2507 }
2507 ASSERT(call->ArgumentCount() == 2); 2508 ASSERT(call->ArgumentCount() == 2);
2508 Definition* left = call->ArgumentAt(0); 2509 Definition* left = call->ArgumentAt(0);
2509 Definition* right = call->ArgumentAt(1); 2510 Definition* right = call->ArgumentAt(1);
2510 // Type check left. 2511 // Type check left.
2511 AddCheckClass(left, 2512 AddCheckClass(left,
2512 ICData::ZoneHandle( 2513 ICData::ZoneHandle(
2513 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 2514 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
2514 call->deopt_id(), 2515 call->deopt_id(),
2515 call->env(), 2516 call->env(),
2516 call); 2517 call);
2517 // Type check right. 2518 // Type check right.
2518 AddCheckClass(right, 2519 AddCheckClass(right,
2519 ICData::ZoneHandle( 2520 ICData::ZoneHandle(
2520 I, call->ic_data()->AsUnaryClassChecksForArgNr(1)), 2521 Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)),
2521 call->deopt_id(), 2522 call->deopt_id(),
2522 call->env(), 2523 call->env(),
2523 call); 2524 call);
2524 // Replace call. 2525 // Replace call.
2525 BinaryFloat32x4OpInstr* float32x4_bin_op = 2526 BinaryFloat32x4OpInstr* float32x4_bin_op =
2526 new(I) BinaryFloat32x4OpInstr( 2527 new(Z) BinaryFloat32x4OpInstr(
2527 op_kind, new(I) Value(left), new(I) Value(right), 2528 op_kind, new(Z) Value(left), new(Z) Value(right),
2528 call->deopt_id()); 2529 call->deopt_id());
2529 ReplaceCall(call, float32x4_bin_op); 2530 ReplaceCall(call, float32x4_bin_op);
2530 2531
2531 return true; 2532 return true;
2532 } 2533 }
2533 2534
2534 2535
2535 bool FlowGraphOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, 2536 bool FlowGraphOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call,
2536 Token::Kind op_kind) { 2537 Token::Kind op_kind) {
2537 if (!ShouldInlineSimd()) { 2538 if (!ShouldInlineSimd()) {
2538 return false; 2539 return false;
2539 } 2540 }
2540 ASSERT(call->ArgumentCount() == 2); 2541 ASSERT(call->ArgumentCount() == 2);
2541 Definition* left = call->ArgumentAt(0); 2542 Definition* left = call->ArgumentAt(0);
2542 Definition* right = call->ArgumentAt(1); 2543 Definition* right = call->ArgumentAt(1);
2543 // Type check left. 2544 // Type check left.
2544 AddCheckClass(left, 2545 AddCheckClass(left,
2545 ICData::ZoneHandle( 2546 ICData::ZoneHandle(
2546 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 2547 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
2547 call->deopt_id(), 2548 call->deopt_id(),
2548 call->env(), 2549 call->env(),
2549 call); 2550 call);
2550 // Type check right. 2551 // Type check right.
2551 AddCheckClass(right, 2552 AddCheckClass(right,
2552 ICData::ZoneHandle(I, 2553 ICData::ZoneHandle(Z,
2553 call->ic_data()->AsUnaryClassChecksForArgNr(1)), 2554 call->ic_data()->AsUnaryClassChecksForArgNr(1)),
2554 call->deopt_id(), 2555 call->deopt_id(),
2555 call->env(), 2556 call->env(),
2556 call); 2557 call);
2557 // Replace call. 2558 // Replace call.
2558 BinaryInt32x4OpInstr* int32x4_bin_op = 2559 BinaryInt32x4OpInstr* int32x4_bin_op =
2559 new(I) BinaryInt32x4OpInstr( 2560 new(Z) BinaryInt32x4OpInstr(
2560 op_kind, new(I) Value(left), new(I) Value(right), 2561 op_kind, new(Z) Value(left), new(Z) Value(right),
2561 call->deopt_id()); 2562 call->deopt_id());
2562 ReplaceCall(call, int32x4_bin_op); 2563 ReplaceCall(call, int32x4_bin_op);
2563 return true; 2564 return true;
2564 } 2565 }
2565 2566
2566 2567
2567 bool FlowGraphOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, 2568 bool FlowGraphOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call,
2568 Token::Kind op_kind) { 2569 Token::Kind op_kind) {
2569 if (!ShouldInlineSimd()) { 2570 if (!ShouldInlineSimd()) {
2570 return false; 2571 return false;
(...skipping 10 matching lines...) Expand all
2581 call); 2582 call);
2582 // Type check right. 2583 // Type check right.
2583 AddCheckClass(right, 2584 AddCheckClass(right,
2584 ICData::ZoneHandle( 2585 ICData::ZoneHandle(
2585 call->ic_data()->AsUnaryClassChecksForArgNr(1)), 2586 call->ic_data()->AsUnaryClassChecksForArgNr(1)),
2586 call->deopt_id(), 2587 call->deopt_id(),
2587 call->env(), 2588 call->env(),
2588 call); 2589 call);
2589 // Replace call. 2590 // Replace call.
2590 BinaryFloat64x2OpInstr* float64x2_bin_op = 2591 BinaryFloat64x2OpInstr* float64x2_bin_op =
2591 new(I) BinaryFloat64x2OpInstr( 2592 new(Z) BinaryFloat64x2OpInstr(
2592 op_kind, new(I) Value(left), new(I) Value(right), 2593 op_kind, new(Z) Value(left), new(Z) Value(right),
2593 call->deopt_id()); 2594 call->deopt_id());
2594 ReplaceCall(call, float64x2_bin_op); 2595 ReplaceCall(call, float64x2_bin_op);
2595 return true; 2596 return true;
2596 } 2597 }
2597 2598
2598 2599
2599 // Only unique implicit instance getters can be currently handled. 2600 // Only unique implicit instance getters can be currently handled.
2600 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { 2601 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) {
2601 ASSERT(call->HasICData()); 2602 ASSERT(call->HasICData());
2602 const ICData& ic_data = *call->ic_data(); 2603 const ICData& ic_data = *call->ic_data();
2603 if (ic_data.NumberOfUsedChecks() == 0) { 2604 if (ic_data.NumberOfUsedChecks() == 0) {
2604 // No type feedback collected. 2605 // No type feedback collected.
2605 return false; 2606 return false;
2606 } 2607 }
2607 2608
2608 if (!ic_data.HasOneTarget()) { 2609 if (!ic_data.HasOneTarget()) {
2609 // Polymorphic sites are inlined like normal methods by conventional 2610 // Polymorphic sites are inlined like normal methods by conventional
2610 // inlining in FlowGraphInliner. 2611 // inlining in FlowGraphInliner.
2611 return false; 2612 return false;
2612 } 2613 }
2613 2614
2614 const Function& target = Function::Handle(I, ic_data.GetTargetAt(0)); 2615 const Function& target = Function::Handle(Z, ic_data.GetTargetAt(0));
2615 if (target.kind() != RawFunction::kImplicitGetter) { 2616 if (target.kind() != RawFunction::kImplicitGetter) {
2616 // Non-implicit getters are inlined like normal methods by conventional 2617 // Non-implicit getters are inlined like normal methods by conventional
2617 // inlining in FlowGraphInliner. 2618 // inlining in FlowGraphInliner.
2618 return false; 2619 return false;
2619 } 2620 }
2620 InlineImplicitInstanceGetter(call); 2621 InlineImplicitInstanceGetter(call);
2621 return true; 2622 return true;
2622 } 2623 }
2623 2624
2624 2625
2625 bool FlowGraphOptimizer::TryReplaceInstanceCallWithInline( 2626 bool FlowGraphOptimizer::TryReplaceInstanceCallWithInline(
2626 InstanceCallInstr* call) { 2627 InstanceCallInstr* call) {
2627 Function& target = Function::Handle(I); 2628 Function& target = Function::Handle(Z);
2628 GrowableArray<intptr_t> class_ids; 2629 GrowableArray<intptr_t> class_ids;
2629 call->ic_data()->GetCheckAt(0, &class_ids, &target); 2630 call->ic_data()->GetCheckAt(0, &class_ids, &target);
2630 const intptr_t receiver_cid = class_ids[0]; 2631 const intptr_t receiver_cid = class_ids[0];
2631 2632
2632 TargetEntryInstr* entry; 2633 TargetEntryInstr* entry;
2633 Definition* last; 2634 Definition* last;
2634 if (!TryInlineRecognizedMethod(receiver_cid, 2635 if (!TryInlineRecognizedMethod(receiver_cid,
2635 target, 2636 target,
2636 call, 2637 call,
2637 call->ArgumentAt(0), 2638 call->ArgumentAt(0),
(...skipping 29 matching lines...) Expand all
2667 2668
2668 // Returns the LoadIndexedInstr. 2669 // Returns the LoadIndexedInstr.
2669 Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp( 2670 Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp(
2670 Instruction* call, 2671 Instruction* call,
2671 intptr_t cid, 2672 intptr_t cid,
2672 Definition* str, 2673 Definition* str,
2673 Definition* index, 2674 Definition* index,
2674 Instruction* cursor) { 2675 Instruction* cursor) {
2675 2676
2676 cursor = flow_graph()->AppendTo(cursor, 2677 cursor = flow_graph()->AppendTo(cursor,
2677 new(I) CheckSmiInstr( 2678 new(Z) CheckSmiInstr(
2678 new(I) Value(index), 2679 new(Z) Value(index),
2679 call->deopt_id(), 2680 call->deopt_id(),
2680 call->token_pos()), 2681 call->token_pos()),
2681 call->env(), 2682 call->env(),
2682 FlowGraph::kEffect); 2683 FlowGraph::kEffect);
2683 2684
2684 // Load the length of the string. 2685 // Load the length of the string.
2685 // Treat length loads as mutable (i.e. affected by side effects) to avoid 2686 // Treat length loads as mutable (i.e. affected by side effects) to avoid
2686 // hoisting them since we can't hoist the preceding class-check. This 2687 // hoisting them since we can't hoist the preceding class-check. This
2687 // is because of externalization of strings that affects their class-id. 2688 // is because of externalization of strings that affects their class-id.
2688 LoadFieldInstr* length = new(I) LoadFieldInstr( 2689 LoadFieldInstr* length = new(Z) LoadFieldInstr(
2689 new(I) Value(str), 2690 new(Z) Value(str),
2690 String::length_offset(), 2691 String::length_offset(),
2691 Type::ZoneHandle(I, Type::SmiType()), 2692 Type::ZoneHandle(Z, Type::SmiType()),
2692 str->token_pos()); 2693 str->token_pos());
2693 length->set_result_cid(kSmiCid); 2694 length->set_result_cid(kSmiCid);
2694 length->set_recognized_kind(MethodRecognizer::kStringBaseLength); 2695 length->set_recognized_kind(MethodRecognizer::kStringBaseLength);
2695 2696
2696 cursor = flow_graph()->AppendTo(cursor, length, NULL, FlowGraph::kValue); 2697 cursor = flow_graph()->AppendTo(cursor, length, NULL, FlowGraph::kValue);
2697 // Bounds check. 2698 // Bounds check.
2698 cursor = flow_graph()->AppendTo(cursor, 2699 cursor = flow_graph()->AppendTo(cursor,
2699 new(I) CheckArrayBoundInstr( 2700 new(Z) CheckArrayBoundInstr(
2700 new(I) Value(length), 2701 new(Z) Value(length),
2701 new(I) Value(index), 2702 new(Z) Value(index),
2702 call->deopt_id()), 2703 call->deopt_id()),
2703 call->env(), 2704 call->env(),
2704 FlowGraph::kEffect); 2705 FlowGraph::kEffect);
2705 2706
2706 LoadIndexedInstr* load_indexed = new(I) LoadIndexedInstr( 2707 LoadIndexedInstr* load_indexed = new(Z) LoadIndexedInstr(
2707 new(I) Value(str), 2708 new(Z) Value(str),
2708 new(I) Value(index), 2709 new(Z) Value(index),
2709 Instance::ElementSizeFor(cid), 2710 Instance::ElementSizeFor(cid),
2710 cid, 2711 cid,
2711 Isolate::kNoDeoptId, 2712 Isolate::kNoDeoptId,
2712 call->token_pos()); 2713 call->token_pos());
2713 2714
2714 cursor = flow_graph()->AppendTo(cursor, 2715 cursor = flow_graph()->AppendTo(cursor,
2715 load_indexed, 2716 load_indexed,
2716 NULL, 2717 NULL,
2717 FlowGraph::kValue); 2718 FlowGraph::kValue);
2718 ASSERT(cursor == load_indexed); 2719 ASSERT(cursor == load_indexed);
2719 return load_indexed; 2720 return load_indexed;
2720 } 2721 }
2721 2722
2722 2723
2723 bool FlowGraphOptimizer::InlineStringCodeUnitAt( 2724 bool FlowGraphOptimizer::InlineStringCodeUnitAt(
2724 Instruction* call, 2725 Instruction* call,
2725 intptr_t cid, 2726 intptr_t cid,
2726 TargetEntryInstr** entry, 2727 TargetEntryInstr** entry,
2727 Definition** last) { 2728 Definition** last) {
2728 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. 2729 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp.
2729 if (RawObject::IsExternalStringClassId(cid)) { 2730 if (RawObject::IsExternalStringClassId(cid)) {
2730 return false; 2731 return false;
2731 } 2732 }
2732 2733
2733 Definition* str = call->ArgumentAt(0); 2734 Definition* str = call->ArgumentAt(0);
2734 Definition* index = call->ArgumentAt(1); 2735 Definition* index = call->ArgumentAt(1);
2735 2736
2736 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), 2737 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
2737 call->GetBlock()->try_index()); 2738 call->GetBlock()->try_index());
2738 (*entry)->InheritDeoptTarget(I, call); 2739 (*entry)->InheritDeoptTarget(I, call);
2739 2740
2740 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); 2741 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry);
2741 2742
2742 return true; 2743 return true;
2743 } 2744 }
2744 2745
2745 2746
2746 bool FlowGraphOptimizer::InlineStringBaseCharAt( 2747 bool FlowGraphOptimizer::InlineStringBaseCharAt(
2747 Instruction* call, 2748 Instruction* call,
2748 intptr_t cid, 2749 intptr_t cid,
2749 TargetEntryInstr** entry, 2750 TargetEntryInstr** entry,
2750 Definition** last) { 2751 Definition** last) {
2751 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. 2752 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp.
2752 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { 2753 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) {
2753 return false; 2754 return false;
2754 } 2755 }
2755 Definition* str = call->ArgumentAt(0); 2756 Definition* str = call->ArgumentAt(0);
2756 Definition* index = call->ArgumentAt(1); 2757 Definition* index = call->ArgumentAt(1);
2757 2758
2758 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), 2759 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
2759 call->GetBlock()->try_index()); 2760 call->GetBlock()->try_index());
2760 (*entry)->InheritDeoptTarget(I, call); 2761 (*entry)->InheritDeoptTarget(I, call);
2761 2762
2762 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); 2763 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry);
2763 2764
2764 StringFromCharCodeInstr* char_at = new(I) StringFromCharCodeInstr( 2765 StringFromCharCodeInstr* char_at = new(Z) StringFromCharCodeInstr(
2765 new(I) Value(*last), cid); 2766 new(Z) Value(*last), cid);
2766 2767
2767 flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue); 2768 flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue);
2768 *last = char_at; 2769 *last = char_at;
2769 2770
2770 return true; 2771 return true;
2771 } 2772 }
2772 2773
2773 2774
2774 bool FlowGraphOptimizer::InlineDoubleOp( 2775 bool FlowGraphOptimizer::InlineDoubleOp(
2775 Token::Kind op_kind, 2776 Token::Kind op_kind,
2776 Instruction* call, 2777 Instruction* call,
2777 TargetEntryInstr** entry, 2778 TargetEntryInstr** entry,
2778 Definition** last) { 2779 Definition** last) {
2779 Definition* left = call->ArgumentAt(0); 2780 Definition* left = call->ArgumentAt(0);
2780 Definition* right = call->ArgumentAt(1); 2781 Definition* right = call->ArgumentAt(1);
2781 2782
2782 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), 2783 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
2783 call->GetBlock()->try_index()); 2784 call->GetBlock()->try_index());
2784 (*entry)->InheritDeoptTarget(I, call); 2785 (*entry)->InheritDeoptTarget(I, call);
2785 // Arguments are checked. No need for class check. 2786 // Arguments are checked. No need for class check.
2786 BinaryDoubleOpInstr* double_bin_op = 2787 BinaryDoubleOpInstr* double_bin_op =
2787 new(I) BinaryDoubleOpInstr(op_kind, 2788 new(Z) BinaryDoubleOpInstr(op_kind,
2788 new(I) Value(left), 2789 new(Z) Value(left),
2789 new(I) Value(right), 2790 new(Z) Value(right),
2790 call->deopt_id(), call->token_pos()); 2791 call->deopt_id(), call->token_pos());
2791 flow_graph()->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue); 2792 flow_graph()->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue);
2792 *last = double_bin_op; 2793 *last = double_bin_op;
2793 2794
2794 return true; 2795 return true;
2795 } 2796 }
2796 2797
2797 2798
2798 void FlowGraphOptimizer::ReplaceWithMathCFunction( 2799 void FlowGraphOptimizer::ReplaceWithMathCFunction(
2799 InstanceCallInstr* call, 2800 InstanceCallInstr* call,
2800 MethodRecognizer::Kind recognized_kind) { 2801 MethodRecognizer::Kind recognized_kind) {
2801 AddReceiverCheck(call); 2802 AddReceiverCheck(call);
2802 ZoneGrowableArray<Value*>* args = 2803 ZoneGrowableArray<Value*>* args =
2803 new(I) ZoneGrowableArray<Value*>(call->ArgumentCount()); 2804 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount());
2804 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { 2805 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
2805 args->Add(new(I) Value(call->ArgumentAt(i))); 2806 args->Add(new(Z) Value(call->ArgumentAt(i)));
2806 } 2807 }
2807 InvokeMathCFunctionInstr* invoke = 2808 InvokeMathCFunctionInstr* invoke =
2808 new(I) InvokeMathCFunctionInstr(args, 2809 new(Z) InvokeMathCFunctionInstr(args,
2809 call->deopt_id(), 2810 call->deopt_id(),
2810 recognized_kind, 2811 recognized_kind,
2811 call->token_pos()); 2812 call->token_pos());
2812 ReplaceCall(call, invoke); 2813 ReplaceCall(call, invoke);
2813 } 2814 }
2814 2815
2815 2816
2816 static bool IsSupportedByteArrayViewCid(intptr_t cid) { 2817 static bool IsSupportedByteArrayViewCid(intptr_t cid) {
2817 switch (cid) { 2818 switch (cid) {
2818 case kTypedDataInt8ArrayCid: 2819 case kTypedDataInt8ArrayCid:
(...skipping 18 matching lines...) Expand all
2837 2838
2838 // Inline only simple, frequently called core library methods. 2839 // Inline only simple, frequently called core library methods.
2839 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { 2840 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
2840 ASSERT(call->HasICData()); 2841 ASSERT(call->HasICData());
2841 const ICData& ic_data = *call->ic_data(); 2842 const ICData& ic_data = *call->ic_data();
2842 if ((ic_data.NumberOfUsedChecks() == 0) || !ic_data.HasOneTarget()) { 2843 if ((ic_data.NumberOfUsedChecks() == 0) || !ic_data.HasOneTarget()) {
2843 // No type feedback collected or multiple targets found. 2844 // No type feedback collected or multiple targets found.
2844 return false; 2845 return false;
2845 } 2846 }
2846 2847
2847 Function& target = Function::Handle(I); 2848 Function& target = Function::Handle(Z);
2848 GrowableArray<intptr_t> class_ids; 2849 GrowableArray<intptr_t> class_ids;
2849 ic_data.GetCheckAt(0, &class_ids, &target); 2850 ic_data.GetCheckAt(0, &class_ids, &target);
2850 MethodRecognizer::Kind recognized_kind = 2851 MethodRecognizer::Kind recognized_kind =
2851 MethodRecognizer::RecognizeKind(target); 2852 MethodRecognizer::RecognizeKind(target);
2852 2853
2853 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) && 2854 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) &&
2854 (ic_data.NumberOfChecks() == 1) && 2855 (ic_data.NumberOfChecks() == 1) &&
2855 (class_ids[0] == kGrowableObjectArrayCid)) { 2856 (class_ids[0] == kGrowableObjectArrayCid)) {
2856 // This is an internal method, no need to check argument types. 2857 // This is an internal method, no need to check argument types.
2857 Definition* array = call->ArgumentAt(0); 2858 Definition* array = call->ArgumentAt(0);
2858 Definition* value = call->ArgumentAt(1); 2859 Definition* value = call->ArgumentAt(1);
2859 StoreInstanceFieldInstr* store = new(I) StoreInstanceFieldInstr( 2860 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr(
2860 GrowableObjectArray::data_offset(), 2861 GrowableObjectArray::data_offset(),
2861 new(I) Value(array), 2862 new(Z) Value(array),
2862 new(I) Value(value), 2863 new(Z) Value(value),
2863 kEmitStoreBarrier, 2864 kEmitStoreBarrier,
2864 call->token_pos()); 2865 call->token_pos());
2865 ReplaceCall(call, store); 2866 ReplaceCall(call, store);
2866 return true; 2867 return true;
2867 } 2868 }
2868 2869
2869 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) && 2870 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) &&
2870 (ic_data.NumberOfChecks() == 1) && 2871 (ic_data.NumberOfChecks() == 1) &&
2871 (class_ids[0] == kGrowableObjectArrayCid)) { 2872 (class_ids[0] == kGrowableObjectArrayCid)) {
2872 // This is an internal method, no need to check argument types nor 2873 // This is an internal method, no need to check argument types nor
2873 // range. 2874 // range.
2874 Definition* array = call->ArgumentAt(0); 2875 Definition* array = call->ArgumentAt(0);
2875 Definition* value = call->ArgumentAt(1); 2876 Definition* value = call->ArgumentAt(1);
2876 StoreInstanceFieldInstr* store = new(I) StoreInstanceFieldInstr( 2877 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr(
2877 GrowableObjectArray::length_offset(), 2878 GrowableObjectArray::length_offset(),
2878 new(I) Value(array), 2879 new(Z) Value(array),
2879 new(I) Value(value), 2880 new(Z) Value(value),
2880 kNoStoreBarrier, 2881 kNoStoreBarrier,
2881 call->token_pos()); 2882 call->token_pos());
2882 ReplaceCall(call, store); 2883 ReplaceCall(call, store);
2883 return true; 2884 return true;
2884 } 2885 }
2885 2886
2886 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || 2887 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) ||
2887 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && 2888 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) &&
2888 (ic_data.NumberOfChecks() == 1) && 2889 (ic_data.NumberOfChecks() == 1) &&
2889 ((class_ids[0] == kOneByteStringCid) || 2890 ((class_ids[0] == kOneByteStringCid) ||
2890 (class_ids[0] == kTwoByteStringCid))) { 2891 (class_ids[0] == kTwoByteStringCid))) {
2891 return TryReplaceInstanceCallWithInline(call); 2892 return TryReplaceInstanceCallWithInline(call);
2892 } 2893 }
2893 2894
2894 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { 2895 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) {
2895 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { 2896 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) {
2896 // This is an internal method, no need to check argument types nor 2897 // This is an internal method, no need to check argument types nor
2897 // range. 2898 // range.
2898 Definition* str = call->ArgumentAt(0); 2899 Definition* str = call->ArgumentAt(0);
2899 Definition* index = call->ArgumentAt(1); 2900 Definition* index = call->ArgumentAt(1);
2900 Definition* value = call->ArgumentAt(2); 2901 Definition* value = call->ArgumentAt(2);
2901 StoreIndexedInstr* store_op = new(I) StoreIndexedInstr( 2902 StoreIndexedInstr* store_op = new(Z) StoreIndexedInstr(
2902 new(I) Value(str), 2903 new(Z) Value(str),
2903 new(I) Value(index), 2904 new(Z) Value(index),
2904 new(I) Value(value), 2905 new(Z) Value(value),
2905 kNoStoreBarrier, 2906 kNoStoreBarrier,
2906 1, // Index scale 2907 1, // Index scale
2907 kOneByteStringCid, 2908 kOneByteStringCid,
2908 call->deopt_id(), 2909 call->deopt_id(),
2909 call->token_pos()); 2910 call->token_pos());
2910 ReplaceCall(call, store_op); 2911 ReplaceCall(call, store_op);
2911 return true; 2912 return true;
2912 } 2913 }
2913 return false; 2914 return false;
2914 } 2915 }
2915 2916
2916 if (CanUnboxDouble() && 2917 if (CanUnboxDouble() &&
2917 (recognized_kind == MethodRecognizer::kIntegerToDouble) && 2918 (recognized_kind == MethodRecognizer::kIntegerToDouble) &&
2918 (ic_data.NumberOfChecks() == 1)) { 2919 (ic_data.NumberOfChecks() == 1)) {
2919 if (class_ids[0] == kSmiCid) { 2920 if (class_ids[0] == kSmiCid) {
2920 AddReceiverCheck(call); 2921 AddReceiverCheck(call);
2921 ReplaceCall(call, 2922 ReplaceCall(call,
2922 new(I) SmiToDoubleInstr( 2923 new(Z) SmiToDoubleInstr(
2923 new(I) Value(call->ArgumentAt(0)), 2924 new(Z) Value(call->ArgumentAt(0)),
2924 call->token_pos())); 2925 call->token_pos()));
2925 return true; 2926 return true;
2926 } else if ((class_ids[0] == kMintCid) && CanConvertUnboxedMintToDouble()) { 2927 } else if ((class_ids[0] == kMintCid) && CanConvertUnboxedMintToDouble()) {
2927 AddReceiverCheck(call); 2928 AddReceiverCheck(call);
2928 ReplaceCall(call, 2929 ReplaceCall(call,
2929 new(I) MintToDoubleInstr(new(I) Value(call->ArgumentAt(0)), 2930 new(Z) MintToDoubleInstr(new(Z) Value(call->ArgumentAt(0)),
2930 call->deopt_id())); 2931 call->deopt_id()));
2931 return true; 2932 return true;
2932 } 2933 }
2933 } 2934 }
2934 2935
2935 if (class_ids[0] == kDoubleCid) { 2936 if (class_ids[0] == kDoubleCid) {
2936 if (!CanUnboxDouble()) { 2937 if (!CanUnboxDouble()) {
2937 return false; 2938 return false;
2938 } 2939 }
2939 switch (recognized_kind) { 2940 switch (recognized_kind) {
2940 case MethodRecognizer::kDoubleToInteger: { 2941 case MethodRecognizer::kDoubleToInteger: {
2941 AddReceiverCheck(call); 2942 AddReceiverCheck(call);
2942 ASSERT(call->HasICData()); 2943 ASSERT(call->HasICData());
2943 const ICData& ic_data = *call->ic_data(); 2944 const ICData& ic_data = *call->ic_data();
2944 Definition* input = call->ArgumentAt(0); 2945 Definition* input = call->ArgumentAt(0);
2945 Definition* d2i_instr = NULL; 2946 Definition* d2i_instr = NULL;
2946 if (ic_data.HasDeoptReason(ICData::kDeoptDoubleToSmi)) { 2947 if (ic_data.HasDeoptReason(ICData::kDeoptDoubleToSmi)) {
2947 // Do not repeatedly deoptimize because result didn't fit into Smi. 2948 // Do not repeatedly deoptimize because result didn't fit into Smi.
2948 d2i_instr = new(I) DoubleToIntegerInstr( 2949 d2i_instr = new(Z) DoubleToIntegerInstr(
2949 new(I) Value(input), call); 2950 new(Z) Value(input), call);
2950 } else { 2951 } else {
2951 // Optimistically assume result fits into Smi. 2952 // Optimistically assume result fits into Smi.
2952 d2i_instr = new(I) DoubleToSmiInstr( 2953 d2i_instr = new(Z) DoubleToSmiInstr(
2953 new(I) Value(input), call->deopt_id()); 2954 new(Z) Value(input), call->deopt_id());
2954 } 2955 }
2955 ReplaceCall(call, d2i_instr); 2956 ReplaceCall(call, d2i_instr);
2956 return true; 2957 return true;
2957 } 2958 }
2958 case MethodRecognizer::kDoubleMod: 2959 case MethodRecognizer::kDoubleMod:
2959 case MethodRecognizer::kDoubleRound: 2960 case MethodRecognizer::kDoubleRound:
2960 ReplaceWithMathCFunction(call, recognized_kind); 2961 ReplaceWithMathCFunction(call, recognized_kind);
2961 return true; 2962 return true;
2962 case MethodRecognizer::kDoubleTruncate: 2963 case MethodRecognizer::kDoubleTruncate:
2963 case MethodRecognizer::kDoubleFloor: 2964 case MethodRecognizer::kDoubleFloor:
2964 case MethodRecognizer::kDoubleCeil: 2965 case MethodRecognizer::kDoubleCeil:
2965 if (!TargetCPUFeatures::double_truncate_round_supported()) { 2966 if (!TargetCPUFeatures::double_truncate_round_supported()) {
2966 ReplaceWithMathCFunction(call, recognized_kind); 2967 ReplaceWithMathCFunction(call, recognized_kind);
2967 } else { 2968 } else {
2968 AddReceiverCheck(call); 2969 AddReceiverCheck(call);
2969 DoubleToDoubleInstr* d2d_instr = 2970 DoubleToDoubleInstr* d2d_instr =
2970 new(I) DoubleToDoubleInstr(new(I) Value(call->ArgumentAt(0)), 2971 new(Z) DoubleToDoubleInstr(new(Z) Value(call->ArgumentAt(0)),
2971 recognized_kind, call->deopt_id()); 2972 recognized_kind, call->deopt_id());
2972 ReplaceCall(call, d2d_instr); 2973 ReplaceCall(call, d2d_instr);
2973 } 2974 }
2974 return true; 2975 return true;
2975 case MethodRecognizer::kDoubleAdd: 2976 case MethodRecognizer::kDoubleAdd:
2976 case MethodRecognizer::kDoubleSub: 2977 case MethodRecognizer::kDoubleSub:
2977 case MethodRecognizer::kDoubleMul: 2978 case MethodRecognizer::kDoubleMul:
2978 case MethodRecognizer::kDoubleDiv: 2979 case MethodRecognizer::kDoubleDiv:
2979 return TryReplaceInstanceCallWithInline(call); 2980 return TryReplaceInstanceCallWithInline(call);
2980 default: 2981 default:
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
3083 ASSERT(int32_mask->IsConstant()); 3084 ASSERT(int32_mask->IsConstant());
3084 const Integer& mask_literal = Integer::Cast( 3085 const Integer& mask_literal = Integer::Cast(
3085 int32_mask->AsConstant()->value()); 3086 int32_mask->AsConstant()->value());
3086 const int64_t mask_value = mask_literal.AsInt64Value(); 3087 const int64_t mask_value = mask_literal.AsInt64Value();
3087 ASSERT(mask_value >= 0); 3088 ASSERT(mask_value >= 0);
3088 if (mask_value > Smi::kMaxValue) { 3089 if (mask_value > Smi::kMaxValue) {
3089 // The result will not be Smi. 3090 // The result will not be Smi.
3090 return false; 3091 return false;
3091 } 3092 }
3092 BinarySmiOpInstr* left_shift = 3093 BinarySmiOpInstr* left_shift =
3093 new(I) BinarySmiOpInstr(Token::kSHL, 3094 new(Z) BinarySmiOpInstr(Token::kSHL,
3094 new(I) Value(value), 3095 new(Z) Value(value),
3095 new(I) Value(count), 3096 new(Z) Value(count),
3096 call->deopt_id()); 3097 call->deopt_id());
3097 left_shift->mark_truncating(); 3098 left_shift->mark_truncating();
3098 if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) { 3099 if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) {
3099 // No BIT_AND operation needed. 3100 // No BIT_AND operation needed.
3100 ReplaceCall(call, left_shift); 3101 ReplaceCall(call, left_shift);
3101 } else { 3102 } else {
3102 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue); 3103 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue);
3103 BinarySmiOpInstr* bit_and = 3104 BinarySmiOpInstr* bit_and =
3104 new(I) BinarySmiOpInstr(Token::kBIT_AND, 3105 new(Z) BinarySmiOpInstr(Token::kBIT_AND,
3105 new(I) Value(left_shift), 3106 new(Z) Value(left_shift),
3106 new(I) Value(int32_mask), 3107 new(Z) Value(int32_mask),
3107 call->deopt_id()); 3108 call->deopt_id());
3108 ReplaceCall(call, bit_and); 3109 ReplaceCall(call, bit_and);
3109 } 3110 }
3110 return true; 3111 return true;
3111 } 3112 }
3112 3113
3113 if (HasTwoMintOrSmi(ic_data) && 3114 if (HasTwoMintOrSmi(ic_data) &&
3114 HasOnlyOneSmi(ICData::Handle(I, 3115 HasOnlyOneSmi(ICData::Handle(Z,
3115 ic_data.AsUnaryClassChecksForArgNr(1)))) { 3116 ic_data.AsUnaryClassChecksForArgNr(1)))) {
3116 if (!FlowGraphCompiler::SupportsUnboxedMints() || 3117 if (!FlowGraphCompiler::SupportsUnboxedMints() ||
3117 ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) { 3118 ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) {
3118 return false; 3119 return false;
3119 } 3120 }
3120 ShiftMintOpInstr* left_shift = 3121 ShiftMintOpInstr* left_shift =
3121 new(I) ShiftMintOpInstr(Token::kSHL, 3122 new(Z) ShiftMintOpInstr(Token::kSHL,
3122 new(I) Value(value), 3123 new(Z) Value(value),
3123 new(I) Value(count), 3124 new(Z) Value(count),
3124 call->deopt_id()); 3125 call->deopt_id());
3125 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue); 3126 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue);
3126 BinaryMintOpInstr* bit_and = 3127 BinaryMintOpInstr* bit_and =
3127 new(I) BinaryMintOpInstr(Token::kBIT_AND, 3128 new(Z) BinaryMintOpInstr(Token::kBIT_AND,
3128 new(I) Value(left_shift), 3129 new(Z) Value(left_shift),
3129 new(I) Value(int32_mask), 3130 new(Z) Value(int32_mask),
3130 call->deopt_id()); 3131 call->deopt_id());
3131 ReplaceCall(call, bit_and); 3132 ReplaceCall(call, bit_and);
3132 return true; 3133 return true;
3133 } 3134 }
3134 } 3135 }
3135 return false; 3136 return false;
3136 } 3137 }
3137 3138
3138 3139
3139 bool FlowGraphOptimizer::TryInlineFloat32x4Constructor( 3140 bool FlowGraphOptimizer::TryInlineFloat32x4Constructor(
3140 StaticCallInstr* call, 3141 StaticCallInstr* call,
3141 MethodRecognizer::Kind recognized_kind) { 3142 MethodRecognizer::Kind recognized_kind) {
3142 if (!ShouldInlineSimd()) { 3143 if (!ShouldInlineSimd()) {
3143 return false; 3144 return false;
3144 } 3145 }
3145 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) { 3146 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) {
3146 Float32x4ZeroInstr* zero = new(I) Float32x4ZeroInstr(); 3147 Float32x4ZeroInstr* zero = new(Z) Float32x4ZeroInstr();
3147 ReplaceCall(call, zero); 3148 ReplaceCall(call, zero);
3148 return true; 3149 return true;
3149 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) { 3150 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) {
3150 Float32x4SplatInstr* splat = 3151 Float32x4SplatInstr* splat =
3151 new(I) Float32x4SplatInstr( 3152 new(Z) Float32x4SplatInstr(
3152 new(I) Value(call->ArgumentAt(1)), call->deopt_id()); 3153 new(Z) Value(call->ArgumentAt(1)), call->deopt_id());
3153 ReplaceCall(call, splat); 3154 ReplaceCall(call, splat);
3154 return true; 3155 return true;
3155 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) { 3156 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) {
3156 Float32x4ConstructorInstr* con = 3157 Float32x4ConstructorInstr* con =
3157 new(I) Float32x4ConstructorInstr( 3158 new(Z) Float32x4ConstructorInstr(
3158 new(I) Value(call->ArgumentAt(1)), 3159 new(Z) Value(call->ArgumentAt(1)),
3159 new(I) Value(call->ArgumentAt(2)), 3160 new(Z) Value(call->ArgumentAt(2)),
3160 new(I) Value(call->ArgumentAt(3)), 3161 new(Z) Value(call->ArgumentAt(3)),
3161 new(I) Value(call->ArgumentAt(4)), 3162 new(Z) Value(call->ArgumentAt(4)),
3162 call->deopt_id()); 3163 call->deopt_id());
3163 ReplaceCall(call, con); 3164 ReplaceCall(call, con);
3164 return true; 3165 return true;
3165 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromInt32x4Bits) { 3166 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromInt32x4Bits) {
3166 Int32x4ToFloat32x4Instr* cast = 3167 Int32x4ToFloat32x4Instr* cast =
3167 new(I) Int32x4ToFloat32x4Instr( 3168 new(Z) Int32x4ToFloat32x4Instr(
3168 new(I) Value(call->ArgumentAt(1)), call->deopt_id()); 3169 new(Z) Value(call->ArgumentAt(1)), call->deopt_id());
3169 ReplaceCall(call, cast); 3170 ReplaceCall(call, cast);
3170 return true; 3171 return true;
3171 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2) { 3172 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2) {
3172 Float64x2ToFloat32x4Instr* cast = 3173 Float64x2ToFloat32x4Instr* cast =
3173 new(I) Float64x2ToFloat32x4Instr( 3174 new(Z) Float64x2ToFloat32x4Instr(
3174 new(I) Value(call->ArgumentAt(1)), call->deopt_id()); 3175 new(Z) Value(call->ArgumentAt(1)), call->deopt_id());
3175 ReplaceCall(call, cast); 3176 ReplaceCall(call, cast);
3176 return true; 3177 return true;
3177 } 3178 }
3178 return false; 3179 return false;
3179 } 3180 }
3180 3181
3181 3182
3182 bool FlowGraphOptimizer::TryInlineFloat64x2Constructor( 3183 bool FlowGraphOptimizer::TryInlineFloat64x2Constructor(
3183 StaticCallInstr* call, 3184 StaticCallInstr* call,
3184 MethodRecognizer::Kind recognized_kind) { 3185 MethodRecognizer::Kind recognized_kind) {
3185 if (!ShouldInlineSimd()) { 3186 if (!ShouldInlineSimd()) {
3186 return false; 3187 return false;
3187 } 3188 }
3188 if (recognized_kind == MethodRecognizer::kFloat64x2Zero) { 3189 if (recognized_kind == MethodRecognizer::kFloat64x2Zero) {
3189 Float64x2ZeroInstr* zero = new(I) Float64x2ZeroInstr(); 3190 Float64x2ZeroInstr* zero = new(Z) Float64x2ZeroInstr();
3190 ReplaceCall(call, zero); 3191 ReplaceCall(call, zero);
3191 return true; 3192 return true;
3192 } else if (recognized_kind == MethodRecognizer::kFloat64x2Splat) { 3193 } else if (recognized_kind == MethodRecognizer::kFloat64x2Splat) {
3193 Float64x2SplatInstr* splat = 3194 Float64x2SplatInstr* splat =
3194 new(I) Float64x2SplatInstr( 3195 new(Z) Float64x2SplatInstr(
3195 new(I) Value(call->ArgumentAt(1)), call->deopt_id()); 3196 new(Z) Value(call->ArgumentAt(1)), call->deopt_id());
3196 ReplaceCall(call, splat); 3197 ReplaceCall(call, splat);
3197 return true; 3198 return true;
3198 } else if (recognized_kind == MethodRecognizer::kFloat64x2Constructor) { 3199 } else if (recognized_kind == MethodRecognizer::kFloat64x2Constructor) {
3199 Float64x2ConstructorInstr* con = 3200 Float64x2ConstructorInstr* con =
3200 new(I) Float64x2ConstructorInstr( 3201 new(Z) Float64x2ConstructorInstr(
3201 new(I) Value(call->ArgumentAt(1)), 3202 new(Z) Value(call->ArgumentAt(1)),
3202 new(I) Value(call->ArgumentAt(2)), 3203 new(Z) Value(call->ArgumentAt(2)),
3203 call->deopt_id()); 3204 call->deopt_id());
3204 ReplaceCall(call, con); 3205 ReplaceCall(call, con);
3205 return true; 3206 return true;
3206 } else if (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4) { 3207 } else if (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4) {
3207 Float32x4ToFloat64x2Instr* cast = 3208 Float32x4ToFloat64x2Instr* cast =
3208 new(I) Float32x4ToFloat64x2Instr( 3209 new(Z) Float32x4ToFloat64x2Instr(
3209 new(I) Value(call->ArgumentAt(1)), call->deopt_id()); 3210 new(Z) Value(call->ArgumentAt(1)), call->deopt_id());
3210 ReplaceCall(call, cast); 3211 ReplaceCall(call, cast);
3211 return true; 3212 return true;
3212 } 3213 }
3213 return false; 3214 return false;
3214 } 3215 }
3215 3216
3216 3217
3217 bool FlowGraphOptimizer::TryInlineInt32x4Constructor( 3218 bool FlowGraphOptimizer::TryInlineInt32x4Constructor(
3218 StaticCallInstr* call, 3219 StaticCallInstr* call,
3219 MethodRecognizer::Kind recognized_kind) { 3220 MethodRecognizer::Kind recognized_kind) {
3220 if (!ShouldInlineSimd()) { 3221 if (!ShouldInlineSimd()) {
3221 return false; 3222 return false;
3222 } 3223 }
3223 if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) { 3224 if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) {
3224 Int32x4BoolConstructorInstr* con = 3225 Int32x4BoolConstructorInstr* con =
3225 new(I) Int32x4BoolConstructorInstr( 3226 new(Z) Int32x4BoolConstructorInstr(
3226 new(I) Value(call->ArgumentAt(1)), 3227 new(Z) Value(call->ArgumentAt(1)),
3227 new(I) Value(call->ArgumentAt(2)), 3228 new(Z) Value(call->ArgumentAt(2)),
3228 new(I) Value(call->ArgumentAt(3)), 3229 new(Z) Value(call->ArgumentAt(3)),
3229 new(I) Value(call->ArgumentAt(4)), 3230 new(Z) Value(call->ArgumentAt(4)),
3230 call->deopt_id()); 3231 call->deopt_id());
3231 ReplaceCall(call, con); 3232 ReplaceCall(call, con);
3232 return true; 3233 return true;
3233 } else if (recognized_kind == MethodRecognizer::kInt32x4FromFloat32x4Bits) { 3234 } else if (recognized_kind == MethodRecognizer::kInt32x4FromFloat32x4Bits) {
3234 Float32x4ToInt32x4Instr* cast = 3235 Float32x4ToInt32x4Instr* cast =
3235 new(I) Float32x4ToInt32x4Instr( 3236 new(Z) Float32x4ToInt32x4Instr(
3236 new(I) Value(call->ArgumentAt(1)), call->deopt_id()); 3237 new(Z) Value(call->ArgumentAt(1)), call->deopt_id());
3237 ReplaceCall(call, cast); 3238 ReplaceCall(call, cast);
3238 return true; 3239 return true;
3239 } else if (recognized_kind == MethodRecognizer::kInt32x4Constructor) { 3240 } else if (recognized_kind == MethodRecognizer::kInt32x4Constructor) {
3240 Int32x4ConstructorInstr* con = 3241 Int32x4ConstructorInstr* con =
3241 new(I) Int32x4ConstructorInstr( 3242 new(Z) Int32x4ConstructorInstr(
3242 new(I) Value(call->ArgumentAt(1)), 3243 new(Z) Value(call->ArgumentAt(1)),
3243 new(I) Value(call->ArgumentAt(2)), 3244 new(Z) Value(call->ArgumentAt(2)),
3244 new(I) Value(call->ArgumentAt(3)), 3245 new(Z) Value(call->ArgumentAt(3)),
3245 new(I) Value(call->ArgumentAt(4)), 3246 new(Z) Value(call->ArgumentAt(4)),
3246 call->deopt_id()); 3247 call->deopt_id());
3247 ReplaceCall(call, con); 3248 ReplaceCall(call, con);
3248 return true; 3249 return true;
3249 } 3250 }
3250 return false; 3251 return false;
3251 } 3252 }
3252 3253
3253 3254
3254 bool FlowGraphOptimizer::TryInlineFloat32x4Method( 3255 bool FlowGraphOptimizer::TryInlineFloat32x4Method(
3255 InstanceCallInstr* call, 3256 InstanceCallInstr* call,
(...skipping 16 matching lines...) Expand all
3272 case MethodRecognizer::kFloat32x4GreaterThan: 3273 case MethodRecognizer::kFloat32x4GreaterThan:
3273 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: 3274 case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
3274 case MethodRecognizer::kFloat32x4LessThan: 3275 case MethodRecognizer::kFloat32x4LessThan:
3275 case MethodRecognizer::kFloat32x4LessThanOrEqual: 3276 case MethodRecognizer::kFloat32x4LessThanOrEqual:
3276 case MethodRecognizer::kFloat32x4NotEqual: { 3277 case MethodRecognizer::kFloat32x4NotEqual: {
3277 Definition* left = call->ArgumentAt(0); 3278 Definition* left = call->ArgumentAt(0);
3278 Definition* right = call->ArgumentAt(1); 3279 Definition* right = call->ArgumentAt(1);
3279 // Type check left. 3280 // Type check left.
3280 AddCheckClass(left, 3281 AddCheckClass(left,
3281 ICData::ZoneHandle( 3282 ICData::ZoneHandle(
3282 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 3283 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
3283 call->deopt_id(), 3284 call->deopt_id(),
3284 call->env(), 3285 call->env(),
3285 call); 3286 call);
3286 // Replace call. 3287 // Replace call.
3287 Float32x4ComparisonInstr* cmp = 3288 Float32x4ComparisonInstr* cmp =
3288 new(I) Float32x4ComparisonInstr(recognized_kind, 3289 new(Z) Float32x4ComparisonInstr(recognized_kind,
3289 new(I) Value(left), 3290 new(Z) Value(left),
3290 new(I) Value(right), 3291 new(Z) Value(right),
3291 call->deopt_id()); 3292 call->deopt_id());
3292 ReplaceCall(call, cmp); 3293 ReplaceCall(call, cmp);
3293 return true; 3294 return true;
3294 } 3295 }
3295 case MethodRecognizer::kFloat32x4Min: 3296 case MethodRecognizer::kFloat32x4Min:
3296 case MethodRecognizer::kFloat32x4Max: { 3297 case MethodRecognizer::kFloat32x4Max: {
3297 Definition* left = call->ArgumentAt(0); 3298 Definition* left = call->ArgumentAt(0);
3298 Definition* right = call->ArgumentAt(1); 3299 Definition* right = call->ArgumentAt(1);
3299 // Type check left. 3300 // Type check left.
3300 AddCheckClass(left, 3301 AddCheckClass(left,
3301 ICData::ZoneHandle( 3302 ICData::ZoneHandle(
3302 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 3303 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
3303 call->deopt_id(), 3304 call->deopt_id(),
3304 call->env(), 3305 call->env(),
3305 call); 3306 call);
3306 Float32x4MinMaxInstr* minmax = 3307 Float32x4MinMaxInstr* minmax =
3307 new(I) Float32x4MinMaxInstr( 3308 new(Z) Float32x4MinMaxInstr(
3308 recognized_kind, 3309 recognized_kind,
3309 new(I) Value(left), 3310 new(Z) Value(left),
3310 new(I) Value(right), 3311 new(Z) Value(right),
3311 call->deopt_id()); 3312 call->deopt_id());
3312 ReplaceCall(call, minmax); 3313 ReplaceCall(call, minmax);
3313 return true; 3314 return true;
3314 } 3315 }
3315 case MethodRecognizer::kFloat32x4Scale: { 3316 case MethodRecognizer::kFloat32x4Scale: {
3316 Definition* left = call->ArgumentAt(0); 3317 Definition* left = call->ArgumentAt(0);
3317 Definition* right = call->ArgumentAt(1); 3318 Definition* right = call->ArgumentAt(1);
3318 // Type check left. 3319 // Type check left.
3319 AddCheckClass(left, 3320 AddCheckClass(left,
3320 ICData::ZoneHandle( 3321 ICData::ZoneHandle(
3321 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 3322 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
3322 call->deopt_id(), 3323 call->deopt_id(),
3323 call->env(), 3324 call->env(),
3324 call); 3325 call);
3325 // Left and right values are swapped when handed to the instruction, 3326 // Left and right values are swapped when handed to the instruction,
3326 // this is done so that the double value is loaded into the output 3327 // this is done so that the double value is loaded into the output
3327 // register and can be destroyed. 3328 // register and can be destroyed.
3328 Float32x4ScaleInstr* scale = 3329 Float32x4ScaleInstr* scale =
3329 new(I) Float32x4ScaleInstr(recognized_kind, 3330 new(Z) Float32x4ScaleInstr(recognized_kind,
3330 new(I) Value(right), 3331 new(Z) Value(right),
3331 new(I) Value(left), 3332 new(Z) Value(left),
3332 call->deopt_id()); 3333 call->deopt_id());
3333 ReplaceCall(call, scale); 3334 ReplaceCall(call, scale);
3334 return true; 3335 return true;
3335 } 3336 }
3336 case MethodRecognizer::kFloat32x4Sqrt: 3337 case MethodRecognizer::kFloat32x4Sqrt:
3337 case MethodRecognizer::kFloat32x4ReciprocalSqrt: 3338 case MethodRecognizer::kFloat32x4ReciprocalSqrt:
3338 case MethodRecognizer::kFloat32x4Reciprocal: { 3339 case MethodRecognizer::kFloat32x4Reciprocal: {
3339 Definition* left = call->ArgumentAt(0); 3340 Definition* left = call->ArgumentAt(0);
3340 AddCheckClass(left, 3341 AddCheckClass(left,
3341 ICData::ZoneHandle( 3342 ICData::ZoneHandle(
3342 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 3343 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
3343 call->deopt_id(), 3344 call->deopt_id(),
3344 call->env(), 3345 call->env(),
3345 call); 3346 call);
3346 Float32x4SqrtInstr* sqrt = 3347 Float32x4SqrtInstr* sqrt =
3347 new(I) Float32x4SqrtInstr(recognized_kind, 3348 new(Z) Float32x4SqrtInstr(recognized_kind,
3348 new(I) Value(left), 3349 new(Z) Value(left),
3349 call->deopt_id()); 3350 call->deopt_id());
3350 ReplaceCall(call, sqrt); 3351 ReplaceCall(call, sqrt);
3351 return true; 3352 return true;
3352 } 3353 }
3353 case MethodRecognizer::kFloat32x4WithX: 3354 case MethodRecognizer::kFloat32x4WithX:
3354 case MethodRecognizer::kFloat32x4WithY: 3355 case MethodRecognizer::kFloat32x4WithY:
3355 case MethodRecognizer::kFloat32x4WithZ: 3356 case MethodRecognizer::kFloat32x4WithZ:
3356 case MethodRecognizer::kFloat32x4WithW: { 3357 case MethodRecognizer::kFloat32x4WithW: {
3357 Definition* left = call->ArgumentAt(0); 3358 Definition* left = call->ArgumentAt(0);
3358 Definition* right = call->ArgumentAt(1); 3359 Definition* right = call->ArgumentAt(1);
3359 // Type check left. 3360 // Type check left.
3360 AddCheckClass(left, 3361 AddCheckClass(left,
3361 ICData::ZoneHandle( 3362 ICData::ZoneHandle(
3362 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 3363 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
3363 call->deopt_id(), 3364 call->deopt_id(),
3364 call->env(), 3365 call->env(),
3365 call); 3366 call);
3366 Float32x4WithInstr* with = new(I) Float32x4WithInstr(recognized_kind, 3367 Float32x4WithInstr* with = new(Z) Float32x4WithInstr(recognized_kind,
3367 new(I) Value(left), 3368 new(Z) Value(left),
3368 new(I) Value(right), 3369 new(Z) Value(right),
3369 call->deopt_id()); 3370 call->deopt_id());
3370 ReplaceCall(call, with); 3371 ReplaceCall(call, with);
3371 return true; 3372 return true;
3372 } 3373 }
3373 case MethodRecognizer::kFloat32x4Absolute: 3374 case MethodRecognizer::kFloat32x4Absolute:
3374 case MethodRecognizer::kFloat32x4Negate: { 3375 case MethodRecognizer::kFloat32x4Negate: {
3375 Definition* left = call->ArgumentAt(0); 3376 Definition* left = call->ArgumentAt(0);
3376 // Type check left. 3377 // Type check left.
3377 AddCheckClass(left, 3378 AddCheckClass(left,
3378 ICData::ZoneHandle( 3379 ICData::ZoneHandle(
3379 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 3380 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
3380 call->deopt_id(), 3381 call->deopt_id(),
3381 call->env(), 3382 call->env(),
3382 call); 3383 call);
3383 Float32x4ZeroArgInstr* zeroArg = 3384 Float32x4ZeroArgInstr* zeroArg =
3384 new(I) Float32x4ZeroArgInstr( 3385 new(Z) Float32x4ZeroArgInstr(
3385 recognized_kind, new(I) Value(left), call->deopt_id()); 3386 recognized_kind, new(Z) Value(left), call->deopt_id());
3386 ReplaceCall(call, zeroArg); 3387 ReplaceCall(call, zeroArg);
3387 return true; 3388 return true;
3388 } 3389 }
3389 case MethodRecognizer::kFloat32x4Clamp: { 3390 case MethodRecognizer::kFloat32x4Clamp: {
3390 Definition* left = call->ArgumentAt(0); 3391 Definition* left = call->ArgumentAt(0);
3391 Definition* lower = call->ArgumentAt(1); 3392 Definition* lower = call->ArgumentAt(1);
3392 Definition* upper = call->ArgumentAt(2); 3393 Definition* upper = call->ArgumentAt(2);
3393 // Type check left. 3394 // Type check left.
3394 AddCheckClass(left, 3395 AddCheckClass(left,
3395 ICData::ZoneHandle( 3396 ICData::ZoneHandle(
3396 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 3397 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
3397 call->deopt_id(), 3398 call->deopt_id(),
3398 call->env(), 3399 call->env(),
3399 call); 3400 call);
3400 Float32x4ClampInstr* clamp = new(I) Float32x4ClampInstr( 3401 Float32x4ClampInstr* clamp = new(Z) Float32x4ClampInstr(
3401 new(I) Value(left), 3402 new(Z) Value(left),
3402 new(I) Value(lower), 3403 new(Z) Value(lower),
3403 new(I) Value(upper), 3404 new(Z) Value(upper),
3404 call->deopt_id()); 3405 call->deopt_id());
3405 ReplaceCall(call, clamp); 3406 ReplaceCall(call, clamp);
3406 return true; 3407 return true;
3407 } 3408 }
3408 case MethodRecognizer::kFloat32x4ShuffleMix: 3409 case MethodRecognizer::kFloat32x4ShuffleMix:
3409 case MethodRecognizer::kFloat32x4Shuffle: { 3410 case MethodRecognizer::kFloat32x4Shuffle: {
3410 return InlineFloat32x4Getter(call, recognized_kind); 3411 return InlineFloat32x4Getter(call, recognized_kind);
3411 } 3412 }
3412 default: 3413 default:
3413 return false; 3414 return false;
(...skipping 15 matching lines...) Expand all
3429 ASSERT(call->ic_data()->HasOneTarget()); 3430 ASSERT(call->ic_data()->HasOneTarget());
3430 return InlineFloat64x2Getter(call, recognized_kind); 3431 return InlineFloat64x2Getter(call, recognized_kind);
3431 case MethodRecognizer::kFloat64x2Negate: 3432 case MethodRecognizer::kFloat64x2Negate:
3432 case MethodRecognizer::kFloat64x2Abs: 3433 case MethodRecognizer::kFloat64x2Abs:
3433 case MethodRecognizer::kFloat64x2Sqrt: 3434 case MethodRecognizer::kFloat64x2Sqrt:
3434 case MethodRecognizer::kFloat64x2GetSignMask: { 3435 case MethodRecognizer::kFloat64x2GetSignMask: {
3435 Definition* left = call->ArgumentAt(0); 3436 Definition* left = call->ArgumentAt(0);
3436 // Type check left. 3437 // Type check left.
3437 AddCheckClass(left, 3438 AddCheckClass(left,
3438 ICData::ZoneHandle( 3439 ICData::ZoneHandle(
3439 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 3440 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
3440 call->deopt_id(), 3441 call->deopt_id(),
3441 call->env(), 3442 call->env(),
3442 call); 3443 call);
3443 Float64x2ZeroArgInstr* zeroArg = 3444 Float64x2ZeroArgInstr* zeroArg =
3444 new(I) Float64x2ZeroArgInstr( 3445 new(Z) Float64x2ZeroArgInstr(
3445 recognized_kind, new(I) Value(left), call->deopt_id()); 3446 recognized_kind, new(Z) Value(left), call->deopt_id());
3446 ReplaceCall(call, zeroArg); 3447 ReplaceCall(call, zeroArg);
3447 return true; 3448 return true;
3448 } 3449 }
3449 case MethodRecognizer::kFloat64x2Scale: 3450 case MethodRecognizer::kFloat64x2Scale:
3450 case MethodRecognizer::kFloat64x2WithX: 3451 case MethodRecognizer::kFloat64x2WithX:
3451 case MethodRecognizer::kFloat64x2WithY: 3452 case MethodRecognizer::kFloat64x2WithY:
3452 case MethodRecognizer::kFloat64x2Min: 3453 case MethodRecognizer::kFloat64x2Min:
3453 case MethodRecognizer::kFloat64x2Max: { 3454 case MethodRecognizer::kFloat64x2Max: {
3454 Definition* left = call->ArgumentAt(0); 3455 Definition* left = call->ArgumentAt(0);
3455 Definition* right = call->ArgumentAt(1); 3456 Definition* right = call->ArgumentAt(1);
3456 // Type check left. 3457 // Type check left.
3457 AddCheckClass(left, 3458 AddCheckClass(left,
3458 ICData::ZoneHandle( 3459 ICData::ZoneHandle(
3459 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 3460 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
3460 call->deopt_id(), 3461 call->deopt_id(),
3461 call->env(), 3462 call->env(),
3462 call); 3463 call);
3463 Float64x2OneArgInstr* zeroArg = 3464 Float64x2OneArgInstr* zeroArg =
3464 new(I) Float64x2OneArgInstr(recognized_kind, 3465 new(Z) Float64x2OneArgInstr(recognized_kind,
3465 new(I) Value(left), 3466 new(Z) Value(left),
3466 new(I) Value(right), 3467 new(Z) Value(right),
3467 call->deopt_id()); 3468 call->deopt_id());
3468 ReplaceCall(call, zeroArg); 3469 ReplaceCall(call, zeroArg);
3469 return true; 3470 return true;
3470 } 3471 }
3471 default: 3472 default:
3472 return false; 3473 return false;
3473 } 3474 }
3474 } 3475 }
3475 3476
3476 3477
(...skipping 16 matching lines...) Expand all
3493 ASSERT(call->ic_data()->HasOneTarget()); 3494 ASSERT(call->ic_data()->HasOneTarget());
3494 return InlineInt32x4Getter(call, recognized_kind); 3495 return InlineInt32x4Getter(call, recognized_kind);
3495 3496
3496 case MethodRecognizer::kInt32x4Select: { 3497 case MethodRecognizer::kInt32x4Select: {
3497 Definition* mask = call->ArgumentAt(0); 3498 Definition* mask = call->ArgumentAt(0);
3498 Definition* trueValue = call->ArgumentAt(1); 3499 Definition* trueValue = call->ArgumentAt(1);
3499 Definition* falseValue = call->ArgumentAt(2); 3500 Definition* falseValue = call->ArgumentAt(2);
3500 // Type check left. 3501 // Type check left.
3501 AddCheckClass(mask, 3502 AddCheckClass(mask,
3502 ICData::ZoneHandle( 3503 ICData::ZoneHandle(
3503 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 3504 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
3504 call->deopt_id(), 3505 call->deopt_id(),
3505 call->env(), 3506 call->env(),
3506 call); 3507 call);
3507 Int32x4SelectInstr* select = new(I) Int32x4SelectInstr( 3508 Int32x4SelectInstr* select = new(Z) Int32x4SelectInstr(
3508 new(I) Value(mask), 3509 new(Z) Value(mask),
3509 new(I) Value(trueValue), 3510 new(Z) Value(trueValue),
3510 new(I) Value(falseValue), 3511 new(Z) Value(falseValue),
3511 call->deopt_id()); 3512 call->deopt_id());
3512 ReplaceCall(call, select); 3513 ReplaceCall(call, select);
3513 return true; 3514 return true;
3514 } 3515 }
3515 case MethodRecognizer::kInt32x4WithFlagX: 3516 case MethodRecognizer::kInt32x4WithFlagX:
3516 case MethodRecognizer::kInt32x4WithFlagY: 3517 case MethodRecognizer::kInt32x4WithFlagY:
3517 case MethodRecognizer::kInt32x4WithFlagZ: 3518 case MethodRecognizer::kInt32x4WithFlagZ:
3518 case MethodRecognizer::kInt32x4WithFlagW: { 3519 case MethodRecognizer::kInt32x4WithFlagW: {
3519 Definition* left = call->ArgumentAt(0); 3520 Definition* left = call->ArgumentAt(0);
3520 Definition* flag = call->ArgumentAt(1); 3521 Definition* flag = call->ArgumentAt(1);
3521 // Type check left. 3522 // Type check left.
3522 AddCheckClass(left, 3523 AddCheckClass(left,
3523 ICData::ZoneHandle( 3524 ICData::ZoneHandle(
3524 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 3525 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
3525 call->deopt_id(), 3526 call->deopt_id(),
3526 call->env(), 3527 call->env(),
3527 call); 3528 call);
3528 Int32x4SetFlagInstr* setFlag = new(I) Int32x4SetFlagInstr( 3529 Int32x4SetFlagInstr* setFlag = new(Z) Int32x4SetFlagInstr(
3529 recognized_kind, 3530 recognized_kind,
3530 new(I) Value(left), 3531 new(Z) Value(left),
3531 new(I) Value(flag), 3532 new(Z) Value(flag),
3532 call->deopt_id()); 3533 call->deopt_id());
3533 ReplaceCall(call, setFlag); 3534 ReplaceCall(call, setFlag);
3534 return true; 3535 return true;
3535 } 3536 }
3536 default: 3537 default:
3537 return false; 3538 return false;
3538 } 3539 }
3539 } 3540 }
3540 3541
3541 3542
3542 bool FlowGraphOptimizer::InlineByteArrayBaseLoad(Instruction* call, 3543 bool FlowGraphOptimizer::InlineByteArrayBaseLoad(Instruction* call,
3543 Definition* receiver, 3544 Definition* receiver,
3544 intptr_t array_cid, 3545 intptr_t array_cid,
3545 intptr_t view_cid, 3546 intptr_t view_cid,
3546 const ICData& ic_data, 3547 const ICData& ic_data,
3547 TargetEntryInstr** entry, 3548 TargetEntryInstr** entry,
3548 Definition** last) { 3549 Definition** last) {
3549 ASSERT(array_cid != kIllegalCid); 3550 ASSERT(array_cid != kIllegalCid);
3550 Definition* array = receiver; 3551 Definition* array = receiver;
3551 Definition* index = call->ArgumentAt(1); 3552 Definition* index = call->ArgumentAt(1);
3552 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), 3553 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
3553 call->GetBlock()->try_index()); 3554 call->GetBlock()->try_index());
3554 (*entry)->InheritDeoptTarget(I, call); 3555 (*entry)->InheritDeoptTarget(I, call);
3555 Instruction* cursor = *entry; 3556 Instruction* cursor = *entry;
3556 3557
3557 array_cid = PrepareInlineByteArrayBaseOp(call, 3558 array_cid = PrepareInlineByteArrayBaseOp(call,
3558 array_cid, 3559 array_cid,
3559 view_cid, 3560 view_cid,
3560 &array, 3561 &array,
3561 index, 3562 index,
3562 &cursor); 3563 &cursor);
3563 3564
3564 intptr_t deopt_id = Isolate::kNoDeoptId; 3565 intptr_t deopt_id = Isolate::kNoDeoptId;
3565 if ((array_cid == kTypedDataInt32ArrayCid) || 3566 if ((array_cid == kTypedDataInt32ArrayCid) ||
3566 (array_cid == kTypedDataUint32ArrayCid)) { 3567 (array_cid == kTypedDataUint32ArrayCid)) {
3567 // Deoptimization may be needed if result does not always fit in a Smi. 3568 // Deoptimization may be needed if result does not always fit in a Smi.
3568 deopt_id = (kSmiBits >= 32) ? Isolate::kNoDeoptId : call->deopt_id(); 3569 deopt_id = (kSmiBits >= 32) ? Isolate::kNoDeoptId : call->deopt_id();
3569 } 3570 }
3570 3571
3571 *last = new(I) LoadIndexedInstr(new(I) Value(array), 3572 *last = new(Z) LoadIndexedInstr(new(Z) Value(array),
3572 new(I) Value(index), 3573 new(Z) Value(index),
3573 1, 3574 1,
3574 view_cid, 3575 view_cid,
3575 deopt_id, 3576 deopt_id,
3576 call->token_pos()); 3577 call->token_pos());
3577 cursor = flow_graph()->AppendTo( 3578 cursor = flow_graph()->AppendTo(
3578 cursor, 3579 cursor,
3579 *last, 3580 *last,
3580 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, 3581 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL,
3581 FlowGraph::kValue); 3582 FlowGraph::kValue);
3582 3583
3583 if (view_cid == kTypedDataFloat32ArrayCid) { 3584 if (view_cid == kTypedDataFloat32ArrayCid) {
3584 *last = new(I) FloatToDoubleInstr(new(I) Value(*last), deopt_id); 3585 *last = new(Z) FloatToDoubleInstr(new(Z) Value(*last), deopt_id);
3585 flow_graph()->AppendTo(cursor, 3586 flow_graph()->AppendTo(cursor,
3586 *last, 3587 *last,
3587 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, 3588 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL,
3588 FlowGraph::kValue); 3589 FlowGraph::kValue);
3589 } 3590 }
3590 return true; 3591 return true;
3591 } 3592 }
3592 3593
3593 3594
3594 bool FlowGraphOptimizer::InlineByteArrayBaseStore(const Function& target, 3595 bool FlowGraphOptimizer::InlineByteArrayBaseStore(const Function& target,
3595 Instruction* call, 3596 Instruction* call,
3596 Definition* receiver, 3597 Definition* receiver,
3597 intptr_t array_cid, 3598 intptr_t array_cid,
3598 intptr_t view_cid, 3599 intptr_t view_cid,
3599 const ICData& ic_data, 3600 const ICData& ic_data,
3600 TargetEntryInstr** entry, 3601 TargetEntryInstr** entry,
3601 Definition** last) { 3602 Definition** last) {
3602 ASSERT(array_cid != kIllegalCid); 3603 ASSERT(array_cid != kIllegalCid);
3603 Definition* array = receiver; 3604 Definition* array = receiver;
3604 Definition* index = call->ArgumentAt(1); 3605 Definition* index = call->ArgumentAt(1);
3605 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), 3606 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
3606 call->GetBlock()->try_index()); 3607 call->GetBlock()->try_index());
3607 (*entry)->InheritDeoptTarget(I, call); 3608 (*entry)->InheritDeoptTarget(I, call);
3608 Instruction* cursor = *entry; 3609 Instruction* cursor = *entry;
3609 3610
3610 array_cid = PrepareInlineByteArrayBaseOp(call, 3611 array_cid = PrepareInlineByteArrayBaseOp(call,
3611 array_cid, 3612 array_cid,
3612 view_cid, 3613 view_cid,
3613 &array, 3614 &array,
3614 index, 3615 index,
3615 &cursor); 3616 &cursor);
3616 3617
3617 // Extract the instance call so we can use the function_name in the stored 3618 // Extract the instance call so we can use the function_name in the stored
3618 // value check ICData. 3619 // value check ICData.
3619 InstanceCallInstr* i_call = NULL; 3620 InstanceCallInstr* i_call = NULL;
3620 if (call->IsPolymorphicInstanceCall()) { 3621 if (call->IsPolymorphicInstanceCall()) {
3621 i_call = call->AsPolymorphicInstanceCall()->instance_call(); 3622 i_call = call->AsPolymorphicInstanceCall()->instance_call();
3622 } else { 3623 } else {
3623 ASSERT(call->IsInstanceCall()); 3624 ASSERT(call->IsInstanceCall());
3624 i_call = call->AsInstanceCall(); 3625 i_call = call->AsInstanceCall();
3625 } 3626 }
3626 ASSERT(i_call != NULL); 3627 ASSERT(i_call != NULL);
3627 ICData& value_check = ICData::ZoneHandle(I); 3628 ICData& value_check = ICData::ZoneHandle(Z);
3628 switch (view_cid) { 3629 switch (view_cid) {
3629 case kTypedDataInt8ArrayCid: 3630 case kTypedDataInt8ArrayCid:
3630 case kTypedDataUint8ArrayCid: 3631 case kTypedDataUint8ArrayCid:
3631 case kTypedDataUint8ClampedArrayCid: 3632 case kTypedDataUint8ClampedArrayCid:
3632 case kExternalTypedDataUint8ArrayCid: 3633 case kExternalTypedDataUint8ArrayCid:
3633 case kExternalTypedDataUint8ClampedArrayCid: 3634 case kExternalTypedDataUint8ClampedArrayCid:
3634 case kTypedDataInt16ArrayCid: 3635 case kTypedDataInt16ArrayCid:
3635 case kTypedDataUint16ArrayCid: { 3636 case kTypedDataUint16ArrayCid: {
3636 // Check that value is always smi. 3637 // Check that value is always smi.
3637 value_check = ICData::New(flow_graph_->parsed_function()->function(), 3638 value_check = ICData::New(flow_graph_->parsed_function()->function(),
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
3690 UNREACHABLE(); 3691 UNREACHABLE();
3691 } 3692 }
3692 3693
3693 Definition* stored_value = call->ArgumentAt(2); 3694 Definition* stored_value = call->ArgumentAt(2);
3694 if (!value_check.IsNull()) { 3695 if (!value_check.IsNull()) {
3695 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), 3696 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(),
3696 call); 3697 call);
3697 } 3698 }
3698 3699
3699 if (view_cid == kTypedDataFloat32ArrayCid) { 3700 if (view_cid == kTypedDataFloat32ArrayCid) {
3700 stored_value = new(I) DoubleToFloatInstr( 3701 stored_value = new(Z) DoubleToFloatInstr(
3701 new(I) Value(stored_value), call->deopt_id()); 3702 new(Z) Value(stored_value), call->deopt_id());
3702 cursor = flow_graph()->AppendTo(cursor, 3703 cursor = flow_graph()->AppendTo(cursor,
3703 stored_value, 3704 stored_value,
3704 NULL, 3705 NULL,
3705 FlowGraph::kValue); 3706 FlowGraph::kValue);
3706 } else if (view_cid == kTypedDataInt32ArrayCid) { 3707 } else if (view_cid == kTypedDataInt32ArrayCid) {
3707 stored_value = new(I) UnboxInt32Instr( 3708 stored_value = new(Z) UnboxInt32Instr(
3708 UnboxInt32Instr::kTruncate, 3709 UnboxInt32Instr::kTruncate,
3709 new(I) Value(stored_value), 3710 new(Z) Value(stored_value),
3710 call->deopt_id()); 3711 call->deopt_id());
3711 cursor = flow_graph()->AppendTo(cursor, 3712 cursor = flow_graph()->AppendTo(cursor,
3712 stored_value, 3713 stored_value,
3713 call->env(), 3714 call->env(),
3714 FlowGraph::kValue); 3715 FlowGraph::kValue);
3715 } else if (view_cid == kTypedDataUint32ArrayCid) { 3716 } else if (view_cid == kTypedDataUint32ArrayCid) {
3716 stored_value = new(I) UnboxUint32Instr( 3717 stored_value = new(Z) UnboxUint32Instr(
3717 new(I) Value(stored_value), 3718 new(Z) Value(stored_value),
3718 call->deopt_id()); 3719 call->deopt_id());
3719 ASSERT(stored_value->AsUnboxInteger()->is_truncating()); 3720 ASSERT(stored_value->AsUnboxInteger()->is_truncating());
3720 cursor = flow_graph()->AppendTo(cursor, 3721 cursor = flow_graph()->AppendTo(cursor,
3721 stored_value, 3722 stored_value,
3722 call->env(), 3723 call->env(),
3723 FlowGraph::kValue); 3724 FlowGraph::kValue);
3724 } 3725 }
3725 3726
3726 StoreBarrierType needs_store_barrier = kNoStoreBarrier; 3727 StoreBarrierType needs_store_barrier = kNoStoreBarrier;
3727 *last = new(I) StoreIndexedInstr(new(I) Value(array), 3728 *last = new(Z) StoreIndexedInstr(new(Z) Value(array),
3728 new(I) Value(index), 3729 new(Z) Value(index),
3729 new(I) Value(stored_value), 3730 new(Z) Value(stored_value),
3730 needs_store_barrier, 3731 needs_store_barrier,
3731 1, // Index scale 3732 1, // Index scale
3732 view_cid, 3733 view_cid,
3733 call->deopt_id(), 3734 call->deopt_id(),
3734 call->token_pos()); 3735 call->token_pos());
3735 3736
3736 flow_graph()->AppendTo(cursor, 3737 flow_graph()->AppendTo(cursor,
3737 *last, 3738 *last,
3738 call->deopt_id() != Isolate::kNoDeoptId ? 3739 call->deopt_id() != Isolate::kNoDeoptId ?
3739 call->env() : NULL, 3740 call->env() : NULL,
3740 FlowGraph::kEffect); 3741 FlowGraph::kEffect);
3741 return true; 3742 return true;
3742 } 3743 }
3743 3744
3744 3745
3745 3746
3746 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayBaseOp( 3747 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayBaseOp(
3747 Instruction* call, 3748 Instruction* call,
3748 intptr_t array_cid, 3749 intptr_t array_cid,
3749 intptr_t view_cid, 3750 intptr_t view_cid,
3750 Definition** array, 3751 Definition** array,
3751 Definition* byte_index, 3752 Definition* byte_index,
3752 Instruction** cursor) { 3753 Instruction** cursor) {
3753 // Insert byte_index smi check. 3754 // Insert byte_index smi check.
3754 *cursor = flow_graph()->AppendTo(*cursor, 3755 *cursor = flow_graph()->AppendTo(*cursor,
3755 new(I) CheckSmiInstr( 3756 new(Z) CheckSmiInstr(
3756 new(I) Value(byte_index), 3757 new(Z) Value(byte_index),
3757 call->deopt_id(), 3758 call->deopt_id(),
3758 call->token_pos()), 3759 call->token_pos()),
3759 call->env(), 3760 call->env(),
3760 FlowGraph::kEffect); 3761 FlowGraph::kEffect);
3761 3762
3762 LoadFieldInstr* length = 3763 LoadFieldInstr* length =
3763 new(I) LoadFieldInstr( 3764 new(Z) LoadFieldInstr(
3764 new(I) Value(*array), 3765 new(Z) Value(*array),
3765 CheckArrayBoundInstr::LengthOffsetFor(array_cid), 3766 CheckArrayBoundInstr::LengthOffsetFor(array_cid),
3766 Type::ZoneHandle(I, Type::SmiType()), 3767 Type::ZoneHandle(Z, Type::SmiType()),
3767 call->token_pos()); 3768 call->token_pos());
3768 length->set_is_immutable(true); 3769 length->set_is_immutable(true);
3769 length->set_result_cid(kSmiCid); 3770 length->set_result_cid(kSmiCid);
3770 length->set_recognized_kind( 3771 length->set_recognized_kind(
3771 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); 3772 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
3772 *cursor = flow_graph()->AppendTo(*cursor, 3773 *cursor = flow_graph()->AppendTo(*cursor,
3773 length, 3774 length,
3774 NULL, 3775 NULL,
3775 FlowGraph::kValue); 3776 FlowGraph::kValue);
3776 3777
3777 intptr_t element_size = Instance::ElementSizeFor(array_cid); 3778 intptr_t element_size = Instance::ElementSizeFor(array_cid);
3778 ConstantInstr* bytes_per_element = 3779 ConstantInstr* bytes_per_element =
3779 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(element_size))); 3780 flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(element_size)));
3780 BinarySmiOpInstr* len_in_bytes = 3781 BinarySmiOpInstr* len_in_bytes =
3781 new(I) BinarySmiOpInstr(Token::kMUL, 3782 new(Z) BinarySmiOpInstr(Token::kMUL,
3782 new(I) Value(length), 3783 new(Z) Value(length),
3783 new(I) Value(bytes_per_element), 3784 new(Z) Value(bytes_per_element),
3784 call->deopt_id()); 3785 call->deopt_id());
3785 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(), 3786 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(),
3786 FlowGraph::kValue); 3787 FlowGraph::kValue);
3787 3788
3788 // adjusted_length = len_in_bytes - (element_size - 1). 3789 // adjusted_length = len_in_bytes - (element_size - 1).
3789 Definition* adjusted_length = len_in_bytes; 3790 Definition* adjusted_length = len_in_bytes;
3790 intptr_t adjustment = Instance::ElementSizeFor(view_cid) - 1; 3791 intptr_t adjustment = Instance::ElementSizeFor(view_cid) - 1;
3791 if (adjustment > 0) { 3792 if (adjustment > 0) {
3792 ConstantInstr* length_adjustment = 3793 ConstantInstr* length_adjustment =
3793 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(adjustment))); 3794 flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(adjustment)));
3794 adjusted_length = 3795 adjusted_length =
3795 new(I) BinarySmiOpInstr(Token::kSUB, 3796 new(Z) BinarySmiOpInstr(Token::kSUB,
3796 new(I) Value(len_in_bytes), 3797 new(Z) Value(len_in_bytes),
3797 new(I) Value(length_adjustment), 3798 new(Z) Value(length_adjustment),
3798 call->deopt_id()); 3799 call->deopt_id());
3799 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(), 3800 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(),
3800 FlowGraph::kValue); 3801 FlowGraph::kValue);
3801 } 3802 }
3802 3803
3803 // Check adjusted_length > 0. 3804 // Check adjusted_length > 0.
3804 ConstantInstr* zero = 3805 ConstantInstr* zero =
3805 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(0))); 3806 flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(0)));
3806 *cursor = flow_graph()->AppendTo(*cursor, 3807 *cursor = flow_graph()->AppendTo(*cursor,
3807 new(I) CheckArrayBoundInstr( 3808 new(Z) CheckArrayBoundInstr(
3808 new(I) Value(adjusted_length), 3809 new(Z) Value(adjusted_length),
3809 new(I) Value(zero), 3810 new(Z) Value(zero),
3810 call->deopt_id()), 3811 call->deopt_id()),
3811 call->env(), 3812 call->env(),
3812 FlowGraph::kEffect); 3813 FlowGraph::kEffect);
3813 // Check 0 <= byte_index < adjusted_length. 3814 // Check 0 <= byte_index < adjusted_length.
3814 *cursor = flow_graph()->AppendTo(*cursor, 3815 *cursor = flow_graph()->AppendTo(*cursor,
3815 new(I) CheckArrayBoundInstr( 3816 new(Z) CheckArrayBoundInstr(
3816 new(I) Value(adjusted_length), 3817 new(Z) Value(adjusted_length),
3817 new(I) Value(byte_index), 3818 new(Z) Value(byte_index),
3818 call->deopt_id()), 3819 call->deopt_id()),
3819 call->env(), 3820 call->env(),
3820 FlowGraph::kEffect); 3821 FlowGraph::kEffect);
3821 3822
3822 if (RawObject::IsExternalTypedDataClassId(array_cid)) { 3823 if (RawObject::IsExternalTypedDataClassId(array_cid)) {
3823 LoadUntaggedInstr* elements = 3824 LoadUntaggedInstr* elements =
3824 new(I) LoadUntaggedInstr(new(I) Value(*array), 3825 new(Z) LoadUntaggedInstr(new(Z) Value(*array),
3825 ExternalTypedData::data_offset()); 3826 ExternalTypedData::data_offset());
3826 *cursor = flow_graph()->AppendTo(*cursor, 3827 *cursor = flow_graph()->AppendTo(*cursor,
3827 elements, 3828 elements,
3828 NULL, 3829 NULL,
3829 FlowGraph::kValue); 3830 FlowGraph::kValue);
3830 *array = elements; 3831 *array = elements;
3831 } 3832 }
3832 return array_cid; 3833 return array_cid;
3833 } 3834 }
3834 3835
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
3873 // check. 3874 // check.
3874 RawBool* FlowGraphOptimizer::InstanceOfAsBool( 3875 RawBool* FlowGraphOptimizer::InstanceOfAsBool(
3875 const ICData& ic_data, 3876 const ICData& ic_data,
3876 const AbstractType& type, 3877 const AbstractType& type,
3877 ZoneGrowableArray<intptr_t>* results) const { 3878 ZoneGrowableArray<intptr_t>* results) const {
3878 ASSERT(results->is_empty()); 3879 ASSERT(results->is_empty());
3879 ASSERT(ic_data.NumArgsTested() == 1); // Unary checks only. 3880 ASSERT(ic_data.NumArgsTested() == 1); // Unary checks only.
3880 if (!type.IsInstantiated() || type.IsMalformedOrMalbounded()) { 3881 if (!type.IsInstantiated() || type.IsMalformedOrMalbounded()) {
3881 return Bool::null(); 3882 return Bool::null();
3882 } 3883 }
3883 const Class& type_class = Class::Handle(I, type.type_class()); 3884 const Class& type_class = Class::Handle(Z, type.type_class());
3884 const intptr_t num_type_args = type_class.NumTypeArguments(); 3885 const intptr_t num_type_args = type_class.NumTypeArguments();
3885 if (num_type_args > 0) { 3886 if (num_type_args > 0) {
3886 // Only raw types can be directly compared, thus disregarding type 3887 // Only raw types can be directly compared, thus disregarding type
3887 // arguments. 3888 // arguments.
3888 const intptr_t num_type_params = type_class.NumTypeParameters(); 3889 const intptr_t num_type_params = type_class.NumTypeParameters();
3889 const intptr_t from_index = num_type_args - num_type_params; 3890 const intptr_t from_index = num_type_args - num_type_params;
3890 const TypeArguments& type_arguments = 3891 const TypeArguments& type_arguments =
3891 TypeArguments::Handle(I, type.arguments()); 3892 TypeArguments::Handle(Z, type.arguments());
3892 const bool is_raw_type = type_arguments.IsNull() || 3893 const bool is_raw_type = type_arguments.IsNull() ||
3893 type_arguments.IsRaw(from_index, num_type_params); 3894 type_arguments.IsRaw(from_index, num_type_params);
3894 if (!is_raw_type) { 3895 if (!is_raw_type) {
3895 // Unknown result. 3896 // Unknown result.
3896 return Bool::null(); 3897 return Bool::null();
3897 } 3898 }
3898 } 3899 }
3899 3900
3900 const ClassTable& class_table = *isolate()->class_table(); 3901 const ClassTable& class_table = *isolate()->class_table();
3901 Bool& prev = Bool::Handle(I); 3902 Bool& prev = Bool::Handle(Z);
3902 Class& cls = Class::Handle(I); 3903 Class& cls = Class::Handle(Z);
3903 3904
3904 bool results_differ = false; 3905 bool results_differ = false;
3905 for (int i = 0; i < ic_data.NumberOfChecks(); i++) { 3906 for (int i = 0; i < ic_data.NumberOfChecks(); i++) {
3906 cls = class_table.At(ic_data.GetReceiverClassIdAt(i)); 3907 cls = class_table.At(ic_data.GetReceiverClassIdAt(i));
3907 if (cls.NumTypeArguments() > 0) { 3908 if (cls.NumTypeArguments() > 0) {
3908 return Bool::null(); 3909 return Bool::null();
3909 } 3910 }
3910 const bool is_subtype = cls.IsSubtypeOf( 3911 const bool is_subtype = cls.IsSubtypeOf(
3911 TypeArguments::Handle(I), 3912 TypeArguments::Handle(Z),
3912 type_class, 3913 type_class,
3913 TypeArguments::Handle(I), 3914 TypeArguments::Handle(Z),
3914 NULL); 3915 NULL);
3915 results->Add(cls.id()); 3916 results->Add(cls.id());
3916 results->Add(is_subtype); 3917 results->Add(is_subtype);
3917 if (prev.IsNull()) { 3918 if (prev.IsNull()) {
3918 prev = Bool::Get(is_subtype).raw(); 3919 prev = Bool::Get(is_subtype).raw();
3919 } else { 3920 } else {
3920 if (is_subtype != prev.value()) { 3921 if (is_subtype != prev.value()) {
3921 results_differ = true; 3922 results_differ = true;
3922 } 3923 }
3923 } 3924 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
4015 void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { 4016 void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
4016 ASSERT(Token::IsTypeTestOperator(call->token_kind())); 4017 ASSERT(Token::IsTypeTestOperator(call->token_kind()));
4017 Definition* left = call->ArgumentAt(0); 4018 Definition* left = call->ArgumentAt(0);
4018 Definition* instantiator = call->ArgumentAt(1); 4019 Definition* instantiator = call->ArgumentAt(1);
4019 Definition* type_args = call->ArgumentAt(2); 4020 Definition* type_args = call->ArgumentAt(2);
4020 const AbstractType& type = 4021 const AbstractType& type =
4021 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); 4022 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value());
4022 const bool negate = Bool::Cast( 4023 const bool negate = Bool::Cast(
4023 call->ArgumentAt(4)->OriginalDefinition()->AsConstant()->value()).value(); 4024 call->ArgumentAt(4)->OriginalDefinition()->AsConstant()->value()).value();
4024 const ICData& unary_checks = 4025 const ICData& unary_checks =
4025 ICData::ZoneHandle(I, call->ic_data()->AsUnaryClassChecks()); 4026 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
4026 if (FLAG_warn_on_javascript_compatibility && 4027 if (FLAG_warn_on_javascript_compatibility &&
4027 !unary_checks.IssuedJSWarning() && 4028 !unary_checks.IssuedJSWarning() &&
4028 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { 4029 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) {
4029 // No warning was reported yet for this type check, either because it has 4030 // No warning was reported yet for this type check, either because it has
4030 // not been executed yet, or because no problematic combinations of instance 4031 // not been executed yet, or because no problematic combinations of instance
4031 // type and test type have been encountered so far. A warning may still be 4032 // type and test type have been encountered so far. A warning may still be
4032 // reported, so do not replace the instance call. 4033 // reported, so do not replace the instance call.
4033 return; 4034 return;
4034 } 4035 }
4035 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { 4036 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) {
4036 ZoneGrowableArray<intptr_t>* results = 4037 ZoneGrowableArray<intptr_t>* results =
4037 new(I) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); 4038 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
4038 Bool& as_bool = 4039 Bool& as_bool =
4039 Bool::ZoneHandle(I, InstanceOfAsBool(unary_checks, type, results)); 4040 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results));
4040 if (as_bool.IsNull()) { 4041 if (as_bool.IsNull()) {
4041 if (results->length() == unary_checks.NumberOfChecks() * 2) { 4042 if (results->length() == unary_checks.NumberOfChecks() * 2) {
4042 const bool can_deopt = TryExpandTestCidsResult(results, type); 4043 const bool can_deopt = TryExpandTestCidsResult(results, type);
4043 TestCidsInstr* test_cids = new(I) TestCidsInstr( 4044 TestCidsInstr* test_cids = new(Z) TestCidsInstr(
4044 call->token_pos(), 4045 call->token_pos(),
4045 negate ? Token::kISNOT : Token::kIS, 4046 negate ? Token::kISNOT : Token::kIS,
4046 new(I) Value(left), 4047 new(Z) Value(left),
4047 *results, 4048 *results,
4048 can_deopt ? call->deopt_id() : Isolate::kNoDeoptId); 4049 can_deopt ? call->deopt_id() : Isolate::kNoDeoptId);
4049 // Remove type. 4050 // Remove type.
4050 ReplaceCall(call, test_cids); 4051 ReplaceCall(call, test_cids);
4051 return; 4052 return;
4052 } 4053 }
4053 } else { 4054 } else {
4054 // TODO(srdjan): Use TestCidsInstr also for this case. 4055 // TODO(srdjan): Use TestCidsInstr also for this case.
4055 // One result only. 4056 // One result only.
4056 AddReceiverCheck(call); 4057 AddReceiverCheck(call);
4057 if (negate) { 4058 if (negate) {
4058 as_bool = Bool::Get(!as_bool.value()).raw(); 4059 as_bool = Bool::Get(!as_bool.value()).raw();
4059 } 4060 }
4060 ConstantInstr* bool_const = flow_graph()->GetConstant(as_bool); 4061 ConstantInstr* bool_const = flow_graph()->GetConstant(as_bool);
4061 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 4062 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
4062 PushArgumentInstr* push = call->PushArgumentAt(i); 4063 PushArgumentInstr* push = call->PushArgumentAt(i);
4063 push->ReplaceUsesWith(push->value()->definition()); 4064 push->ReplaceUsesWith(push->value()->definition());
4064 push->RemoveFromGraph(); 4065 push->RemoveFromGraph();
4065 } 4066 }
4066 call->ReplaceUsesWith(bool_const); 4067 call->ReplaceUsesWith(bool_const);
4067 ASSERT(current_iterator()->Current() == call); 4068 ASSERT(current_iterator()->Current() == call);
4068 current_iterator()->RemoveCurrentFromGraph(); 4069 current_iterator()->RemoveCurrentFromGraph();
4069 return; 4070 return;
4070 } 4071 }
4071 } 4072 }
4072 4073
4073 if (TypeCheckAsClassEquality(type)) { 4074 if (TypeCheckAsClassEquality(type)) {
4074 LoadClassIdInstr* left_cid = new(I) LoadClassIdInstr(new(I) Value(left)); 4075 LoadClassIdInstr* left_cid = new(Z) LoadClassIdInstr(new(Z) Value(left));
4075 InsertBefore(call, 4076 InsertBefore(call,
4076 left_cid, 4077 left_cid,
4077 NULL, 4078 NULL,
4078 FlowGraph::kValue); 4079 FlowGraph::kValue);
4079 const intptr_t type_cid = Class::Handle(I, type.type_class()).id(); 4080 const intptr_t type_cid = Class::Handle(Z, type.type_class()).id();
4080 ConstantInstr* cid = 4081 ConstantInstr* cid =
4081 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(type_cid))); 4082 flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(type_cid)));
4082 4083
4083 StrictCompareInstr* check_cid = 4084 StrictCompareInstr* check_cid =
4084 new(I) StrictCompareInstr( 4085 new(Z) StrictCompareInstr(
4085 call->token_pos(), 4086 call->token_pos(),
4086 negate ? Token::kNE_STRICT : Token::kEQ_STRICT, 4087 negate ? Token::kNE_STRICT : Token::kEQ_STRICT,
4087 new(I) Value(left_cid), 4088 new(Z) Value(left_cid),
4088 new(I) Value(cid), 4089 new(Z) Value(cid),
4089 false); // No number check. 4090 false); // No number check.
4090 ReplaceCall(call, check_cid); 4091 ReplaceCall(call, check_cid);
4091 return; 4092 return;
4092 } 4093 }
4093 4094
4094 InstanceOfInstr* instance_of = 4095 InstanceOfInstr* instance_of =
4095 new(I) InstanceOfInstr(call->token_pos(), 4096 new(Z) InstanceOfInstr(call->token_pos(),
4096 new(I) Value(left), 4097 new(Z) Value(left),
4097 new(I) Value(instantiator), 4098 new(Z) Value(instantiator),
4098 new(I) Value(type_args), 4099 new(Z) Value(type_args),
4099 type, 4100 type,
4100 negate, 4101 negate,
4101 call->deopt_id()); 4102 call->deopt_id());
4102 ReplaceCall(call, instance_of); 4103 ReplaceCall(call, instance_of);
4103 } 4104 }
4104 4105
4105 4106
4106 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). 4107 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids).
4107 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { 4108 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
4108 ASSERT(Token::IsTypeCastOperator(call->token_kind())); 4109 ASSERT(Token::IsTypeCastOperator(call->token_kind()));
4109 Definition* left = call->ArgumentAt(0); 4110 Definition* left = call->ArgumentAt(0);
4110 Definition* instantiator = call->ArgumentAt(1); 4111 Definition* instantiator = call->ArgumentAt(1);
4111 Definition* type_args = call->ArgumentAt(2); 4112 Definition* type_args = call->ArgumentAt(2);
4112 const AbstractType& type = 4113 const AbstractType& type =
4113 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); 4114 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value());
4114 ASSERT(!type.IsMalformedOrMalbounded()); 4115 ASSERT(!type.IsMalformedOrMalbounded());
4115 const ICData& unary_checks = 4116 const ICData& unary_checks =
4116 ICData::ZoneHandle(I, call->ic_data()->AsUnaryClassChecks()); 4117 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
4117 if (FLAG_warn_on_javascript_compatibility && 4118 if (FLAG_warn_on_javascript_compatibility &&
4118 !unary_checks.IssuedJSWarning() && 4119 !unary_checks.IssuedJSWarning() &&
4119 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { 4120 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) {
4120 // No warning was reported yet for this type check, either because it has 4121 // No warning was reported yet for this type check, either because it has
4121 // not been executed yet, or because no problematic combinations of instance 4122 // not been executed yet, or because no problematic combinations of instance
4122 // type and test type have been encountered so far. A warning may still be 4123 // type and test type have been encountered so far. A warning may still be
4123 // reported, so do not replace the instance call. 4124 // reported, so do not replace the instance call.
4124 return; 4125 return;
4125 } 4126 }
4126 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { 4127 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) {
4127 ZoneGrowableArray<intptr_t>* results = 4128 ZoneGrowableArray<intptr_t>* results =
4128 new(I) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); 4129 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
4129 const Bool& as_bool = Bool::ZoneHandle(I, 4130 const Bool& as_bool = Bool::ZoneHandle(Z,
4130 InstanceOfAsBool(unary_checks, type, results)); 4131 InstanceOfAsBool(unary_checks, type, results));
4131 if (as_bool.raw() == Bool::True().raw()) { 4132 if (as_bool.raw() == Bool::True().raw()) {
4132 AddReceiverCheck(call); 4133 AddReceiverCheck(call);
4133 // Remove the original push arguments. 4134 // Remove the original push arguments.
4134 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 4135 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
4135 PushArgumentInstr* push = call->PushArgumentAt(i); 4136 PushArgumentInstr* push = call->PushArgumentAt(i);
4136 push->ReplaceUsesWith(push->value()->definition()); 4137 push->ReplaceUsesWith(push->value()->definition());
4137 push->RemoveFromGraph(); 4138 push->RemoveFromGraph();
4138 } 4139 }
4139 // Remove call, replace it with 'left'. 4140 // Remove call, replace it with 'left'.
4140 call->ReplaceUsesWith(left); 4141 call->ReplaceUsesWith(left);
4141 ASSERT(current_iterator()->Current() == call); 4142 ASSERT(current_iterator()->Current() == call);
4142 current_iterator()->RemoveCurrentFromGraph(); 4143 current_iterator()->RemoveCurrentFromGraph();
4143 return; 4144 return;
4144 } 4145 }
4145 } 4146 }
4146 const String& dst_name = String::ZoneHandle(I, 4147 const String& dst_name = String::ZoneHandle(Z,
4147 Symbols::New(Exceptions::kCastErrorDstName)); 4148 Symbols::New(Exceptions::kCastErrorDstName));
4148 AssertAssignableInstr* assert_as = 4149 AssertAssignableInstr* assert_as =
4149 new(I) AssertAssignableInstr(call->token_pos(), 4150 new(Z) AssertAssignableInstr(call->token_pos(),
4150 new(I) Value(left), 4151 new(Z) Value(left),
4151 new(I) Value(instantiator), 4152 new(Z) Value(instantiator),
4152 new(I) Value(type_args), 4153 new(Z) Value(type_args),
4153 type, 4154 type,
4154 dst_name, 4155 dst_name,
4155 call->deopt_id()); 4156 call->deopt_id());
4156 ReplaceCall(call, assert_as); 4157 ReplaceCall(call, assert_as);
4157 } 4158 }
4158 4159
4159 4160
4160 // Tries to optimize instance call by replacing it with a faster instruction 4161 // Tries to optimize instance call by replacing it with a faster instruction
4161 // (e.g, binary op, field load, ..). 4162 // (e.g, binary op, field load, ..).
4162 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { 4163 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
4163 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) { 4164 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) {
4164 return; 4165 return;
4165 } 4166 }
4166 4167
4167 const Token::Kind op_kind = instr->token_kind(); 4168 const Token::Kind op_kind = instr->token_kind();
4168 // Type test is special as it always gets converted into inlined code. 4169 // Type test is special as it always gets converted into inlined code.
4169 if (Token::IsTypeTestOperator(op_kind)) { 4170 if (Token::IsTypeTestOperator(op_kind)) {
4170 ReplaceWithInstanceOf(instr); 4171 ReplaceWithInstanceOf(instr);
4171 return; 4172 return;
4172 } 4173 }
4173 4174
4174 if (Token::IsTypeCastOperator(op_kind)) { 4175 if (Token::IsTypeCastOperator(op_kind)) {
4175 ReplaceWithTypeCast(instr); 4176 ReplaceWithTypeCast(instr);
4176 return; 4177 return;
4177 } 4178 }
4178 4179
4179 const ICData& unary_checks = 4180 const ICData& unary_checks =
4180 ICData::ZoneHandle(I, instr->ic_data()->AsUnaryClassChecks()); 4181 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks());
4181 4182
4182 const intptr_t max_checks = (op_kind == Token::kEQ) 4183 const intptr_t max_checks = (op_kind == Token::kEQ)
4183 ? FLAG_max_equality_polymorphic_checks 4184 ? FLAG_max_equality_polymorphic_checks
4184 : FLAG_max_polymorphic_checks; 4185 : FLAG_max_polymorphic_checks;
4185 if ((unary_checks.NumberOfChecks() > max_checks) && 4186 if ((unary_checks.NumberOfChecks() > max_checks) &&
4186 InstanceCallNeedsClassCheck(instr, RawFunction::kRegularFunction)) { 4187 InstanceCallNeedsClassCheck(instr, RawFunction::kRegularFunction)) {
4187 // Too many checks, it will be megamorphic which needs unary checks. 4188 // Too many checks, it will be megamorphic which needs unary checks.
4188 instr->set_ic_data(&unary_checks); 4189 instr->set_ic_data(&unary_checks);
4189 return; 4190 return;
4190 } 4191 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
4223 if (TryInlineInstanceMethod(instr)) { 4224 if (TryInlineInstanceMethod(instr)) {
4224 return; 4225 return;
4225 } 4226 }
4226 4227
4227 bool has_one_target = unary_checks.HasOneTarget(); 4228 bool has_one_target = unary_checks.HasOneTarget();
4228 4229
4229 if (has_one_target) { 4230 if (has_one_target) {
4230 // Check if the single target is a polymorphic target, if it is, 4231 // Check if the single target is a polymorphic target, if it is,
4231 // we don't have one target. 4232 // we don't have one target.
4232 const Function& target = 4233 const Function& target =
4233 Function::Handle(I, unary_checks.GetTargetAt(0)); 4234 Function::Handle(Z, unary_checks.GetTargetAt(0));
4234 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); 4235 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target);
4235 has_one_target = !polymorphic_target; 4236 has_one_target = !polymorphic_target;
4236 } 4237 }
4237 4238
4238 if (has_one_target) { 4239 if (has_one_target) {
4239 RawFunction::Kind function_kind = 4240 RawFunction::Kind function_kind =
4240 Function::Handle(I, unary_checks.GetTargetAt(0)).kind(); 4241 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind();
4241 if (!InstanceCallNeedsClassCheck(instr, function_kind)) { 4242 if (!InstanceCallNeedsClassCheck(instr, function_kind)) {
4242 const bool call_with_checks = false; 4243 const bool call_with_checks = false;
4243 PolymorphicInstanceCallInstr* call = 4244 PolymorphicInstanceCallInstr* call =
4244 new(I) PolymorphicInstanceCallInstr(instr, unary_checks, 4245 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks,
4245 call_with_checks); 4246 call_with_checks);
4246 instr->ReplaceWith(call, current_iterator()); 4247 instr->ReplaceWith(call, current_iterator());
4247 return; 4248 return;
4248 } 4249 }
4249 } 4250 }
4250 4251
4251 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { 4252 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) {
4252 bool call_with_checks; 4253 bool call_with_checks;
4253 if (has_one_target) { 4254 if (has_one_target) {
4254 // Type propagation has not run yet, we cannot eliminate the check. 4255 // Type propagation has not run yet, we cannot eliminate the check.
4255 AddReceiverCheck(instr); 4256 AddReceiverCheck(instr);
4256 // Call can still deoptimize, do not detach environment from instr. 4257 // Call can still deoptimize, do not detach environment from instr.
4257 call_with_checks = false; 4258 call_with_checks = false;
4258 } else { 4259 } else {
4259 call_with_checks = true; 4260 call_with_checks = true;
4260 } 4261 }
4261 PolymorphicInstanceCallInstr* call = 4262 PolymorphicInstanceCallInstr* call =
4262 new(I) PolymorphicInstanceCallInstr(instr, unary_checks, 4263 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks,
4263 call_with_checks); 4264 call_with_checks);
4264 instr->ReplaceWith(call, current_iterator()); 4265 instr->ReplaceWith(call, current_iterator());
4265 } 4266 }
4266 } 4267 }
4267 4268
4268 4269
4269 void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) { 4270 void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) {
4270 if (!CanUnboxDouble()) { 4271 if (!CanUnboxDouble()) {
4271 return; 4272 return;
4272 } 4273 }
4273 MethodRecognizer::Kind recognized_kind = 4274 MethodRecognizer::Kind recognized_kind =
4274 MethodRecognizer::RecognizeKind(call->function()); 4275 MethodRecognizer::RecognizeKind(call->function());
4275 MathUnaryInstr::MathUnaryKind unary_kind; 4276 MathUnaryInstr::MathUnaryKind unary_kind;
4276 switch (recognized_kind) { 4277 switch (recognized_kind) {
4277 case MethodRecognizer::kMathSqrt: 4278 case MethodRecognizer::kMathSqrt:
4278 unary_kind = MathUnaryInstr::kSqrt; 4279 unary_kind = MathUnaryInstr::kSqrt;
4279 break; 4280 break;
4280 case MethodRecognizer::kMathSin: 4281 case MethodRecognizer::kMathSin:
4281 unary_kind = MathUnaryInstr::kSin; 4282 unary_kind = MathUnaryInstr::kSin;
4282 break; 4283 break;
4283 case MethodRecognizer::kMathCos: 4284 case MethodRecognizer::kMathCos:
4284 unary_kind = MathUnaryInstr::kCos; 4285 unary_kind = MathUnaryInstr::kCos;
4285 break; 4286 break;
4286 default: 4287 default:
4287 unary_kind = MathUnaryInstr::kIllegal; 4288 unary_kind = MathUnaryInstr::kIllegal;
4288 break; 4289 break;
4289 } 4290 }
4290 if (unary_kind != MathUnaryInstr::kIllegal) { 4291 if (unary_kind != MathUnaryInstr::kIllegal) {
4291 MathUnaryInstr* math_unary = 4292 MathUnaryInstr* math_unary =
4292 new(I) MathUnaryInstr(unary_kind, 4293 new(Z) MathUnaryInstr(unary_kind,
4293 new(I) Value(call->ArgumentAt(0)), 4294 new(Z) Value(call->ArgumentAt(0)),
4294 call->deopt_id()); 4295 call->deopt_id());
4295 ReplaceCall(call, math_unary); 4296 ReplaceCall(call, math_unary);
4296 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) || 4297 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) ||
4297 (recognized_kind == MethodRecognizer::kFloat32x4Splat) || 4298 (recognized_kind == MethodRecognizer::kFloat32x4Splat) ||
4298 (recognized_kind == MethodRecognizer::kFloat32x4Constructor) || 4299 (recognized_kind == MethodRecognizer::kFloat32x4Constructor) ||
4299 (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2)) { 4300 (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2)) {
4300 TryInlineFloat32x4Constructor(call, recognized_kind); 4301 TryInlineFloat32x4Constructor(call, recognized_kind);
4301 } else if ((recognized_kind == MethodRecognizer::kFloat64x2Constructor) || 4302 } else if ((recognized_kind == MethodRecognizer::kFloat64x2Constructor) ||
4302 (recognized_kind == MethodRecognizer::kFloat64x2Zero) || 4303 (recognized_kind == MethodRecognizer::kFloat64x2Zero) ||
4303 (recognized_kind == MethodRecognizer::kFloat64x2Splat) || 4304 (recognized_kind == MethodRecognizer::kFloat64x2Splat) ||
(...skipping 20 matching lines...) Expand all
4324 // being either doubles or smis. 4325 // being either doubles or smis.
4325 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { 4326 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) {
4326 const ICData& ic_data = *call->ic_data(); 4327 const ICData& ic_data = *call->ic_data();
4327 intptr_t result_cid = kIllegalCid; 4328 intptr_t result_cid = kIllegalCid;
4328 if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, kDoubleCid)) { 4329 if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, kDoubleCid)) {
4329 result_cid = kDoubleCid; 4330 result_cid = kDoubleCid;
4330 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { 4331 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) {
4331 result_cid = kSmiCid; 4332 result_cid = kSmiCid;
4332 } 4333 }
4333 if (result_cid != kIllegalCid) { 4334 if (result_cid != kIllegalCid) {
4334 MathMinMaxInstr* min_max = new(I) MathMinMaxInstr( 4335 MathMinMaxInstr* min_max = new(Z) MathMinMaxInstr(
4335 recognized_kind, 4336 recognized_kind,
4336 new(I) Value(call->ArgumentAt(0)), 4337 new(Z) Value(call->ArgumentAt(0)),
4337 new(I) Value(call->ArgumentAt(1)), 4338 new(Z) Value(call->ArgumentAt(1)),
4338 call->deopt_id(), 4339 call->deopt_id(),
4339 result_cid); 4340 result_cid);
4340 const ICData& unary_checks = 4341 const ICData& unary_checks =
4341 ICData::ZoneHandle(I, ic_data.AsUnaryClassChecks()); 4342 ICData::ZoneHandle(Z, ic_data.AsUnaryClassChecks());
4342 AddCheckClass(min_max->left()->definition(), 4343 AddCheckClass(min_max->left()->definition(),
4343 unary_checks, 4344 unary_checks,
4344 call->deopt_id(), 4345 call->deopt_id(),
4345 call->env(), 4346 call->env(),
4346 call); 4347 call);
4347 AddCheckClass(min_max->right()->definition(), 4348 AddCheckClass(min_max->right()->definition(),
4348 unary_checks, 4349 unary_checks,
4349 call->deopt_id(), 4350 call->deopt_id(),
4350 call->env(), 4351 call->env(),
4351 call); 4352 call);
4352 ReplaceCall(call, min_max); 4353 ReplaceCall(call, min_max);
4353 } 4354 }
4354 } 4355 }
4355 } else if (recognized_kind == MethodRecognizer::kMathDoublePow) { 4356 } else if (recognized_kind == MethodRecognizer::kMathDoublePow) {
4356 // We know that first argument is double, the second is num. 4357 // We know that first argument is double, the second is num.
4357 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble 4358 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble
4358 // instructions contain type checks and conversions to double. 4359 // instructions contain type checks and conversions to double.
4359 ZoneGrowableArray<Value*>* args = 4360 ZoneGrowableArray<Value*>* args =
4360 new(I) ZoneGrowableArray<Value*>(call->ArgumentCount()); 4361 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount());
4361 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { 4362 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
4362 args->Add(new(I) Value(call->ArgumentAt(i))); 4363 args->Add(new(Z) Value(call->ArgumentAt(i)));
4363 } 4364 }
4364 InvokeMathCFunctionInstr* invoke = 4365 InvokeMathCFunctionInstr* invoke =
4365 new(I) InvokeMathCFunctionInstr(args, 4366 new(Z) InvokeMathCFunctionInstr(args,
4366 call->deopt_id(), 4367 call->deopt_id(),
4367 recognized_kind, 4368 recognized_kind,
4368 call->token_pos()); 4369 call->token_pos());
4369 ReplaceCall(call, invoke); 4370 ReplaceCall(call, invoke);
4370 } else if (recognized_kind == MethodRecognizer::kDoubleFromInteger) { 4371 } else if (recognized_kind == MethodRecognizer::kDoubleFromInteger) {
4371 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { 4372 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) {
4372 const ICData& ic_data = *call->ic_data(); 4373 const ICData& ic_data = *call->ic_data();
4373 if (CanUnboxDouble()) { 4374 if (CanUnboxDouble()) {
4374 if (ArgIsAlways(kSmiCid, ic_data, 1)) { 4375 if (ArgIsAlways(kSmiCid, ic_data, 1)) {
4375 Definition* arg = call->ArgumentAt(1); 4376 Definition* arg = call->ArgumentAt(1);
4376 AddCheckSmi(arg, call->deopt_id(), call->env(), call); 4377 AddCheckSmi(arg, call->deopt_id(), call->env(), call);
4377 ReplaceCall(call, 4378 ReplaceCall(call,
4378 new(I) SmiToDoubleInstr(new(I) Value(arg), 4379 new(Z) SmiToDoubleInstr(new(Z) Value(arg),
4379 call->token_pos())); 4380 call->token_pos()));
4380 } else if (ArgIsAlways(kMintCid, ic_data, 1) && 4381 } else if (ArgIsAlways(kMintCid, ic_data, 1) &&
4381 CanConvertUnboxedMintToDouble()) { 4382 CanConvertUnboxedMintToDouble()) {
4382 Definition* arg = call->ArgumentAt(1); 4383 Definition* arg = call->ArgumentAt(1);
4383 ReplaceCall(call, 4384 ReplaceCall(call,
4384 new(I) MintToDoubleInstr(new(I) Value(arg), 4385 new(Z) MintToDoubleInstr(new(Z) Value(arg),
4385 call->deopt_id())); 4386 call->deopt_id()));
4386 } 4387 }
4387 } 4388 }
4388 } 4389 }
4389 } else if (call->function().IsFactory()) { 4390 } else if (call->function().IsFactory()) {
4390 const Class& function_class = 4391 const Class& function_class =
4391 Class::Handle(I, call->function().Owner()); 4392 Class::Handle(Z, call->function().Owner());
4392 if ((function_class.library() == Library::CoreLibrary()) || 4393 if ((function_class.library() == Library::CoreLibrary()) ||
4393 (function_class.library() == Library::TypedDataLibrary())) { 4394 (function_class.library() == Library::TypedDataLibrary())) {
4394 intptr_t cid = FactoryRecognizer::ResultCid(call->function()); 4395 intptr_t cid = FactoryRecognizer::ResultCid(call->function());
4395 switch (cid) { 4396 switch (cid) {
4396 case kArrayCid: { 4397 case kArrayCid: {
4397 Value* type = new(I) Value(call->ArgumentAt(0)); 4398 Value* type = new(Z) Value(call->ArgumentAt(0));
4398 Value* num_elements = new(I) Value(call->ArgumentAt(1)); 4399 Value* num_elements = new(Z) Value(call->ArgumentAt(1));
4399 if (num_elements->BindsToConstant() && 4400 if (num_elements->BindsToConstant() &&
4400 num_elements->BoundConstant().IsSmi()) { 4401 num_elements->BoundConstant().IsSmi()) {
4401 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); 4402 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value();
4402 if (length >= 0 && length <= Array::kMaxElements) { 4403 if (length >= 0 && length <= Array::kMaxElements) {
4403 CreateArrayInstr* create_array = 4404 CreateArrayInstr* create_array =
4404 new(I) CreateArrayInstr( 4405 new(Z) CreateArrayInstr(
4405 call->token_pos(), type, num_elements); 4406 call->token_pos(), type, num_elements);
4406 ReplaceCall(call, create_array); 4407 ReplaceCall(call, create_array);
4407 } 4408 }
4408 } 4409 }
4409 } 4410 }
4410 default: 4411 default:
4411 break; 4412 break;
4412 } 4413 }
4413 } 4414 }
4414 } 4415 }
4415 } 4416 }
4416 4417
4417 4418
4418 void FlowGraphOptimizer::VisitStoreInstanceField( 4419 void FlowGraphOptimizer::VisitStoreInstanceField(
4419 StoreInstanceFieldInstr* instr) { 4420 StoreInstanceFieldInstr* instr) {
4420 if (instr->IsUnboxedStore()) { 4421 if (instr->IsUnboxedStore()) {
4421 ASSERT(instr->is_potential_unboxed_initialization_); 4422 ASSERT(instr->is_potential_unboxed_initialization_);
4422 // Determine if this field should be unboxed based on the usage of getter 4423 // Determine if this field should be unboxed based on the usage of getter
4423 // and setter functions: The heuristic requires that the setter has a 4424 // and setter functions: The heuristic requires that the setter has a
4424 // usage count of at least 1/kGetterSetterRatio of the getter usage count. 4425 // usage count of at least 1/kGetterSetterRatio of the getter usage count.
4425 // This is to avoid unboxing fields where the setter is never or rarely 4426 // This is to avoid unboxing fields where the setter is never or rarely
4426 // executed. 4427 // executed.
4427 const Field& field = Field::ZoneHandle(I, instr->field().raw()); 4428 const Field& field = Field::ZoneHandle(Z, instr->field().raw());
4428 const String& field_name = String::Handle(I, field.name()); 4429 const String& field_name = String::Handle(Z, field.name());
4429 const Class& owner = Class::Handle(I, field.owner()); 4430 const Class& owner = Class::Handle(Z, field.owner());
4430 const Function& getter = 4431 const Function& getter =
4431 Function::Handle(I, owner.LookupGetterFunction(field_name)); 4432 Function::Handle(Z, owner.LookupGetterFunction(field_name));
4432 const Function& setter = 4433 const Function& setter =
4433 Function::Handle(I, owner.LookupSetterFunction(field_name)); 4434 Function::Handle(Z, owner.LookupSetterFunction(field_name));
4434 bool result = !getter.IsNull() 4435 bool result = !getter.IsNull()
4435 && !setter.IsNull() 4436 && !setter.IsNull()
4436 && (setter.usage_counter() > 0) 4437 && (setter.usage_counter() > 0)
4437 && (FLAG_getter_setter_ratio * setter.usage_counter() >= 4438 && (FLAG_getter_setter_ratio * setter.usage_counter() >=
4438 getter.usage_counter()); 4439 getter.usage_counter());
4439 if (!result) { 4440 if (!result) {
4440 if (FLAG_trace_optimization) { 4441 if (FLAG_trace_optimization) {
4441 OS::Print("Disabling unboxing of %s\n", field.ToCString()); 4442 OS::Print("Disabling unboxing of %s\n", field.ToCString());
4442 } 4443 }
4443 field.set_is_unboxing_candidate(false); 4444 field.set_is_unboxing_candidate(false);
4444 field.DeoptimizeDependentCode(); 4445 field.DeoptimizeDependentCode();
4445 } else { 4446 } else {
4446 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); 4447 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field);
4447 } 4448 }
4448 } 4449 }
4449 } 4450 }
4450 4451
4451 4452
4452 void FlowGraphOptimizer::VisitAllocateContext(AllocateContextInstr* instr) { 4453 void FlowGraphOptimizer::VisitAllocateContext(AllocateContextInstr* instr) {
4453 // Replace generic allocation with a sequence of inlined allocation and 4454 // Replace generic allocation with a sequence of inlined allocation and
4454 // explicit initalizing stores. 4455 // explicit initalizing stores.
4455 AllocateUninitializedContextInstr* replacement = 4456 AllocateUninitializedContextInstr* replacement =
4456 new AllocateUninitializedContextInstr(instr->token_pos(), 4457 new AllocateUninitializedContextInstr(instr->token_pos(),
4457 instr->num_context_variables()); 4458 instr->num_context_variables());
4458 instr->ReplaceWith(replacement, current_iterator()); 4459 instr->ReplaceWith(replacement, current_iterator());
4459 4460
4460 StoreInstanceFieldInstr* store = 4461 StoreInstanceFieldInstr* store =
4461 new(I) StoreInstanceFieldInstr(Context::parent_offset(), 4462 new(Z) StoreInstanceFieldInstr(Context::parent_offset(),
4462 new Value(replacement), 4463 new Value(replacement),
4463 new Value(flow_graph_->constant_null()), 4464 new Value(flow_graph_->constant_null()),
4464 kNoStoreBarrier, 4465 kNoStoreBarrier,
4465 instr->token_pos()); 4466 instr->token_pos());
4466 // Storing into uninitialized memory; remember to prevent dead store 4467 // Storing into uninitialized memory; remember to prevent dead store
4467 // elimination and ensure proper GC barrier. 4468 // elimination and ensure proper GC barrier.
4468 store->set_is_object_reference_initialization(true); 4469 store->set_is_object_reference_initialization(true);
4469 flow_graph_->InsertAfter(replacement, store, NULL, FlowGraph::kEffect); 4470 flow_graph_->InsertAfter(replacement, store, NULL, FlowGraph::kEffect);
4470 Definition* cursor = store; 4471 Definition* cursor = store;
4471 for (intptr_t i = 0; i < instr->num_context_variables(); ++i) { 4472 for (intptr_t i = 0; i < instr->num_context_variables(); ++i) {
4472 store = 4473 store =
4473 new(I) StoreInstanceFieldInstr(Context::variable_offset(i), 4474 new(Z) StoreInstanceFieldInstr(Context::variable_offset(i),
4474 new Value(replacement), 4475 new Value(replacement),
4475 new Value(flow_graph_->constant_null()), 4476 new Value(flow_graph_->constant_null()),
4476 kNoStoreBarrier, 4477 kNoStoreBarrier,
4477 instr->token_pos()); 4478 instr->token_pos());
4478 // Storing into uninitialized memory; remember to prevent dead store 4479 // Storing into uninitialized memory; remember to prevent dead store
4479 // elimination and ensure proper GC barrier. 4480 // elimination and ensure proper GC barrier.
4480 store->set_is_object_reference_initialization(true); 4481 store->set_is_object_reference_initialization(true);
4481 flow_graph_->InsertAfter(cursor, store, NULL, FlowGraph::kEffect); 4482 flow_graph_->InsertAfter(cursor, store, NULL, FlowGraph::kEffect);
4482 cursor = store; 4483 cursor = store;
4483 } 4484 }
(...skipping 22 matching lines...) Expand all
4506 ASSERT(instr->HasICData()); 4507 ASSERT(instr->HasICData());
4507 if (unary_ic_data.NumberOfChecks() == 0) { 4508 if (unary_ic_data.NumberOfChecks() == 0) {
4508 // No type feedback collected. 4509 // No type feedback collected.
4509 return false; 4510 return false;
4510 } 4511 }
4511 if (!unary_ic_data.HasOneTarget()) { 4512 if (!unary_ic_data.HasOneTarget()) {
4512 // Polymorphic sites are inlined like normal method calls by conventional 4513 // Polymorphic sites are inlined like normal method calls by conventional
4513 // inlining. 4514 // inlining.
4514 return false; 4515 return false;
4515 } 4516 }
4516 Function& target = Function::Handle(I); 4517 Function& target = Function::Handle(Z);
4517 intptr_t class_id; 4518 intptr_t class_id;
4518 unary_ic_data.GetOneClassCheckAt(0, &class_id, &target); 4519 unary_ic_data.GetOneClassCheckAt(0, &class_id, &target);
4519 if (target.kind() != RawFunction::kImplicitSetter) { 4520 if (target.kind() != RawFunction::kImplicitSetter) {
4520 // Non-implicit setter are inlined like normal method calls. 4521 // Non-implicit setter are inlined like normal method calls.
4521 return false; 4522 return false;
4522 } 4523 }
4523 // Inline implicit instance setter. 4524 // Inline implicit instance setter.
4524 const String& field_name = 4525 const String& field_name =
4525 String::Handle(I, Field::NameFromSetter(instr->function_name())); 4526 String::Handle(Z, Field::NameFromSetter(instr->function_name()));
4526 const Field& field = 4527 const Field& field =
4527 Field::ZoneHandle(I, GetField(class_id, field_name)); 4528 Field::ZoneHandle(Z, GetField(class_id, field_name));
4528 ASSERT(!field.IsNull()); 4529 ASSERT(!field.IsNull());
4529 4530
4530 if (InstanceCallNeedsClassCheck(instr, RawFunction::kImplicitSetter)) { 4531 if (InstanceCallNeedsClassCheck(instr, RawFunction::kImplicitSetter)) {
4531 AddReceiverCheck(instr); 4532 AddReceiverCheck(instr);
4532 } 4533 }
4533 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; 4534 StoreBarrierType needs_store_barrier = kEmitStoreBarrier;
4534 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) { 4535 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) {
4535 InsertBefore(instr, 4536 InsertBefore(instr,
4536 new(I) CheckSmiInstr( 4537 new(Z) CheckSmiInstr(
4537 new(I) Value(instr->ArgumentAt(1)), 4538 new(Z) Value(instr->ArgumentAt(1)),
4538 instr->deopt_id(), 4539 instr->deopt_id(),
4539 instr->token_pos()), 4540 instr->token_pos()),
4540 instr->env(), 4541 instr->env(),
4541 FlowGraph::kEffect); 4542 FlowGraph::kEffect);
4542 needs_store_barrier = kNoStoreBarrier; 4543 needs_store_barrier = kNoStoreBarrier;
4543 } 4544 }
4544 4545
4545 if (field.guarded_cid() != kDynamicCid) { 4546 if (field.guarded_cid() != kDynamicCid) {
4546 InsertBefore(instr, 4547 InsertBefore(instr,
4547 new(I) GuardFieldClassInstr( 4548 new(Z) GuardFieldClassInstr(
4548 new(I) Value(instr->ArgumentAt(1)), 4549 new(Z) Value(instr->ArgumentAt(1)),
4549 field, 4550 field,
4550 instr->deopt_id()), 4551 instr->deopt_id()),
4551 instr->env(), 4552 instr->env(),
4552 FlowGraph::kEffect); 4553 FlowGraph::kEffect);
4553 } 4554 }
4554 4555
4555 if (field.needs_length_check()) { 4556 if (field.needs_length_check()) {
4556 InsertBefore(instr, 4557 InsertBefore(instr,
4557 new(I) GuardFieldLengthInstr( 4558 new(Z) GuardFieldLengthInstr(
4558 new(I) Value(instr->ArgumentAt(1)), 4559 new(Z) Value(instr->ArgumentAt(1)),
4559 field, 4560 field,
4560 instr->deopt_id()), 4561 instr->deopt_id()),
4561 instr->env(), 4562 instr->env(),
4562 FlowGraph::kEffect); 4563 FlowGraph::kEffect);
4563 } 4564 }
4564 4565
4565 // Field guard was detached. 4566 // Field guard was detached.
4566 StoreInstanceFieldInstr* store = new(I) StoreInstanceFieldInstr( 4567 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr(
4567 field, 4568 field,
4568 new(I) Value(instr->ArgumentAt(0)), 4569 new(Z) Value(instr->ArgumentAt(0)),
4569 new(I) Value(instr->ArgumentAt(1)), 4570 new(Z) Value(instr->ArgumentAt(1)),
4570 needs_store_barrier, 4571 needs_store_barrier,
4571 instr->token_pos()); 4572 instr->token_pos());
4572 4573
4573 if (store->IsUnboxedStore()) { 4574 if (store->IsUnboxedStore()) {
4574 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); 4575 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field);
4575 } 4576 }
4576 4577
4577 // Discard the environment from the original instruction because the store 4578 // Discard the environment from the original instruction because the store
4578 // can't deoptimize. 4579 // can't deoptimize.
4579 instr->RemoveEnvironment(); 4580 instr->RemoveEnvironment();
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
4655 4656
4656 // Step 3. For each candidate transitively collect all other BinarySmiOpInstr 4657 // Step 3. For each candidate transitively collect all other BinarySmiOpInstr
4657 // and PhiInstr that depend on it and that it depends on and count amount of 4658 // and PhiInstr that depend on it and that it depends on and count amount of
4658 // untagging operations that we save in assumption that this whole graph of 4659 // untagging operations that we save in assumption that this whole graph of
4659 // values is using kUnboxedInt32 representation instead of kTagged. 4660 // values is using kUnboxedInt32 representation instead of kTagged.
4660 // Convert those graphs that have positive gain to kUnboxedInt32. 4661 // Convert those graphs that have positive gain to kUnboxedInt32.
4661 4662
4662 // BitVector containing SSA indexes of all processed definitions. Used to skip 4663 // BitVector containing SSA indexes of all processed definitions. Used to skip
4663 // those candidates that belong to dependency graph of another candidate. 4664 // those candidates that belong to dependency graph of another candidate.
4664 BitVector* processed = 4665 BitVector* processed =
4665 new(I) BitVector(I, flow_graph_->current_ssa_temp_index()); 4666 new(Z) BitVector(Z, flow_graph_->current_ssa_temp_index());
4666 4667
4667 // Worklist used to collect dependency graph. 4668 // Worklist used to collect dependency graph.
4668 DefinitionWorklist worklist(flow_graph_, candidates.length()); 4669 DefinitionWorklist worklist(flow_graph_, candidates.length());
4669 for (intptr_t i = 0; i < candidates.length(); i++) { 4670 for (intptr_t i = 0; i < candidates.length(); i++) {
4670 BinarySmiOpInstr* op = candidates[i]; 4671 BinarySmiOpInstr* op = candidates[i];
4671 if (op->WasEliminated() || processed->Contains(op->ssa_temp_index())) { 4672 if (op->WasEliminated() || processed->Contains(op->ssa_temp_index())) {
4672 continue; 4673 continue;
4673 } 4674 }
4674 4675
4675 if (FLAG_trace_smi_widening) { 4676 if (FLAG_trace_smi_widening) {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
4779 4780
4780 if (gain > 0) { 4781 if (gain > 0) {
4781 // We have positive gain from widening. Convert all BinarySmiOpInstr into 4782 // We have positive gain from widening. Convert all BinarySmiOpInstr into
4782 // BinaryInt32OpInstr and set representation of all phis to kUnboxedInt32. 4783 // BinaryInt32OpInstr and set representation of all phis to kUnboxedInt32.
4783 for (intptr_t j = 0; j < worklist.definitions().length(); j++) { 4784 for (intptr_t j = 0; j < worklist.definitions().length(); j++) {
4784 Definition* defn = worklist.definitions()[j]; 4785 Definition* defn = worklist.definitions()[j];
4785 ASSERT(defn->IsPhi() || defn->IsBinarySmiOp()); 4786 ASSERT(defn->IsPhi() || defn->IsBinarySmiOp());
4786 4787
4787 if (defn->IsBinarySmiOp()) { 4788 if (defn->IsBinarySmiOp()) {
4788 BinarySmiOpInstr* smi_op = defn->AsBinarySmiOp(); 4789 BinarySmiOpInstr* smi_op = defn->AsBinarySmiOp();
4789 BinaryInt32OpInstr* int32_op = new(I) BinaryInt32OpInstr( 4790 BinaryInt32OpInstr* int32_op = new(Z) BinaryInt32OpInstr(
4790 smi_op->op_kind(), 4791 smi_op->op_kind(),
4791 smi_op->left()->CopyWithType(), 4792 smi_op->left()->CopyWithType(),
4792 smi_op->right()->CopyWithType(), 4793 smi_op->right()->CopyWithType(),
4793 smi_op->DeoptimizationTarget()); 4794 smi_op->DeoptimizationTarget());
4794 4795
4795 smi_op->ReplaceWith(int32_op, NULL); 4796 smi_op->ReplaceWith(int32_op, NULL);
4796 } else if (defn->IsPhi()) { 4797 } else if (defn->IsPhi()) {
4797 defn->AsPhi()->set_representation(kUnboxedInt32); 4798 defn->AsPhi()->set_representation(kUnboxedInt32);
4798 ASSERT(defn->Type()->IsInt()); 4799 ASSERT(defn->Type()->IsInt());
4799 } 4800 }
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
5205 *is_store = true; 5206 *is_store = true;
5206 break; 5207 break;
5207 } 5208 }
5208 5209
5209 default: 5210 default:
5210 break; 5211 break;
5211 } 5212 }
5212 } 5213 }
5213 5214
5214 // Create object representing *[*] alias. 5215 // Create object representing *[*] alias.
5215 static Place* CreateAnyInstanceAnyIndexAlias(Isolate* isolate, 5216 static Place* CreateAnyInstanceAnyIndexAlias(Zone* zone,
5216 intptr_t id) { 5217 intptr_t id) {
5217 return Wrap(isolate, Place(kIndexed, NULL, 0), id); 5218 return Wrap(zone, Place(kIndexed, NULL, 0), id);
5218 } 5219 }
5219 5220
5220 // Return least generic alias for this place. Given that aliases are 5221 // Return least generic alias for this place. Given that aliases are
5221 // essentially sets of places we define least generic alias as a smallest 5222 // essentially sets of places we define least generic alias as a smallest
5222 // alias that contains this place. 5223 // alias that contains this place.
5223 // 5224 //
5224 // We obtain such alias by a simple transformation: 5225 // We obtain such alias by a simple transformation:
5225 // 5226 //
5226 // - for places that depend on an instance X.f, X.@offs, X[i], X[C] 5227 // - for places that depend on an instance X.f, X.@offs, X[i], X[C]
5227 // we drop X if X is not an allocation because in this case X does not 5228 // we drop X if X is not an allocation because in this case X does not
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
5359 } 5360 }
5360 5361
5361 bool Equals(const Place* other) const { 5362 bool Equals(const Place* other) const {
5362 return (kind_ == other->kind_) && 5363 return (kind_ == other->kind_) &&
5363 (representation_ == other->representation_) && 5364 (representation_ == other->representation_) &&
5364 (instance_ == other->instance_) && 5365 (instance_ == other->instance_) &&
5365 SameField(other); 5366 SameField(other);
5366 } 5367 }
5367 5368
5368 // Create a zone allocated copy of this place and assign given id to it. 5369 // Create a zone allocated copy of this place and assign given id to it.
5369 static Place* Wrap(Isolate* isolate, const Place& place, intptr_t id); 5370 static Place* Wrap(Zone* zone, const Place& place, intptr_t id);
5370 5371
5371 static bool IsAllocation(Definition* defn) { 5372 static bool IsAllocation(Definition* defn) {
5372 return (defn != NULL) && 5373 return (defn != NULL) &&
5373 (defn->IsAllocateObject() || 5374 (defn->IsAllocateObject() ||
5374 defn->IsCreateArray() || 5375 defn->IsCreateArray() ||
5375 defn->IsAllocateUninitializedContext() || 5376 defn->IsAllocateUninitializedContext() ||
5376 (defn->IsStaticCall() && 5377 (defn->IsStaticCall() &&
5377 defn->AsStaticCall()->IsRecognizedFactory())); 5378 defn->AsStaticCall()->IsRecognizedFactory()));
5378 } 5379 }
5379 5380
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
5426 public: 5427 public:
5427 explicit ZonePlace(const Place& place) : place_(place) { } 5428 explicit ZonePlace(const Place& place) : place_(place) { }
5428 5429
5429 Place* place() { return &place_; } 5430 Place* place() { return &place_; }
5430 5431
5431 private: 5432 private:
5432 Place place_; 5433 Place place_;
5433 }; 5434 };
5434 5435
5435 5436
5436 Place* Place::Wrap(Isolate* isolate, const Place& place, intptr_t id) { 5437 Place* Place::Wrap(Zone* zone, const Place& place, intptr_t id) {
5437 Place* wrapped = (new(isolate) ZonePlace(place))->place(); 5438 Place* wrapped = (new(zone) ZonePlace(place))->place();
5438 wrapped->id_ = id; 5439 wrapped->id_ = id;
5439 return wrapped; 5440 return wrapped;
5440 } 5441 }
5441 5442
5442 5443
5443 // Correspondence between places connected through outgoing phi moves on the 5444 // Correspondence between places connected through outgoing phi moves on the
5444 // edge that targets join. 5445 // edge that targets join.
5445 class PhiPlaceMoves : public ZoneAllocated { 5446 class PhiPlaceMoves : public ZoneAllocated {
5446 public: 5447 public:
5447 // Record a move from the place with id |from| to the place with id |to| at 5448 // Record a move from the place with id |from| to the place with id |to| at
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
5483 private: 5484 private:
5484 GrowableArray<ZoneGrowableArray<Move>* > moves_; 5485 GrowableArray<ZoneGrowableArray<Move>* > moves_;
5485 }; 5486 };
5486 5487
5487 5488
5488 // A map from aliases to a set of places sharing the alias. Additionally 5489 // A map from aliases to a set of places sharing the alias. Additionally
5489 // carries a set of places that can be aliased by side-effects, essentially 5490 // carries a set of places that can be aliased by side-effects, essentially
5490 // those that are affected by calls. 5491 // those that are affected by calls.
5491 class AliasedSet : public ZoneAllocated { 5492 class AliasedSet : public ZoneAllocated {
5492 public: 5493 public:
5493 AliasedSet(Isolate* isolate, 5494 AliasedSet(Zone* zone,
5494 DirectChainedHashMap<PointerKeyValueTrait<Place> >* places_map, 5495 DirectChainedHashMap<PointerKeyValueTrait<Place> >* places_map,
5495 ZoneGrowableArray<Place*>* places, 5496 ZoneGrowableArray<Place*>* places,
5496 PhiPlaceMoves* phi_moves) 5497 PhiPlaceMoves* phi_moves)
5497 : isolate_(isolate), 5498 : zone_(zone),
5498 places_map_(places_map), 5499 places_map_(places_map),
5499 places_(*places), 5500 places_(*places),
5500 phi_moves_(phi_moves), 5501 phi_moves_(phi_moves),
5501 aliases_(5), 5502 aliases_(5),
5502 aliases_map_(), 5503 aliases_map_(),
5503 representatives_(), 5504 representatives_(),
5504 killed_(), 5505 killed_(),
5505 aliased_by_effects_(new(isolate) BitVector(isolate, places->length())) { 5506 aliased_by_effects_(new(zone) BitVector(zone, places->length())) {
5506 InsertAlias(Place::CreateAnyInstanceAnyIndexAlias(isolate_, 5507 InsertAlias(Place::CreateAnyInstanceAnyIndexAlias(zone_,
5507 kAnyInstanceAnyIndexAlias)); 5508 kAnyInstanceAnyIndexAlias));
5508 for (intptr_t i = 0; i < places_.length(); i++) { 5509 for (intptr_t i = 0; i < places_.length(); i++) {
5509 AddRepresentative(places_[i]); 5510 AddRepresentative(places_[i]);
5510 } 5511 }
5511 ComputeKillSets(); 5512 ComputeKillSets();
5512 } 5513 }
5513 5514
5514 intptr_t LookupAliasId(const Place& alias) { 5515 intptr_t LookupAliasId(const Place& alias) {
5515 const Place* result = aliases_map_.Lookup(&alias); 5516 const Place* result = aliases_map_.Lookup(&alias);
5516 return (result != NULL) ? result->id() : static_cast<intptr_t>(kNoAlias); 5517 return (result != NULL) ? result->id() : static_cast<intptr_t>(kNoAlias);
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
5644 } 5645 }
5645 5646
5646 void InsertAlias(const Place* alias) { 5647 void InsertAlias(const Place* alias) {
5647 aliases_map_.Insert(alias); 5648 aliases_map_.Insert(alias);
5648 aliases_.Add(alias); 5649 aliases_.Add(alias);
5649 } 5650 }
5650 5651
5651 const Place* CanonicalizeAlias(const Place& alias) { 5652 const Place* CanonicalizeAlias(const Place& alias) {
5652 const Place* canonical = aliases_map_.Lookup(&alias); 5653 const Place* canonical = aliases_map_.Lookup(&alias);
5653 if (canonical == NULL) { 5654 if (canonical == NULL) {
5654 canonical = Place::Wrap(isolate_, 5655 canonical = Place::Wrap(zone_,
5655 alias, 5656 alias,
5656 kAnyInstanceAnyIndexAlias + aliases_.length()); 5657 kAnyInstanceAnyIndexAlias + aliases_.length());
5657 InsertAlias(canonical); 5658 InsertAlias(canonical);
5658 } 5659 }
5659 return canonical; 5660 return canonical;
5660 } 5661 }
5661 5662
5662 BitVector* GetRepresentativesSet(intptr_t alias) { 5663 BitVector* GetRepresentativesSet(intptr_t alias) {
5663 return (alias < representatives_.length()) ? representatives_[alias] : NULL; 5664 return (alias < representatives_.length()) ? representatives_[alias] : NULL;
5664 } 5665 }
5665 5666
5666 BitVector* EnsureSet(GrowableArray<BitVector*>* sets, 5667 BitVector* EnsureSet(GrowableArray<BitVector*>* sets,
5667 intptr_t alias) { 5668 intptr_t alias) {
5668 while (sets->length() <= alias) { 5669 while (sets->length() <= alias) {
5669 sets->Add(NULL); 5670 sets->Add(NULL);
5670 } 5671 }
5671 5672
5672 BitVector* set = (*sets)[alias]; 5673 BitVector* set = (*sets)[alias];
5673 if (set == NULL) { 5674 if (set == NULL) {
5674 (*sets)[alias] = set = new(isolate_) BitVector(isolate_, max_place_id()); 5675 (*sets)[alias] = set = new(zone_) BitVector(zone_, max_place_id());
5675 } 5676 }
5676 return set; 5677 return set;
5677 } 5678 }
5678 5679
5679 void AddAllRepresentatives(const Place* to, intptr_t from) { 5680 void AddAllRepresentatives(const Place* to, intptr_t from) {
5680 AddAllRepresentatives(to->id(), from); 5681 AddAllRepresentatives(to->id(), from);
5681 } 5682 }
5682 5683
5683 void AddAllRepresentatives(intptr_t to, intptr_t from) { 5684 void AddAllRepresentatives(intptr_t to, intptr_t from) {
5684 BitVector* from_set = GetRepresentativesSet(from); 5685 BitVector* from_set = GetRepresentativesSet(from);
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
5897 } 5898 }
5898 5899
5899 // If the allocation site is marked as aliased conservatively mark 5900 // If the allocation site is marked as aliased conservatively mark
5900 // any values stored into the object aliased too. 5901 // any values stored into the object aliased too.
5901 if (defn->Identity().IsAliased()) { 5902 if (defn->Identity().IsAliased()) {
5902 MarkStoredValuesEscaping(defn); 5903 MarkStoredValuesEscaping(defn);
5903 } 5904 }
5904 } 5905 }
5905 } 5906 }
5906 5907
5907 Isolate* isolate_; 5908 Zone* zone_;
5908 5909
5909 DirectChainedHashMap<PointerKeyValueTrait<Place> >* places_map_; 5910 DirectChainedHashMap<PointerKeyValueTrait<Place> >* places_map_;
5910 5911
5911 const ZoneGrowableArray<Place*>& places_; 5912 const ZoneGrowableArray<Place*>& places_;
5912 5913
5913 const PhiPlaceMoves* phi_moves_; 5914 const PhiPlaceMoves* phi_moves_;
5914 5915
5915 // A list of all seen aliases and a map that allows looking up canonical 5916 // A list of all seen aliases and a map that allows looking up canonical
5916 // alias object. 5917 // alias object.
5917 GrowableArray<const Place*> aliases_; 5918 GrowableArray<const Place*> aliases_;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
5970 } 5971 }
5971 5972
5972 5973
5973 // For each place that depends on a phi ensure that equivalent places 5974 // For each place that depends on a phi ensure that equivalent places
5974 // corresponding to phi input are numbered and record outgoing phi moves 5975 // corresponding to phi input are numbered and record outgoing phi moves
5975 // for each block which establish correspondence between phi dependent place 5976 // for each block which establish correspondence between phi dependent place
5976 // and phi input's place that is flowing in. 5977 // and phi input's place that is flowing in.
5977 static PhiPlaceMoves* ComputePhiMoves( 5978 static PhiPlaceMoves* ComputePhiMoves(
5978 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map, 5979 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map,
5979 ZoneGrowableArray<Place*>* places) { 5980 ZoneGrowableArray<Place*>* places) {
5980 Isolate* isolate = Isolate::Current(); 5981 Thread* thread = Thread::Current();
5981 PhiPlaceMoves* phi_moves = new(isolate) PhiPlaceMoves(); 5982 Isolate* isolate = thread->isolate();
5983 Zone* zone = thread->zone();
5984 PhiPlaceMoves* phi_moves = new(zone) PhiPlaceMoves();
5982 5985
5983 for (intptr_t i = 0; i < places->length(); i++) { 5986 for (intptr_t i = 0; i < places->length(); i++) {
5984 Place* place = (*places)[i]; 5987 Place* place = (*places)[i];
5985 5988
5986 if (IsPhiDependentPlace(place)) { 5989 if (IsPhiDependentPlace(place)) {
5987 PhiInstr* phi = place->instance()->AsPhi(); 5990 PhiInstr* phi = place->instance()->AsPhi();
5988 BlockEntryInstr* block = phi->GetBlock(); 5991 BlockEntryInstr* block = phi->GetBlock();
5989 5992
5990 if (FLAG_trace_optimization) { 5993 if (FLAG_trace_optimization) {
5991 OS::Print("phi dependent place %s\n", place->ToCString()); 5994 OS::Print("phi dependent place %s\n", place->ToCString());
5992 } 5995 }
5993 5996
5994 Place input_place(*place); 5997 Place input_place(*place);
5995 for (intptr_t j = 0; j < phi->InputCount(); j++) { 5998 for (intptr_t j = 0; j < phi->InputCount(); j++) {
5996 input_place.set_instance(phi->InputAt(j)->definition()); 5999 input_place.set_instance(phi->InputAt(j)->definition());
5997 6000
5998 Place* result = map->Lookup(&input_place); 6001 Place* result = map->Lookup(&input_place);
5999 if (result == NULL) { 6002 if (result == NULL) {
6000 result = Place::Wrap(isolate, input_place, places->length()); 6003 result = Place::Wrap(zone, input_place, places->length());
6001 map->Insert(result); 6004 map->Insert(result);
6002 places->Add(result); 6005 places->Add(result);
6003 if (FLAG_trace_optimization) { 6006 if (FLAG_trace_optimization) {
6004 OS::Print(" adding place %s as %" Pd "\n", 6007 OS::Print(" adding place %s as %" Pd "\n",
6005 result->ToCString(), 6008 result->ToCString(),
6006 result->id()); 6009 result->id());
6007 } 6010 }
6008 } 6011 }
6009 phi_moves->CreateOutgoingMove(isolate, 6012 phi_moves->CreateOutgoingMove(isolate,
6010 block->PredecessorAt(j), 6013 block->PredecessorAt(j),
(...skipping 12 matching lines...) Expand all
6023 kOptimizeStores 6026 kOptimizeStores
6024 }; 6027 };
6025 6028
6026 6029
6027 static AliasedSet* NumberPlaces( 6030 static AliasedSet* NumberPlaces(
6028 FlowGraph* graph, 6031 FlowGraph* graph,
6029 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map, 6032 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map,
6030 CSEMode mode) { 6033 CSEMode mode) {
6031 // Loads representing different expression ids will be collected and 6034 // Loads representing different expression ids will be collected and
6032 // used to build per offset kill sets. 6035 // used to build per offset kill sets.
6033 Isolate* isolate = graph->isolate(); 6036 Zone* zone = graph->zone();
6034 ZoneGrowableArray<Place*>* places = 6037 ZoneGrowableArray<Place*>* places =
6035 new(isolate) ZoneGrowableArray<Place*>(10); 6038 new(zone) ZoneGrowableArray<Place*>(10);
6036 6039
6037 bool has_loads = false; 6040 bool has_loads = false;
6038 bool has_stores = false; 6041 bool has_stores = false;
6039 for (BlockIterator it = graph->reverse_postorder_iterator(); 6042 for (BlockIterator it = graph->reverse_postorder_iterator();
6040 !it.Done(); 6043 !it.Done();
6041 it.Advance()) { 6044 it.Advance()) {
6042 BlockEntryInstr* block = it.Current(); 6045 BlockEntryInstr* block = it.Current();
6043 6046
6044 for (ForwardInstructionIterator instr_it(block); 6047 for (ForwardInstructionIterator instr_it(block);
6045 !instr_it.Done(); 6048 !instr_it.Done();
6046 instr_it.Advance()) { 6049 instr_it.Advance()) {
6047 Instruction* instr = instr_it.Current(); 6050 Instruction* instr = instr_it.Current();
6048 Place place(instr, &has_loads, &has_stores); 6051 Place place(instr, &has_loads, &has_stores);
6049 if (place.kind() == Place::kNone) { 6052 if (place.kind() == Place::kNone) {
6050 continue; 6053 continue;
6051 } 6054 }
6052 6055
6053 Place* result = map->Lookup(&place); 6056 Place* result = map->Lookup(&place);
6054 if (result == NULL) { 6057 if (result == NULL) {
6055 result = Place::Wrap(isolate, place, places->length()); 6058 result = Place::Wrap(zone, place, places->length());
6056 map->Insert(result); 6059 map->Insert(result);
6057 places->Add(result); 6060 places->Add(result);
6058 6061
6059 if (FLAG_trace_optimization) { 6062 if (FLAG_trace_optimization) {
6060 OS::Print("numbering %s as %" Pd "\n", 6063 OS::Print("numbering %s as %" Pd "\n",
6061 result->ToCString(), 6064 result->ToCString(),
6062 result->id()); 6065 result->id());
6063 } 6066 }
6064 } 6067 }
6065 6068
6066 instr->set_place_id(result->id()); 6069 instr->set_place_id(result->id());
6067 } 6070 }
6068 } 6071 }
6069 6072
6070 if ((mode == kOptimizeLoads) && !has_loads) { 6073 if ((mode == kOptimizeLoads) && !has_loads) {
6071 return NULL; 6074 return NULL;
6072 } 6075 }
6073 if ((mode == kOptimizeStores) && !has_stores) { 6076 if ((mode == kOptimizeStores) && !has_stores) {
6074 return NULL; 6077 return NULL;
6075 } 6078 }
6076 6079
6077 PhiPlaceMoves* phi_moves = ComputePhiMoves(map, places); 6080 PhiPlaceMoves* phi_moves = ComputePhiMoves(map, places);
6078 6081
6079 // Build aliasing sets mapping aliases to loads. 6082 // Build aliasing sets mapping aliases to loads.
6080 return new(isolate) AliasedSet(isolate, map, places, phi_moves); 6083 return new(zone) AliasedSet(zone, map, places, phi_moves);
6081 } 6084 }
6082 6085
6083 6086
6084 class LoadOptimizer : public ValueObject { 6087 class LoadOptimizer : public ValueObject {
6085 public: 6088 public:
6086 LoadOptimizer(FlowGraph* graph, AliasedSet* aliased_set) 6089 LoadOptimizer(FlowGraph* graph, AliasedSet* aliased_set)
6087 : graph_(graph), 6090 : graph_(graph),
6088 aliased_set_(aliased_set), 6091 aliased_set_(aliased_set),
6089 in_(graph_->preorder().length()), 6092 in_(graph_->preorder().length()),
6090 out_(graph_->preorder().length()), 6093 out_(graph_->preorder().length()),
6091 gen_(graph_->preorder().length()), 6094 gen_(graph_->preorder().length()),
6092 kill_(graph_->preorder().length()), 6095 kill_(graph_->preorder().length()),
6093 exposed_values_(graph_->preorder().length()), 6096 exposed_values_(graph_->preorder().length()),
6094 out_values_(graph_->preorder().length()), 6097 out_values_(graph_->preorder().length()),
6095 phis_(5), 6098 phis_(5),
6096 worklist_(5), 6099 worklist_(5),
6097 congruency_worklist_(6), 6100 congruency_worklist_(6),
6098 in_worklist_(NULL), 6101 in_worklist_(NULL),
6099 forwarded_(false) { 6102 forwarded_(false) {
6100 const intptr_t num_blocks = graph_->preorder().length(); 6103 const intptr_t num_blocks = graph_->preorder().length();
6101 for (intptr_t i = 0; i < num_blocks; i++) { 6104 for (intptr_t i = 0; i < num_blocks; i++) {
6102 out_.Add(NULL); 6105 out_.Add(NULL);
6103 gen_.Add(new(I) BitVector(I, aliased_set_->max_place_id())); 6106 gen_.Add(new(Z) BitVector(Z, aliased_set_->max_place_id()));
6104 kill_.Add(new(I) BitVector(I, aliased_set_->max_place_id())); 6107 kill_.Add(new(Z) BitVector(Z, aliased_set_->max_place_id()));
6105 in_.Add(new(I) BitVector(I, aliased_set_->max_place_id())); 6108 in_.Add(new(Z) BitVector(Z, aliased_set_->max_place_id()));
6106 6109
6107 exposed_values_.Add(NULL); 6110 exposed_values_.Add(NULL);
6108 out_values_.Add(NULL); 6111 out_values_.Add(NULL);
6109 } 6112 }
6110 } 6113 }
6111 6114
6112 ~LoadOptimizer() { 6115 ~LoadOptimizer() {
6113 aliased_set_->RollbackAliasedIdentites(); 6116 aliased_set_->RollbackAliasedIdentites();
6114 } 6117 }
6115 6118
6116 Isolate* isolate() const { return graph_->isolate(); } 6119 Isolate* isolate() const { return graph_->isolate(); }
6120 Zone* zone() const { return graph_->zone(); }
6117 6121
6118 static bool OptimizeGraph(FlowGraph* graph) { 6122 static bool OptimizeGraph(FlowGraph* graph) {
6119 ASSERT(FLAG_load_cse); 6123 ASSERT(FLAG_load_cse);
6120 if (FLAG_trace_load_optimization) { 6124 if (FLAG_trace_load_optimization) {
6121 FlowGraphPrinter::PrintGraph("Before LoadOptimizer", graph); 6125 FlowGraphPrinter::PrintGraph("Before LoadOptimizer", graph);
6122 } 6126 }
6123 6127
6124 DirectChainedHashMap<PointerKeyValueTrait<Place> > map; 6128 DirectChainedHashMap<PointerKeyValueTrait<Place> > map;
6125 AliasedSet* aliased_set = NumberPlaces(graph, &map, kOptimizeLoads); 6129 AliasedSet* aliased_set = NumberPlaces(graph, &map, kOptimizeLoads);
6126 if ((aliased_set != NULL) && !aliased_set->IsEmpty()) { 6130 if ((aliased_set != NULL) && !aliased_set->IsEmpty()) {
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
6333 defn->ReplaceUsesWith(replacement); 6337 defn->ReplaceUsesWith(replacement);
6334 instr_it.RemoveCurrentFromGraph(); 6338 instr_it.RemoveCurrentFromGraph();
6335 forwarded_ = true; 6339 forwarded_ = true;
6336 continue; 6340 continue;
6337 } else if (!kill->Contains(place_id)) { 6341 } else if (!kill->Contains(place_id)) {
6338 // This is an exposed load: it is the first representative of a 6342 // This is an exposed load: it is the first representative of a
6339 // given expression id and it is not killed on the path from 6343 // given expression id and it is not killed on the path from
6340 // the block entry. 6344 // the block entry.
6341 if (exposed_values == NULL) { 6345 if (exposed_values == NULL) {
6342 static const intptr_t kMaxExposedValuesInitialSize = 5; 6346 static const intptr_t kMaxExposedValuesInitialSize = 5;
6343 exposed_values = new(I) ZoneGrowableArray<Definition*>( 6347 exposed_values = new(Z) ZoneGrowableArray<Definition*>(
6344 Utils::Minimum(kMaxExposedValuesInitialSize, 6348 Utils::Minimum(kMaxExposedValuesInitialSize,
6345 aliased_set_->max_place_id())); 6349 aliased_set_->max_place_id()));
6346 } 6350 }
6347 6351
6348 exposed_values->Add(defn); 6352 exposed_values->Add(defn);
6349 } 6353 }
6350 6354
6351 gen->Add(place_id); 6355 gen->Add(place_id);
6352 6356
6353 if (out_values == NULL) out_values = CreateBlockOutValues(); 6357 if (out_values == NULL) out_values = CreateBlockOutValues();
(...skipping 27 matching lines...) Expand all
6381 6385
6382 out->Remove(to); 6386 out->Remove(to);
6383 } 6387 }
6384 6388
6385 out->AddAll(forwarded_loads); 6389 out->AddAll(forwarded_loads);
6386 } 6390 }
6387 6391
6388 // Compute OUT sets by propagating them iteratively until fix point 6392 // Compute OUT sets by propagating them iteratively until fix point
6389 // is reached. 6393 // is reached.
6390 void ComputeOutSets() { 6394 void ComputeOutSets() {
6391 BitVector* temp = new(I) BitVector(I, aliased_set_->max_place_id()); 6395 BitVector* temp = new(Z) BitVector(Z, aliased_set_->max_place_id());
6392 BitVector* forwarded_loads = 6396 BitVector* forwarded_loads =
6393 new(I) BitVector(I, aliased_set_->max_place_id()); 6397 new(Z) BitVector(Z, aliased_set_->max_place_id());
6394 BitVector* temp_out = new(I) BitVector(I, aliased_set_->max_place_id()); 6398 BitVector* temp_out = new(Z) BitVector(Z, aliased_set_->max_place_id());
6395 6399
6396 bool changed = true; 6400 bool changed = true;
6397 while (changed) { 6401 while (changed) {
6398 changed = false; 6402 changed = false;
6399 6403
6400 for (BlockIterator block_it = graph_->reverse_postorder_iterator(); 6404 for (BlockIterator block_it = graph_->reverse_postorder_iterator();
6401 !block_it.Done(); 6405 !block_it.Done();
6402 block_it.Advance()) { 6406 block_it.Advance()) {
6403 BlockEntryInstr* block = block_it.Current(); 6407 BlockEntryInstr* block = block_it.Current();
6404 6408
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
6436 if (!temp->Equals(*block_in) || (block_out == NULL)) { 6440 if (!temp->Equals(*block_in) || (block_out == NULL)) {
6437 // If IN set has changed propagate the change to OUT set. 6441 // If IN set has changed propagate the change to OUT set.
6438 block_in->CopyFrom(temp); 6442 block_in->CopyFrom(temp);
6439 6443
6440 temp->RemoveAll(block_kill); 6444 temp->RemoveAll(block_kill);
6441 temp->AddAll(block_gen); 6445 temp->AddAll(block_gen);
6442 6446
6443 if ((block_out == NULL) || !block_out->Equals(*temp)) { 6447 if ((block_out == NULL) || !block_out->Equals(*temp)) {
6444 if (block_out == NULL) { 6448 if (block_out == NULL) {
6445 block_out = out_[preorder_number] = 6449 block_out = out_[preorder_number] =
6446 new(I) BitVector(I, aliased_set_->max_place_id()); 6450 new(Z) BitVector(Z, aliased_set_->max_place_id());
6447 } 6451 }
6448 block_out->CopyFrom(temp); 6452 block_out->CopyFrom(temp);
6449 changed = true; 6453 changed = true;
6450 } 6454 }
6451 } 6455 }
6452 } 6456 }
6453 } 6457 }
6454 } 6458 }
6455 6459
6456 // Compute out_values mappings by propagating them in reverse postorder once 6460 // Compute out_values mappings by propagating them in reverse postorder once
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
6489 out_values_[preorder_number] = block_out_values = 6493 out_values_[preorder_number] = block_out_values =
6490 CreateBlockOutValues(); 6494 CreateBlockOutValues();
6491 } 6495 }
6492 6496
6493 if ((*block_out_values)[place_id] == NULL) { 6497 if ((*block_out_values)[place_id] == NULL) {
6494 ASSERT(block->PredecessorCount() > 0); 6498 ASSERT(block->PredecessorCount() > 0);
6495 Definition* in_value = can_merge_eagerly ? 6499 Definition* in_value = can_merge_eagerly ?
6496 MergeIncomingValues(block, place_id) : NULL; 6500 MergeIncomingValues(block, place_id) : NULL;
6497 if ((in_value == NULL) && 6501 if ((in_value == NULL) &&
6498 (in_[preorder_number]->Contains(place_id))) { 6502 (in_[preorder_number]->Contains(place_id))) {
6499 PhiInstr* phi = new(I) PhiInstr(block->AsJoinEntry(), 6503 PhiInstr* phi = new(Z) PhiInstr(block->AsJoinEntry(),
6500 block->PredecessorCount()); 6504 block->PredecessorCount());
6501 phi->set_place_id(place_id); 6505 phi->set_place_id(place_id);
6502 pending_phis.Add(phi); 6506 pending_phis.Add(phi);
6503 in_value = phi; 6507 in_value = phi;
6504 } 6508 }
6505 (*block_out_values)[place_id] = in_value; 6509 (*block_out_values)[place_id] = in_value;
6506 } 6510 }
6507 } 6511 }
6508 6512
6509 // If the block has outgoing phi moves perform them. Use temporary list 6513 // If the block has outgoing phi moves perform them. Use temporary list
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
6563 } 6567 }
6564 } 6568 }
6565 return true; 6569 return true;
6566 } 6570 }
6567 6571
6568 void MarkLoopInvariantLoads() { 6572 void MarkLoopInvariantLoads() {
6569 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = 6573 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers =
6570 graph_->LoopHeaders(); 6574 graph_->LoopHeaders();
6571 6575
6572 ZoneGrowableArray<BitVector*>* invariant_loads = 6576 ZoneGrowableArray<BitVector*>* invariant_loads =
6573 new(I) ZoneGrowableArray<BitVector*>(loop_headers.length()); 6577 new(Z) ZoneGrowableArray<BitVector*>(loop_headers.length());
6574 6578
6575 for (intptr_t i = 0; i < loop_headers.length(); i++) { 6579 for (intptr_t i = 0; i < loop_headers.length(); i++) {
6576 BlockEntryInstr* header = loop_headers[i]; 6580 BlockEntryInstr* header = loop_headers[i];
6577 BlockEntryInstr* pre_header = header->ImmediateDominator(); 6581 BlockEntryInstr* pre_header = header->ImmediateDominator();
6578 if (pre_header == NULL) { 6582 if (pre_header == NULL) {
6579 invariant_loads->Add(NULL); 6583 invariant_loads->Add(NULL);
6580 continue; 6584 continue;
6581 } 6585 }
6582 6586
6583 BitVector* loop_gen = new(I) BitVector(I, aliased_set_->max_place_id()); 6587 BitVector* loop_gen = new(Z) BitVector(Z, aliased_set_->max_place_id());
6584 for (BitVector::Iterator loop_it(header->loop_info()); 6588 for (BitVector::Iterator loop_it(header->loop_info());
6585 !loop_it.Done(); 6589 !loop_it.Done();
6586 loop_it.Advance()) { 6590 loop_it.Advance()) {
6587 const intptr_t preorder_number = loop_it.Current(); 6591 const intptr_t preorder_number = loop_it.Current();
6588 loop_gen->AddAll(gen_[preorder_number]); 6592 loop_gen->AddAll(gen_[preorder_number]);
6589 } 6593 }
6590 6594
6591 for (BitVector::Iterator loop_it(header->loop_info()); 6595 for (BitVector::Iterator loop_it(header->loop_info());
6592 !loop_it.Done(); 6596 !loop_it.Done();
6593 loop_it.Advance()) { 6597 loop_it.Advance()) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
6629 incoming = kDifferentValuesMarker; 6633 incoming = kDifferentValuesMarker;
6630 } 6634 }
6631 } 6635 }
6632 6636
6633 if (incoming != kDifferentValuesMarker) { 6637 if (incoming != kDifferentValuesMarker) {
6634 ASSERT(incoming != NULL); 6638 ASSERT(incoming != NULL);
6635 return incoming; 6639 return incoming;
6636 } 6640 }
6637 6641
6638 // Incoming values are different. Phi is required to merge. 6642 // Incoming values are different. Phi is required to merge.
6639 PhiInstr* phi = new(I) PhiInstr( 6643 PhiInstr* phi = new(Z) PhiInstr(
6640 block->AsJoinEntry(), block->PredecessorCount()); 6644 block->AsJoinEntry(), block->PredecessorCount());
6641 phi->set_place_id(place_id); 6645 phi->set_place_id(place_id);
6642 FillPhiInputs(phi); 6646 FillPhiInputs(phi);
6643 return phi; 6647 return phi;
6644 } 6648 }
6645 6649
6646 void FillPhiInputs(PhiInstr* phi) { 6650 void FillPhiInputs(PhiInstr* phi) {
6647 BlockEntryInstr* block = phi->GetBlock(); 6651 BlockEntryInstr* block = phi->GetBlock();
6648 const intptr_t place_id = phi->place_id(); 6652 const intptr_t place_id = phi->place_id();
6649 6653
6650 for (intptr_t i = 0; i < block->PredecessorCount(); i++) { 6654 for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
6651 BlockEntryInstr* pred = block->PredecessorAt(i); 6655 BlockEntryInstr* pred = block->PredecessorAt(i);
6652 ZoneGrowableArray<Definition*>* pred_out_values = 6656 ZoneGrowableArray<Definition*>* pred_out_values =
6653 out_values_[pred->preorder_number()]; 6657 out_values_[pred->preorder_number()];
6654 ASSERT((*pred_out_values)[place_id] != NULL); 6658 ASSERT((*pred_out_values)[place_id] != NULL);
6655 6659
6656 // Sets of outgoing values are not linked into use lists so 6660 // Sets of outgoing values are not linked into use lists so
6657 // they might contain values that were replaced and removed 6661 // they might contain values that were replaced and removed
6658 // from the graph by this iteration. 6662 // from the graph by this iteration.
6659 // To prevent using them we additionally mark definitions themselves 6663 // To prevent using them we additionally mark definitions themselves
6660 // as replaced and store a pointer to the replacement. 6664 // as replaced and store a pointer to the replacement.
6661 Definition* replacement = (*pred_out_values)[place_id]->Replacement(); 6665 Definition* replacement = (*pred_out_values)[place_id]->Replacement();
6662 Value* input = new(I) Value(replacement); 6666 Value* input = new(Z) Value(replacement);
6663 phi->SetInputAt(i, input); 6667 phi->SetInputAt(i, input);
6664 replacement->AddInputUse(input); 6668 replacement->AddInputUse(input);
6665 } 6669 }
6666 6670
6667 phi->set_ssa_temp_index(graph_->alloc_ssa_temp_index()); 6671 phi->set_ssa_temp_index(graph_->alloc_ssa_temp_index());
6668 phis_.Add(phi); // Postpone phi insertion until after load forwarding. 6672 phis_.Add(phi); // Postpone phi insertion until after load forwarding.
6669 6673
6670 if (FLAG_trace_load_optimization) { 6674 if (FLAG_trace_load_optimization) {
6671 OS::Print("created pending phi %s for %s at B%" Pd "\n", 6675 OS::Print("created pending phi %s for %s at B%" Pd "\n",
6672 phi->ToCString(), 6676 phi->ToCString(),
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
6725 // Eliminate it as redundant if this is the case. 6729 // Eliminate it as redundant if this is the case.
6726 // When analyzing phi operands assumes that only generated during 6730 // When analyzing phi operands assumes that only generated during
6727 // this load phase can be redundant. They can be distinguished because 6731 // this load phase can be redundant. They can be distinguished because
6728 // they are not marked alive. 6732 // they are not marked alive.
6729 // TODO(vegorov): move this into a separate phase over all phis. 6733 // TODO(vegorov): move this into a separate phase over all phis.
6730 bool EliminateRedundantPhi(PhiInstr* phi) { 6734 bool EliminateRedundantPhi(PhiInstr* phi) {
6731 Definition* value = NULL; // Possible value of this phi. 6735 Definition* value = NULL; // Possible value of this phi.
6732 6736
6733 worklist_.Clear(); 6737 worklist_.Clear();
6734 if (in_worklist_ == NULL) { 6738 if (in_worklist_ == NULL) {
6735 in_worklist_ = new(I) BitVector(I, graph_->current_ssa_temp_index()); 6739 in_worklist_ = new(Z) BitVector(Z, graph_->current_ssa_temp_index());
6736 } else { 6740 } else {
6737 in_worklist_->Clear(); 6741 in_worklist_->Clear();
6738 } 6742 }
6739 6743
6740 worklist_.Add(phi); 6744 worklist_.Add(phi);
6741 in_worklist_->Add(phi->ssa_temp_index()); 6745 in_worklist_->Add(phi->ssa_temp_index());
6742 6746
6743 for (intptr_t i = 0; i < worklist_.length(); i++) { 6747 for (intptr_t i = 0; i < worklist_.length(); i++) {
6744 PhiInstr* phi = worklist_[i]; 6748 PhiInstr* phi = worklist_[i];
6745 6749
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
6848 } 6852 }
6849 6853
6850 // Replace the given phi with another if they are congruent. 6854 // Replace the given phi with another if they are congruent.
6851 // Returns true if succeeds. 6855 // Returns true if succeeds.
6852 bool ReplacePhiWith(PhiInstr* phi, PhiInstr* replacement) { 6856 bool ReplacePhiWith(PhiInstr* phi, PhiInstr* replacement) {
6853 ASSERT(phi->InputCount() == replacement->InputCount()); 6857 ASSERT(phi->InputCount() == replacement->InputCount());
6854 ASSERT(phi->block() == replacement->block()); 6858 ASSERT(phi->block() == replacement->block());
6855 6859
6856 congruency_worklist_.Clear(); 6860 congruency_worklist_.Clear();
6857 if (in_worklist_ == NULL) { 6861 if (in_worklist_ == NULL) {
6858 in_worklist_ = new(I) BitVector(I, graph_->current_ssa_temp_index()); 6862 in_worklist_ = new(Z) BitVector(Z, graph_->current_ssa_temp_index());
6859 } else { 6863 } else {
6860 in_worklist_->Clear(); 6864 in_worklist_->Clear();
6861 } 6865 }
6862 6866
6863 // During the comparison worklist contains pairs of definitions to be 6867 // During the comparison worklist contains pairs of definitions to be
6864 // compared. 6868 // compared.
6865 if (!AddPairToCongruencyWorklist(phi, replacement)) { 6869 if (!AddPairToCongruencyWorklist(phi, replacement)) {
6866 return false; 6870 return false;
6867 } 6871 }
6868 6872
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
6953 for (intptr_t i = 0; i < phis_.length(); i++) { 6957 for (intptr_t i = 0; i < phis_.length(); i++) {
6954 PhiInstr* phi = phis_[i]; 6958 PhiInstr* phi = phis_[i];
6955 if ((phi != NULL) && (!phi->HasUses() || !EmitPhi(phi))) { 6959 if ((phi != NULL) && (!phi->HasUses() || !EmitPhi(phi))) {
6956 phi->UnuseAllInputs(); 6960 phi->UnuseAllInputs();
6957 } 6961 }
6958 } 6962 }
6959 } 6963 }
6960 6964
6961 ZoneGrowableArray<Definition*>* CreateBlockOutValues() { 6965 ZoneGrowableArray<Definition*>* CreateBlockOutValues() {
6962 ZoneGrowableArray<Definition*>* out = 6966 ZoneGrowableArray<Definition*>* out =
6963 new(I) ZoneGrowableArray<Definition*>(aliased_set_->max_place_id()); 6967 new(Z) ZoneGrowableArray<Definition*>(aliased_set_->max_place_id());
6964 for (intptr_t i = 0; i < aliased_set_->max_place_id(); i++) { 6968 for (intptr_t i = 0; i < aliased_set_->max_place_id(); i++) {
6965 out->Add(NULL); 6969 out->Add(NULL);
6966 } 6970 }
6967 return out; 6971 return out;
6968 } 6972 }
6969 6973
6970 FlowGraph* graph_; 6974 FlowGraph* graph_;
6971 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map_; 6975 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map_;
6972 6976
6973 // Mapping between field offsets in words and expression ids of loads from 6977 // Mapping between field offsets in words and expression ids of loads from
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
7059 case Instruction::kStoreIndexed: 7063 case Instruction::kStoreIndexed:
7060 case Instruction::kStoreStaticField: 7064 case Instruction::kStoreStaticField:
7061 return true; 7065 return true;
7062 default: 7066 default:
7063 UNREACHABLE(); 7067 UNREACHABLE();
7064 return false; 7068 return false;
7065 } 7069 }
7066 } 7070 }
7067 7071
7068 virtual void ComputeInitialSets() { 7072 virtual void ComputeInitialSets() {
7069 Isolate* isolate = graph_->isolate(); 7073 Zone* zone = graph_->zone();
7070 BitVector* all_places = new(isolate) BitVector(isolate, 7074 BitVector* all_places = new(zone) BitVector(zone,
7071 aliased_set_->max_place_id()); 7075 aliased_set_->max_place_id());
7072 all_places->SetAll(); 7076 all_places->SetAll();
7073 for (BlockIterator block_it = graph_->postorder_iterator(); 7077 for (BlockIterator block_it = graph_->postorder_iterator();
7074 !block_it.Done(); 7078 !block_it.Done();
7075 block_it.Advance()) { 7079 block_it.Advance()) {
7076 BlockEntryInstr* block = block_it.Current(); 7080 BlockEntryInstr* block = block_it.Current();
7077 const intptr_t postorder_number = block->postorder_number(); 7081 const intptr_t postorder_number = block->postorder_number();
7078 7082
7079 BitVector* kill = kill_[postorder_number]; 7083 BitVector* kill = kill_[postorder_number];
7080 BitVector* live_in = live_in_[postorder_number]; 7084 BitVector* live_in = live_in_[postorder_number];
(...skipping 25 matching lines...) Expand all
7106 "Removing dead store to place %" Pd " in block B%" Pd "\n", 7110 "Removing dead store to place %" Pd " in block B%" Pd "\n",
7107 instr->place_id(), block->block_id()); 7111 instr->place_id(), block->block_id());
7108 } 7112 }
7109 instr_it.RemoveCurrentFromGraph(); 7113 instr_it.RemoveCurrentFromGraph();
7110 } 7114 }
7111 } else if (!live_in->Contains(instr->place_id())) { 7115 } else if (!live_in->Contains(instr->place_id())) {
7112 // Mark this store as down-ward exposed: They are the only 7116 // Mark this store as down-ward exposed: They are the only
7113 // candidates for the global store elimination. 7117 // candidates for the global store elimination.
7114 if (exposed_stores == NULL) { 7118 if (exposed_stores == NULL) {
7115 const intptr_t kMaxExposedStoresInitialSize = 5; 7119 const intptr_t kMaxExposedStoresInitialSize = 5;
7116 exposed_stores = new(isolate) ZoneGrowableArray<Instruction*>( 7120 exposed_stores = new(zone) ZoneGrowableArray<Instruction*>(
7117 Utils::Minimum(kMaxExposedStoresInitialSize, 7121 Utils::Minimum(kMaxExposedStoresInitialSize,
7118 aliased_set_->max_place_id())); 7122 aliased_set_->max_place_id()));
7119 } 7123 }
7120 exposed_stores->Add(instr); 7124 exposed_stores->Add(instr);
7121 } 7125 }
7122 // Interfering stores kill only loads from the same place. 7126 // Interfering stores kill only loads from the same place.
7123 kill->Add(instr->place_id()); 7127 kill->Add(instr->place_id());
7124 live_in->Remove(instr->place_id()); 7128 live_in->Remove(instr->place_id());
7125 continue; 7129 continue;
7126 } 7130 }
(...skipping 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after
8216 } 8220 }
8217 8221
8218 8222
8219 // Insert MaterializeObject instruction for the given allocation before 8223 // Insert MaterializeObject instruction for the given allocation before
8220 // the given instruction that can deoptimize. 8224 // the given instruction that can deoptimize.
8221 void AllocationSinking::CreateMaterializationAt( 8225 void AllocationSinking::CreateMaterializationAt(
8222 Instruction* exit, 8226 Instruction* exit,
8223 Definition* alloc, 8227 Definition* alloc,
8224 const ZoneGrowableArray<const Object*>& slots) { 8228 const ZoneGrowableArray<const Object*>& slots) {
8225 ZoneGrowableArray<Value*>* values = 8229 ZoneGrowableArray<Value*>* values =
8226 new(I) ZoneGrowableArray<Value*>(slots.length()); 8230 new(Z) ZoneGrowableArray<Value*>(slots.length());
8227 8231
8228 // All loads should be inserted before the first materialization so that 8232 // All loads should be inserted before the first materialization so that
8229 // IR follows the following pattern: loads, materializations, deoptimizing 8233 // IR follows the following pattern: loads, materializations, deoptimizing
8230 // instruction. 8234 // instruction.
8231 Instruction* load_point = FirstMaterializationAt(exit); 8235 Instruction* load_point = FirstMaterializationAt(exit);
8232 8236
8233 // Insert load instruction for every field. 8237 // Insert load instruction for every field.
8234 for (intptr_t i = 0; i < slots.length(); i++) { 8238 for (intptr_t i = 0; i < slots.length(); i++) {
8235 LoadFieldInstr* load = slots[i]->IsField() 8239 LoadFieldInstr* load = slots[i]->IsField()
8236 ? new(I) LoadFieldInstr( 8240 ? new(Z) LoadFieldInstr(
8237 new(I) Value(alloc), 8241 new(Z) Value(alloc),
8238 &Field::Cast(*slots[i]), 8242 &Field::Cast(*slots[i]),
8239 AbstractType::ZoneHandle(I), 8243 AbstractType::ZoneHandle(Z),
8240 alloc->token_pos()) 8244 alloc->token_pos())
8241 : new(I) LoadFieldInstr( 8245 : new(Z) LoadFieldInstr(
8242 new(I) Value(alloc), 8246 new(Z) Value(alloc),
8243 Smi::Cast(*slots[i]).Value(), 8247 Smi::Cast(*slots[i]).Value(),
8244 AbstractType::ZoneHandle(I), 8248 AbstractType::ZoneHandle(Z),
8245 alloc->token_pos()); 8249 alloc->token_pos());
8246 flow_graph_->InsertBefore( 8250 flow_graph_->InsertBefore(
8247 load_point, load, NULL, FlowGraph::kValue); 8251 load_point, load, NULL, FlowGraph::kValue);
8248 values->Add(new(I) Value(load)); 8252 values->Add(new(Z) Value(load));
8249 } 8253 }
8250 8254
8251 MaterializeObjectInstr* mat = NULL; 8255 MaterializeObjectInstr* mat = NULL;
8252 if (alloc->IsAllocateObject()) { 8256 if (alloc->IsAllocateObject()) {
8253 mat = new(I) MaterializeObjectInstr( 8257 mat = new(Z) MaterializeObjectInstr(
8254 alloc->AsAllocateObject(), slots, values); 8258 alloc->AsAllocateObject(), slots, values);
8255 } else { 8259 } else {
8256 ASSERT(alloc->IsAllocateUninitializedContext()); 8260 ASSERT(alloc->IsAllocateUninitializedContext());
8257 mat = new(I) MaterializeObjectInstr( 8261 mat = new(Z) MaterializeObjectInstr(
8258 alloc->AsAllocateUninitializedContext(), slots, values); 8262 alloc->AsAllocateUninitializedContext(), slots, values);
8259 } 8263 }
8260 8264
8261 flow_graph_->InsertBefore(exit, mat, NULL, FlowGraph::kValue); 8265 flow_graph_->InsertBefore(exit, mat, NULL, FlowGraph::kValue);
8262 8266
8263 // Replace all mentions of this allocation with a newly inserted 8267 // Replace all mentions of this allocation with a newly inserted
8264 // MaterializeObject instruction. 8268 // MaterializeObject instruction.
8265 // We must preserve the identity: all mentions are replaced by the same 8269 // We must preserve the identity: all mentions are replaced by the same
8266 // materialization. 8270 // materialization.
8267 for (Environment::DeepIterator env_it(exit->env()); 8271 for (Environment::DeepIterator env_it(exit->env());
8268 !env_it.Done(); 8272 !env_it.Done();
8269 env_it.Advance()) { 8273 env_it.Advance()) {
8270 Value* use = env_it.CurrentValue(); 8274 Value* use = env_it.CurrentValue();
8271 if (use->definition() == alloc) { 8275 if (use->definition() == alloc) {
8272 use->RemoveFromUseList(); 8276 use->RemoveFromUseList();
8273 use->set_definition(mat); 8277 use->set_definition(mat);
8274 mat->AddEnvUse(use); 8278 mat->AddEnvUse(use);
8275 } 8279 }
8276 } 8280 }
8277 8281
8278 // Mark MaterializeObject as an environment use of this allocation. 8282 // Mark MaterializeObject as an environment use of this allocation.
8279 // This will allow us to discover it when we are looking for deoptimization 8283 // This will allow us to discover it when we are looking for deoptimization
8280 // exits for another allocation that potentially flows into this one. 8284 // exits for another allocation that potentially flows into this one.
8281 Value* val = new(I) Value(alloc); 8285 Value* val = new(Z) Value(alloc);
8282 val->set_instruction(mat); 8286 val->set_instruction(mat);
8283 alloc->AddEnvUse(val); 8287 alloc->AddEnvUse(val);
8284 8288
8285 // Record inserted materialization. 8289 // Record inserted materialization.
8286 materializations_.Add(mat); 8290 materializations_.Add(mat);
8287 } 8291 }
8288 8292
8289 8293
8290 // Add given instruction to the list of the instructions if it is not yet 8294 // Add given instruction to the list of the instructions if it is not yet
8291 // present there. 8295 // present there.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
8346 // as a bitvector. 8350 // as a bitvector.
8347 for (intptr_t i = 0; i < worklist_.length(); i++) { 8351 for (intptr_t i = 0; i < worklist_.length(); i++) {
8348 Collect(worklist_[i]); 8352 Collect(worklist_[i]);
8349 } 8353 }
8350 } 8354 }
8351 8355
8352 8356
8353 void AllocationSinking::InsertMaterializations(Definition* alloc) { 8357 void AllocationSinking::InsertMaterializations(Definition* alloc) {
8354 // Collect all fields that are written for this instance. 8358 // Collect all fields that are written for this instance.
8355 ZoneGrowableArray<const Object*>* slots = 8359 ZoneGrowableArray<const Object*>* slots =
8356 new(I) ZoneGrowableArray<const Object*>(5); 8360 new(Z) ZoneGrowableArray<const Object*>(5);
8357 8361
8358 for (Value* use = alloc->input_use_list(); 8362 for (Value* use = alloc->input_use_list();
8359 use != NULL; 8363 use != NULL;
8360 use = use->next_use()) { 8364 use = use->next_use()) {
8361 StoreInstanceFieldInstr* store = use->instruction()->AsStoreInstanceField(); 8365 StoreInstanceFieldInstr* store = use->instruction()->AsStoreInstanceField();
8362 if ((store != NULL) && (store->instance()->definition() == alloc)) { 8366 if ((store != NULL) && (store->instance()->definition() == alloc)) {
8363 if (!store->field().IsNull()) { 8367 if (!store->field().IsNull()) {
8364 AddSlot(slots, store->field()); 8368 AddSlot(slots, store->field());
8365 } else { 8369 } else {
8366 AddSlot(slots, Smi::ZoneHandle(I, Smi::New(store->offset_in_bytes()))); 8370 AddSlot(slots, Smi::ZoneHandle(Z, Smi::New(store->offset_in_bytes())));
8367 } 8371 }
8368 } 8372 }
8369 } 8373 }
8370 8374
8371 if (alloc->ArgumentCount() > 0) { 8375 if (alloc->ArgumentCount() > 0) {
8372 AllocateObjectInstr* alloc_object = alloc->AsAllocateObject(); 8376 AllocateObjectInstr* alloc_object = alloc->AsAllocateObject();
8373 ASSERT(alloc_object->ArgumentCount() == 1); 8377 ASSERT(alloc_object->ArgumentCount() == 1);
8374 intptr_t type_args_offset = 8378 intptr_t type_args_offset =
8375 alloc_object->cls().type_arguments_field_offset(); 8379 alloc_object->cls().type_arguments_field_offset();
8376 AddSlot(slots, Smi::ZoneHandle(I, Smi::New(type_args_offset))); 8380 AddSlot(slots, Smi::ZoneHandle(Z, Smi::New(type_args_offset)));
8377 } 8381 }
8378 8382
8379 // Collect all instructions that mention this object in the environment. 8383 // Collect all instructions that mention this object in the environment.
8380 exits_collector_.CollectTransitively(alloc); 8384 exits_collector_.CollectTransitively(alloc);
8381 8385
8382 // Insert materializations at environment uses. 8386 // Insert materializations at environment uses.
8383 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { 8387 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) {
8384 CreateMaterializationAt( 8388 CreateMaterializationAt(
8385 exits_collector_.exits()[i], alloc, *slots); 8389 exits_collector_.exits()[i], alloc, *slots);
8386 } 8390 }
8387 } 8391 }
8388 8392
8389 8393
8390 } // namespace dart 8394 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698