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 |