| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 prev->set_next(next); | 89 prev->set_next(next); |
| 90 next->set_previous(prev); | 90 next->set_previous(prev); |
| 91 // Reset successor and previous instruction to indicate | 91 // Reset successor and previous instruction to indicate |
| 92 // that the instruction is removed from the graph. | 92 // that the instruction is removed from the graph. |
| 93 current_->set_previous(NULL); | 93 current_->set_previous(NULL); |
| 94 current_->set_next(NULL); | 94 current_->set_next(NULL); |
| 95 current_ = prev; | 95 current_ = prev; |
| 96 } | 96 } |
| 97 | 97 |
| 98 | 98 |
| 99 // True iff. the v2 is above v1 on stack, or one of them is constant. | |
| 100 static bool VerifyValues(Value* v1, Value* v2) { | |
| 101 ASSERT(v1->IsUse() && v2->IsUse()); | |
| 102 return (v1->AsUse()->definition()->temp_index() + 1) == | |
| 103 v2->AsUse()->definition()->temp_index(); | |
| 104 } | |
| 105 | |
| 106 | |
| 107 // Default implementation of visiting basic blocks. Can be overridden. | 99 // Default implementation of visiting basic blocks. Can be overridden. |
| 108 void FlowGraphVisitor::VisitBlocks() { | 100 void FlowGraphVisitor::VisitBlocks() { |
| 109 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 101 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 110 BlockEntryInstr* entry = block_order_[i]; | 102 BlockEntryInstr* entry = block_order_[i]; |
| 111 entry->Accept(this); | 103 entry->Accept(this); |
| 112 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 104 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 113 it.Current()->Accept(this); | 105 it.Current()->Accept(this); |
| 114 } | 106 } |
| 115 } | 107 } |
| 116 } | 108 } |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 | 377 |
| 386 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const { | 378 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const { |
| 387 for (intptr_t i = 0; i < predecessors_.length(); ++i) { | 379 for (intptr_t i = 0; i < predecessors_.length(); ++i) { |
| 388 if (predecessors_[i] == pred) return i; | 380 if (predecessors_[i] == pred) return i; |
| 389 } | 381 } |
| 390 return -1; | 382 return -1; |
| 391 } | 383 } |
| 392 | 384 |
| 393 | 385 |
| 394 // ==== Recording assigned variables. | 386 // ==== Recording assigned variables. |
| 395 void Computation::RecordAssignedVars(BitVector* assigned_vars) { | 387 void Computation::RecordAssignedVars(BitVector* assigned_vars, |
| 388 intptr_t fixed_parameter_count) { |
| 396 // Nothing to do for the base class. | 389 // Nothing to do for the base class. |
| 397 } | 390 } |
| 398 | 391 |
| 399 | 392 |
| 400 void StoreLocalComp::RecordAssignedVars(BitVector* assigned_vars) { | 393 void StoreLocalComp::RecordAssignedVars(BitVector* assigned_vars, |
| 394 intptr_t fixed_parameter_count) { |
| 401 if (!local().is_captured()) { | 395 if (!local().is_captured()) { |
| 402 assigned_vars->Add(local().BitIndexIn(assigned_vars->length())); | 396 assigned_vars->Add(local().BitIndexIn(fixed_parameter_count)); |
| 403 } | 397 } |
| 404 } | 398 } |
| 405 | 399 |
| 406 | 400 |
| 407 void Instruction::RecordAssignedVars(BitVector* assigned_vars) { | 401 void Instruction::RecordAssignedVars(BitVector* assigned_vars, |
| 402 intptr_t fixed_parameter_count) { |
| 408 // Nothing to do for the base class. | 403 // Nothing to do for the base class. |
| 409 } | 404 } |
| 410 | 405 |
| 411 | 406 |
| 412 void BindInstr::RecordAssignedVars(BitVector* assigned_vars) { | 407 void BindInstr::RecordAssignedVars(BitVector* assigned_vars, |
| 413 computation()->RecordAssignedVars(assigned_vars); | 408 intptr_t fixed_parameter_count) { |
| 409 computation()->RecordAssignedVars(assigned_vars, fixed_parameter_count); |
| 414 } | 410 } |
| 415 | 411 |
| 416 | 412 |
| 417 // ==== Postorder graph traversal. | 413 // ==== Postorder graph traversal. |
| 418 void GraphEntryInstr::DiscoverBlocks( | 414 void GraphEntryInstr::DiscoverBlocks( |
| 419 BlockEntryInstr* current_block, | 415 BlockEntryInstr* current_block, |
| 420 GrowableArray<BlockEntryInstr*>* preorder, | 416 GrowableArray<BlockEntryInstr*>* preorder, |
| 421 GrowableArray<BlockEntryInstr*>* postorder, | 417 GrowableArray<BlockEntryInstr*>* postorder, |
| 422 GrowableArray<intptr_t>* parent, | 418 GrowableArray<intptr_t>* parent, |
| 423 GrowableArray<BitVector*>* assigned_vars, | 419 GrowableArray<BitVector*>* assigned_vars, |
| 424 intptr_t variable_count) { | 420 intptr_t variable_count, |
| 421 intptr_t fixed_parameter_count) { |
| 425 // We only visit this block once, first of all blocks. | 422 // We only visit this block once, first of all blocks. |
| 426 ASSERT(preorder_number() == -1); | 423 ASSERT(preorder_number() == -1); |
| 427 ASSERT(current_block == NULL); | 424 ASSERT(current_block == NULL); |
| 428 ASSERT(preorder->is_empty()); | 425 ASSERT(preorder->is_empty()); |
| 429 ASSERT(postorder->is_empty()); | 426 ASSERT(postorder->is_empty()); |
| 430 ASSERT(parent->is_empty()); | 427 ASSERT(parent->is_empty()); |
| 431 | 428 |
| 432 // This node has no parent, indicated by -1. The preorder number is 0. | 429 // This node has no parent, indicated by -1. The preorder number is 0. |
| 433 parent->Add(-1); | 430 parent->Add(-1); |
| 434 set_preorder_number(0); | 431 set_preorder_number(0); |
| 435 preorder->Add(this); | 432 preorder->Add(this); |
| 436 BitVector* vars = | 433 BitVector* vars = |
| 437 (variable_count == 0) ? NULL : new BitVector(variable_count); | 434 (variable_count == 0) ? NULL : new BitVector(variable_count); |
| 438 assigned_vars->Add(vars); | 435 assigned_vars->Add(vars); |
| 439 | 436 |
| 440 // The graph entry consists of only one instruction. | 437 // The graph entry consists of only one instruction. |
| 441 set_last_instruction(this); | 438 set_last_instruction(this); |
| 442 | 439 |
| 443 // Iteratively traverse all successors. In the unoptimized code, we will | 440 // Iteratively traverse all successors. In the unoptimized code, we will |
| 444 // enter the function at the first successor in reverse postorder, so we | 441 // enter the function at the first successor in reverse postorder, so we |
| 445 // must visit the normal entry last. | 442 // must visit the normal entry last. |
| 446 for (intptr_t i = catch_entries_.length() - 1; i >= 0; --i) { | 443 for (intptr_t i = catch_entries_.length() - 1; i >= 0; --i) { |
| 447 catch_entries_[i]->DiscoverBlocks(this, preorder, postorder, | 444 catch_entries_[i]->DiscoverBlocks(this, preorder, postorder, |
| 448 parent, assigned_vars, variable_count); | 445 parent, assigned_vars, |
| 446 variable_count, fixed_parameter_count); |
| 449 } | 447 } |
| 450 normal_entry_->DiscoverBlocks(this, preorder, postorder, | 448 normal_entry_->DiscoverBlocks(this, preorder, postorder, |
| 451 parent, assigned_vars, variable_count); | 449 parent, assigned_vars, |
| 450 variable_count, fixed_parameter_count); |
| 452 | 451 |
| 453 // Assign postorder number. | 452 // Assign postorder number. |
| 454 set_postorder_number(postorder->length()); | 453 set_postorder_number(postorder->length()); |
| 455 postorder->Add(this); | 454 postorder->Add(this); |
| 456 } | 455 } |
| 457 | 456 |
| 458 | 457 |
| 459 // Base class implementation used for JoinEntry and TargetEntry. | 458 // Base class implementation used for JoinEntry and TargetEntry. |
| 460 void BlockEntryInstr::DiscoverBlocks( | 459 void BlockEntryInstr::DiscoverBlocks( |
| 461 BlockEntryInstr* current_block, | 460 BlockEntryInstr* current_block, |
| 462 GrowableArray<BlockEntryInstr*>* preorder, | 461 GrowableArray<BlockEntryInstr*>* preorder, |
| 463 GrowableArray<BlockEntryInstr*>* postorder, | 462 GrowableArray<BlockEntryInstr*>* postorder, |
| 464 GrowableArray<intptr_t>* parent, | 463 GrowableArray<intptr_t>* parent, |
| 465 GrowableArray<BitVector*>* assigned_vars, | 464 GrowableArray<BitVector*>* assigned_vars, |
| 466 intptr_t variable_count) { | 465 intptr_t variable_count, |
| 466 intptr_t fixed_parameter_count) { |
| 467 // We have already visited the graph entry, so we can assume current_block | 467 // We have already visited the graph entry, so we can assume current_block |
| 468 // is non-null and preorder array is non-empty. | 468 // is non-null and preorder array is non-empty. |
| 469 ASSERT(current_block != NULL); | 469 ASSERT(current_block != NULL); |
| 470 ASSERT(!preorder->is_empty()); | 470 ASSERT(!preorder->is_empty()); |
| 471 | 471 |
| 472 // 1. Record control-flow-graph basic-block predecessors. | 472 // 1. Record control-flow-graph basic-block predecessors. |
| 473 AddPredecessor(current_block); | 473 AddPredecessor(current_block); |
| 474 | 474 |
| 475 // 2. If the block has already been reached by the traversal, we are | 475 // 2. If the block has already been reached by the traversal, we are |
| 476 // done. Blocks with a single predecessor cannot have been reached | 476 // done. Blocks with a single predecessor cannot have been reached |
| (...skipping 19 matching lines...) Expand all Loading... |
| 496 // 5. Iterate straight-line successors until a branch instruction or | 496 // 5. Iterate straight-line successors until a branch instruction or |
| 497 // another basic block entry instruction, and visit that instruction. | 497 // another basic block entry instruction, and visit that instruction. |
| 498 ASSERT(next() != NULL); | 498 ASSERT(next() != NULL); |
| 499 Instruction* next_instr = next(); | 499 Instruction* next_instr = next(); |
| 500 if (next_instr->IsBlockEntry()) { | 500 if (next_instr->IsBlockEntry()) { |
| 501 set_last_instruction(this); | 501 set_last_instruction(this); |
| 502 } else { | 502 } else { |
| 503 while ((next_instr != NULL) && | 503 while ((next_instr != NULL) && |
| 504 !next_instr->IsBlockEntry() && | 504 !next_instr->IsBlockEntry() && |
| 505 !next_instr->IsBranch()) { | 505 !next_instr->IsBranch()) { |
| 506 if (vars != NULL) next_instr->RecordAssignedVars(vars); | 506 if (vars != NULL) { |
| 507 next_instr->RecordAssignedVars(vars, fixed_parameter_count); |
| 508 } |
| 507 set_last_instruction(next_instr); | 509 set_last_instruction(next_instr); |
| 508 GotoInstr* goto_instr = next_instr->AsGoto(); | 510 GotoInstr* goto_instr = next_instr->AsGoto(); |
| 509 next_instr = | 511 next_instr = |
| 510 (goto_instr != NULL) ? goto_instr->successor() : next_instr->next(); | 512 (goto_instr != NULL) ? goto_instr->successor() : next_instr->next(); |
| 511 } | 513 } |
| 512 } | 514 } |
| 513 if (next_instr != NULL) { | 515 if (next_instr != NULL) { |
| 514 next_instr->DiscoverBlocks(this, preorder, postorder, | 516 next_instr->DiscoverBlocks(this, preorder, postorder, |
| 515 parent, assigned_vars, variable_count); | 517 parent, assigned_vars, |
| 518 variable_count, fixed_parameter_count); |
| 516 } | 519 } |
| 517 | 520 |
| 518 // 6. Assign postorder number and add the block entry to the list. | 521 // 6. Assign postorder number and add the block entry to the list. |
| 519 set_postorder_number(postorder->length()); | 522 set_postorder_number(postorder->length()); |
| 520 postorder->Add(this); | 523 postorder->Add(this); |
| 521 } | 524 } |
| 522 | 525 |
| 523 | 526 |
| 524 void BranchInstr::DiscoverBlocks( | 527 void BranchInstr::DiscoverBlocks( |
| 525 BlockEntryInstr* current_block, | 528 BlockEntryInstr* current_block, |
| 526 GrowableArray<BlockEntryInstr*>* preorder, | 529 GrowableArray<BlockEntryInstr*>* preorder, |
| 527 GrowableArray<BlockEntryInstr*>* postorder, | 530 GrowableArray<BlockEntryInstr*>* postorder, |
| 528 GrowableArray<intptr_t>* parent, | 531 GrowableArray<intptr_t>* parent, |
| 529 GrowableArray<BitVector*>* assigned_vars, | 532 GrowableArray<BitVector*>* assigned_vars, |
| 530 intptr_t variable_count) { | 533 intptr_t variable_count, |
| 534 intptr_t fixed_parameter_count) { |
| 531 current_block->set_last_instruction(this); | 535 current_block->set_last_instruction(this); |
| 532 // Visit the false successor before the true successor so they appear in | 536 // Visit the false successor before the true successor so they appear in |
| 533 // true/false order in reverse postorder used as the block ordering in the | 537 // true/false order in reverse postorder used as the block ordering in the |
| 534 // nonoptimizing compiler. | 538 // nonoptimizing compiler. |
| 535 ASSERT(true_successor_ != NULL); | 539 ASSERT(true_successor_ != NULL); |
| 536 ASSERT(false_successor_ != NULL); | 540 ASSERT(false_successor_ != NULL); |
| 537 false_successor_->DiscoverBlocks(current_block, preorder, postorder, | 541 false_successor_->DiscoverBlocks(current_block, preorder, postorder, |
| 538 parent, assigned_vars, variable_count); | 542 parent, assigned_vars, |
| 543 variable_count, fixed_parameter_count); |
| 539 true_successor_->DiscoverBlocks(current_block, preorder, postorder, | 544 true_successor_->DiscoverBlocks(current_block, preorder, postorder, |
| 540 parent, assigned_vars, variable_count); | 545 parent, assigned_vars, |
| 546 variable_count, fixed_parameter_count); |
| 541 } | 547 } |
| 542 | 548 |
| 543 | 549 |
| 544 void JoinEntryInstr::InsertPhi(intptr_t var_index, intptr_t var_count) { | 550 void JoinEntryInstr::InsertPhi(intptr_t var_index, intptr_t var_count) { |
| 545 // Lazily initialize the array of phis. | 551 // Lazily initialize the array of phis. |
| 546 // Currently, phis are stored in a sparse array that holds the phi | 552 // Currently, phis are stored in a sparse array that holds the phi |
| 547 // for variable with index i at position i. | 553 // for variable with index i at position i. |
| 548 // TODO(fschneider): Store phis in a more compact way. | 554 // TODO(fschneider): Store phis in a more compact way. |
| 549 if (phis_ == NULL) { | 555 if (phis_ == NULL) { |
| 550 phis_ = new ZoneGrowableArray<PhiInstr*>(var_count); | 556 phis_ = new ZoneGrowableArray<PhiInstr*>(var_count); |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 949 summary->set_in(0, Location::RequiresRegister()); | 955 summary->set_in(0, Location::RequiresRegister()); |
| 950 summary->set_in(1, Location::RequiresRegister()); | 956 summary->set_in(1, Location::RequiresRegister()); |
| 951 if (HasICData()) { | 957 if (HasICData()) { |
| 952 summary->set_temp(0, Location::RequiresRegister()); | 958 summary->set_temp(0, Location::RequiresRegister()); |
| 953 } | 959 } |
| 954 return summary; | 960 return summary; |
| 955 } | 961 } |
| 956 | 962 |
| 957 | 963 |
| 958 void StoreInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 964 void StoreInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 959 ASSERT(VerifyValues(instance(), value())); | |
| 960 Register instance_reg = locs()->in(0).reg(); | 965 Register instance_reg = locs()->in(0).reg(); |
| 961 Register value_reg = locs()->in(1).reg(); | 966 Register value_reg = locs()->in(1).reg(); |
| 962 | 967 |
| 963 if (HasICData()) { | 968 if (HasICData()) { |
| 964 ASSERT(original() != NULL); | 969 ASSERT(original() != NULL); |
| 965 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 970 Label* deopt = compiler->AddDeoptStub(original()->cid(), |
| 966 original()->token_pos(), | 971 original()->token_pos(), |
| 967 original()->try_index(), | 972 original()->try_index(), |
| 968 kDeoptInstanceGetterSameTarget, | 973 kDeoptInstanceGetterSameTarget, |
| 969 instance_reg, | 974 instance_reg, |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1300 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); | 1305 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); |
| 1301 compiler->GenerateCall(token_pos(), try_index(), &label, | 1306 compiler->GenerateCall(token_pos(), try_index(), &label, |
| 1302 PcDescriptors::kOther); | 1307 PcDescriptors::kOther); |
| 1303 __ Drop(2); // Discard type arguments and receiver. | 1308 __ Drop(2); // Discard type arguments and receiver. |
| 1304 } | 1309 } |
| 1305 | 1310 |
| 1306 | 1311 |
| 1307 #undef __ | 1312 #undef __ |
| 1308 | 1313 |
| 1309 } // namespace dart | 1314 } // namespace dart |
| OLD | NEW |