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