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