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

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

Issue 12457034: Ensure that all goto instructions have deoptimization target. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Delete UNREACHABLE Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.cc ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/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 1812 matching lines...) Expand 10 before | Expand all | Expand 10 after
1823 ReplaceCall(call, bool_const); 1823 ReplaceCall(call, bool_const);
1824 return; 1824 return;
1825 } 1825 }
1826 } 1826 }
1827 InstanceOfInstr* instance_of = 1827 InstanceOfInstr* instance_of =
1828 new InstanceOfInstr(call->token_pos(), 1828 new InstanceOfInstr(call->token_pos(),
1829 new Value(left), 1829 new Value(left),
1830 new Value(instantiator), 1830 new Value(instantiator),
1831 new Value(type_args), 1831 new Value(type_args),
1832 type, 1832 type,
1833 negate); 1833 negate,
1834 call->deopt_id());
1834 ReplaceCall(call, instance_of); 1835 ReplaceCall(call, instance_of);
1835 } 1836 }
1836 1837
1837 1838
1838 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { 1839 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
1839 ASSERT(Token::IsTypeCastOperator(call->token_kind())); 1840 ASSERT(Token::IsTypeCastOperator(call->token_kind()));
1840 Definition* left = call->ArgumentAt(0); 1841 Definition* left = call->ArgumentAt(0);
1841 Definition* instantiator = call->ArgumentAt(1); 1842 Definition* instantiator = call->ArgumentAt(1);
1842 Definition* type_args = call->ArgumentAt(2); 1843 Definition* type_args = call->ArgumentAt(2);
1843 const AbstractType& type = 1844 const AbstractType& type =
(...skipping 19 matching lines...) Expand all
1863 } 1864 }
1864 const String& dst_name = String::ZoneHandle( 1865 const String& dst_name = String::ZoneHandle(
1865 Symbols::New(Exceptions::kCastErrorDstName)); 1866 Symbols::New(Exceptions::kCastErrorDstName));
1866 AssertAssignableInstr* assert_as = 1867 AssertAssignableInstr* assert_as =
1867 new AssertAssignableInstr(call->token_pos(), 1868 new AssertAssignableInstr(call->token_pos(),
1868 new Value(left), 1869 new Value(left),
1869 new Value(instantiator), 1870 new Value(instantiator),
1870 new Value(type_args), 1871 new Value(type_args),
1871 type, 1872 type,
1872 dst_name); 1873 dst_name);
1874 // Newly inserted instructions that can deoptimize or throw an exception
1875 // must have a deoptimization id that is valid for lookup in the unoptimized
1876 // code.
1877 assert_as->deopt_id_ = call->deopt_id();
1873 ReplaceCall(call, assert_as); 1878 ReplaceCall(call, assert_as);
1874 } 1879 }
1875 1880
1876 1881
1877 // Tries to optimize instance call by replacing it with a faster instruction 1882 // Tries to optimize instance call by replacing it with a faster instruction
1878 // (e.g, binary op, field load, ..). 1883 // (e.g, binary op, field load, ..).
1879 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { 1884 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
1880 if (!instr->HasICData() || (instr->ic_data()->NumberOfChecks() == 0)) { 1885 if (!instr->HasICData() || (instr->ic_data()->NumberOfChecks() == 0)) {
1881 return; 1886 return;
1882 } 1887 }
(...skipping 2475 matching lines...) Expand 10 before | Expand all | Expand 10 after
4358 if (!reachable_->Contains(block->preorder_number())) { 4363 if (!reachable_->Contains(block->preorder_number())) {
4359 if (FLAG_trace_constant_propagation) { 4364 if (FLAG_trace_constant_propagation) {
4360 OS::Print("Unreachable B%"Pd"\n", block->block_id()); 4365 OS::Print("Unreachable B%"Pd"\n", block->block_id());
4361 } 4366 }
4362 // Remove all uses in unreachable blocks. 4367 // Remove all uses in unreachable blocks.
4363 if (join != NULL) { 4368 if (join != NULL) {
4364 for (PhiIterator it(join); !it.Done(); it.Advance()) { 4369 for (PhiIterator it(join); !it.Done(); it.Advance()) {
4365 it.Current()->UnuseAllInputs(); 4370 it.Current()->UnuseAllInputs();
4366 } 4371 }
4367 } 4372 }
4373 block->UnuseAllInputs();
4368 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 4374 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
4369 it.Current()->UnuseAllInputs(); 4375 it.Current()->UnuseAllInputs();
4370 } 4376 }
4371 continue; 4377 continue;
4372 } 4378 }
4373 4379
4374 if (join != NULL) { 4380 if (join != NULL) {
4375 // Remove phi inputs corresponding to unreachable predecessor blocks. 4381 // Remove phi inputs corresponding to unreachable predecessor blocks.
4376 // Predecessors will be recomputed (in block id order) after removing 4382 // Predecessors will be recomputed (in block id order) after removing
4377 // unreachable code so we merely have to keep the phi inputs in order. 4383 // unreachable code so we merely have to keep the phi inputs in order.
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
4450 TargetEntryInstr* if_true = branch->true_successor(); 4456 TargetEntryInstr* if_true = branch->true_successor();
4451 TargetEntryInstr* if_false = branch->false_successor(); 4457 TargetEntryInstr* if_false = branch->false_successor();
4452 JoinEntryInstr* join = NULL; 4458 JoinEntryInstr* join = NULL;
4453 Instruction* next = NULL; 4459 Instruction* next = NULL;
4454 4460
4455 if (!reachable_->Contains(if_true->preorder_number())) { 4461 if (!reachable_->Contains(if_true->preorder_number())) {
4456 ASSERT(reachable_->Contains(if_false->preorder_number())); 4462 ASSERT(reachable_->Contains(if_false->preorder_number()));
4457 ASSERT(if_false->parallel_move() == NULL); 4463 ASSERT(if_false->parallel_move() == NULL);
4458 ASSERT(if_false->loop_info() == NULL); 4464 ASSERT(if_false->loop_info() == NULL);
4459 join = new JoinEntryInstr(if_false->block_id(), if_false->try_index()); 4465 join = new JoinEntryInstr(if_false->block_id(), if_false->try_index());
4466 join->InheritDeoptTarget(if_false);
4467 if_false->UnuseAllInputs();
4460 next = if_false->next(); 4468 next = if_false->next();
4461 } else if (!reachable_->Contains(if_false->preorder_number())) { 4469 } else if (!reachable_->Contains(if_false->preorder_number())) {
4462 ASSERT(if_true->parallel_move() == NULL); 4470 ASSERT(if_true->parallel_move() == NULL);
4463 ASSERT(if_true->loop_info() == NULL); 4471 ASSERT(if_true->loop_info() == NULL);
4464 join = new JoinEntryInstr(if_true->block_id(), if_true->try_index()); 4472 join = new JoinEntryInstr(if_true->block_id(), if_true->try_index());
4473 join->InheritDeoptTarget(if_true);
4474 if_true->UnuseAllInputs();
4465 next = if_true->next(); 4475 next = if_true->next();
4466 } 4476 }
4467 4477
4468 if (join != NULL) { 4478 if (join != NULL) {
4469 // Replace the branch with a jump to the reachable successor. 4479 // Replace the branch with a jump to the reachable successor.
4470 // Drop the comparison, which does not have side effects as long 4480 // Drop the comparison, which does not have side effects as long
4471 // as it is a strict compare (the only one we can determine is 4481 // as it is a strict compare (the only one we can determine is
4472 // constant with the current analysis). 4482 // constant with the current analysis).
4473 GotoInstr* jump = new GotoInstr(join); 4483 GotoInstr* jump = new GotoInstr(join);
4484 jump->InheritDeoptTarget(branch);
4485
4474 Instruction* previous = branch->previous(); 4486 Instruction* previous = branch->previous();
4475 branch->set_previous(NULL); 4487 branch->set_previous(NULL);
4476 previous->LinkTo(jump); 4488 previous->LinkTo(jump);
4489
4477 // Replace the false target entry with the new join entry. We will 4490 // Replace the false target entry with the new join entry. We will
4478 // recompute the dominators after this pass. 4491 // recompute the dominators after this pass.
4479 join->LinkTo(next); 4492 join->LinkTo(next);
4480 branch->UnuseAllInputs(); 4493 branch->UnuseAllInputs();
4481 } 4494 }
4482 } 4495 }
4483 } 4496 }
4484 4497
4485 graph_->DiscoverBlocks(); 4498 graph_->DiscoverBlocks();
4486 GrowableArray<BitVector*> dominance_frontier; 4499 GrowableArray<BitVector*> dominance_frontier;
4487 graph_->ComputeDominators(&dominance_frontier); 4500 graph_->ComputeDominators(&dominance_frontier);
4488 4501
4489 if (FLAG_trace_constant_propagation) { 4502 if (FLAG_trace_constant_propagation) {
4490 OS::Print("\n==== After constant propagation ====\n"); 4503 OS::Print("\n==== After constant propagation ====\n");
4491 FlowGraphPrinter printer(*graph_); 4504 FlowGraphPrinter printer(*graph_);
4492 printer.PrintBlocks(); 4505 printer.PrintBlocks();
4493 } 4506 }
4494 } 4507 }
4495 4508
4496 4509
4510 // Returns true if the given phi has a single input use and
4511 // is used in the environments either at the corresponding block entry or
4512 // at the same instruction where input use is.
4513 static bool PhiHasSingleUse(PhiInstr* phi, Value* use) {
4514 if ((use->next_use() != NULL) || (phi->input_use_list() != use)) {
4515 return false;
4516 }
4517
4518 BlockEntryInstr* block = phi->block();
4519 for (Value* env_use = phi->env_use_list();
4520 env_use != NULL;
4521 env_use = env_use->next_use()) {
4522 if ((env_use->instruction() != block) &&
4523 (env_use->instruction() != use->instruction())) {
4524 return false;
4525 }
4526 }
4527
4528 return true;
4529 }
4530
4531
4497 bool BranchSimplifier::Match(JoinEntryInstr* block) { 4532 bool BranchSimplifier::Match(JoinEntryInstr* block) {
4498 // Match the pattern of a branch on a comparison whose left operand is a 4533 // Match the pattern of a branch on a comparison whose left operand is a
4499 // phi from the same block, and whose right operand is a constant. 4534 // phi from the same block, and whose right operand is a constant.
4500 // 4535 //
4501 // Branch(Comparison(kind, Phi, Constant)) 4536 // Branch(Comparison(kind, Phi, Constant))
4502 // 4537 //
4503 // These are the branches produced by inlining in a test context. Also, 4538 // These are the branches produced by inlining in a test context. Also,
4504 // the phi and the constant have no other uses so they can simply be 4539 // the phi and the constant have no other uses so they can simply be
4505 // eliminated. The block has no other phis and no instructions 4540 // eliminated. The block has no other phis and no instructions
4506 // intervening between the phi, constant, and branch so the block can 4541 // intervening between the phi, constant, and branch so the block can
4507 // simply be eliminated. 4542 // simply be eliminated.
4508 BranchInstr* branch = block->last_instruction()->AsBranch(); 4543 BranchInstr* branch = block->last_instruction()->AsBranch();
4509 ASSERT(branch != NULL); 4544 ASSERT(branch != NULL);
4510 ComparisonInstr* comparison = branch->comparison(); 4545 ComparisonInstr* comparison = branch->comparison();
4511 Value* left = comparison->left(); 4546 Value* left = comparison->left();
4512 PhiInstr* phi = left->definition()->AsPhi(); 4547 PhiInstr* phi = left->definition()->AsPhi();
4513 Value* right = comparison->right(); 4548 Value* right = comparison->right();
4514 ConstantInstr* constant = right->definition()->AsConstant(); 4549 ConstantInstr* constant = right->definition()->AsConstant();
4515 return (phi != NULL) && 4550 return (phi != NULL) &&
4516 (constant != NULL) && 4551 (constant != NULL) &&
4517 (phi->GetBlock() == block) && 4552 (phi->GetBlock() == block) &&
4518 phi->HasOnlyUse(left) && 4553 PhiHasSingleUse(phi, left) &&
4519 constant->HasOnlyUse(right) && 4554 constant->HasOnlyUse(right) &&
4520 (block->next() == constant) && 4555 (block->next() == constant) &&
4521 (constant->next() == branch) && 4556 (constant->next() == branch) &&
4522 (block->phis()->length() == 1); 4557 (block->phis()->length() == 1);
4523 } 4558 }
4524 4559
4525 4560
4526 JoinEntryInstr* BranchSimplifier::ToJoinEntry(TargetEntryInstr* target) { 4561 JoinEntryInstr* BranchSimplifier::ToJoinEntry(TargetEntryInstr* target) {
4527 // Convert a target block into a join block. Branches will be duplicated 4562 // Convert a target block into a join block. Branches will be duplicated
4528 // so the former true and false targets become joins of the control flows 4563 // so the former true and false targets become joins of the control flows
4529 // from all the duplicated branches. 4564 // from all the duplicated branches.
4530 JoinEntryInstr* join = 4565 JoinEntryInstr* join =
4531 new JoinEntryInstr(target->block_id(), target->try_index()); 4566 new JoinEntryInstr(target->block_id(), target->try_index());
4567 join->InheritDeoptTarget(target);
4532 join->LinkTo(target->next()); 4568 join->LinkTo(target->next());
4533 join->set_last_instruction(target->last_instruction()); 4569 join->set_last_instruction(target->last_instruction());
4570 target->UnuseAllInputs();
4534 return join; 4571 return join;
4535 } 4572 }
4536 4573
4537 4574
4538 ConstantInstr* BranchSimplifier::CloneConstant(FlowGraph* flow_graph, 4575 ConstantInstr* BranchSimplifier::CloneConstant(FlowGraph* flow_graph,
4539 ConstantInstr* constant) { 4576 ConstantInstr* constant) {
4540 ConstantInstr* new_constant = new ConstantInstr(constant->value()); 4577 ConstantInstr* new_constant = new ConstantInstr(constant->value());
4541 new_constant->set_ssa_temp_index(flow_graph->alloc_ssa_temp_index()); 4578 new_constant->set_ssa_temp_index(flow_graph->alloc_ssa_temp_index());
4542 return new_constant; 4579 return new_constant;
4543 } 4580 }
4544 4581
4545 4582
4546 BranchInstr* BranchSimplifier::CloneBranch(BranchInstr* branch, 4583 BranchInstr* BranchSimplifier::CloneBranch(BranchInstr* branch,
4547 Value* left, 4584 Value* left,
4548 Value* right) { 4585 Value* right) {
4549 ComparisonInstr* comparison = branch->comparison(); 4586 ComparisonInstr* comparison = branch->comparison();
4550 ComparisonInstr* new_comparison = NULL; 4587 ComparisonInstr* new_comparison = NULL;
4551 if (comparison->IsStrictCompare()) { 4588 if (comparison->IsStrictCompare()) {
4552 new_comparison = new StrictCompareInstr(comparison->kind(), left, right); 4589 new_comparison = new StrictCompareInstr(comparison->kind(), left, right);
4553 } else if (comparison->IsEqualityCompare()) { 4590 } else if (comparison->IsEqualityCompare()) {
4554 new_comparison = 4591 EqualityCompareInstr* equality_compare = comparison->AsEqualityCompare();
4555 new EqualityCompareInstr(comparison->AsEqualityCompare()->token_pos(), 4592 EqualityCompareInstr* new_equality_compare =
4593 new EqualityCompareInstr(equality_compare->token_pos(),
4556 comparison->kind(), 4594 comparison->kind(),
4557 left, 4595 left,
4558 right); 4596 right);
4597 new_equality_compare->set_ic_data(equality_compare->ic_data());
4598 new_comparison = new_equality_compare;
4559 } else { 4599 } else {
4560 ASSERT(comparison->IsRelationalOp()); 4600 ASSERT(comparison->IsRelationalOp());
4561 new_comparison = 4601 RelationalOpInstr* relational_op = comparison->AsRelationalOp();
4562 new RelationalOpInstr(comparison->AsRelationalOp()->token_pos(), 4602 RelationalOpInstr* new_relational_op =
4603 new RelationalOpInstr(relational_op->token_pos(),
4563 comparison->kind(), 4604 comparison->kind(),
4564 left, 4605 left,
4565 right); 4606 right);
4607 new_relational_op->set_ic_data(relational_op->ic_data());
4608 new_comparison = new_relational_op;
4566 } 4609 }
4567 return new BranchInstr(new_comparison, branch->is_checked()); 4610 return new BranchInstr(new_comparison, branch->is_checked());
4568 } 4611 }
4569 4612
4570 4613
4571 void BranchSimplifier::Simplify(FlowGraph* flow_graph) { 4614 void BranchSimplifier::Simplify(FlowGraph* flow_graph) {
4572 // Optimize some branches that test the value of a phi. When it is safe 4615 // Optimize some branches that test the value of a phi. When it is safe
4573 // to do so, push the branch to each of the predecessor blocks. This is 4616 // to do so, push the branch to each of the predecessor blocks. This is
4574 // an optimization when (a) it can avoid materializing a boolean object at 4617 // an optimization when (a) it can avoid materializing a boolean object at
4575 // the phi only to test its value, and (b) it can expose opportunities for 4618 // the phi only to test its value, and (b) it can expose opportunities for
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
4624 4667
4625 // Insert a copy of the constant in all the predecessors. 4668 // Insert a copy of the constant in all the predecessors.
4626 ConstantInstr* new_constant = CloneConstant(flow_graph, constant); 4669 ConstantInstr* new_constant = CloneConstant(flow_graph, constant);
4627 new_constant->InsertBefore(old_goto); 4670 new_constant->InsertBefore(old_goto);
4628 4671
4629 // Replace the goto in each predecessor with a rewritten branch, 4672 // Replace the goto in each predecessor with a rewritten branch,
4630 // rewritten to use the corresponding phi input instead of the phi. 4673 // rewritten to use the corresponding phi input instead of the phi.
4631 Value* new_left = phi->InputAt(i)->Copy(); 4674 Value* new_left = phi->InputAt(i)->Copy();
4632 Value* new_right = new Value(new_constant); 4675 Value* new_right = new Value(new_constant);
4633 BranchInstr* new_branch = CloneBranch(branch, new_left, new_right); 4676 BranchInstr* new_branch = CloneBranch(branch, new_left, new_right);
4677 new_branch->InheritDeoptTarget(old_goto);
4634 new_branch->InsertBefore(old_goto); 4678 new_branch->InsertBefore(old_goto);
4635 new_branch->set_next(NULL); // Detaching the goto from the graph. 4679 new_branch->set_next(NULL); // Detaching the goto from the graph.
4636 old_goto->UnuseAllInputs(); 4680 old_goto->UnuseAllInputs();
4637 4681
4638 // Update the predecessor block. We may have created another 4682 // Update the predecessor block. We may have created another
4639 // instance of the pattern so add it to the worklist if necessary. 4683 // instance of the pattern so add it to the worklist if necessary.
4640 BlockEntryInstr* branch_block = new_branch->GetBlock(); 4684 BlockEntryInstr* branch_block = new_branch->GetBlock();
4641 branch_block->set_last_instruction(new_branch); 4685 branch_block->set_last_instruction(new_branch);
4642 if (branch_block->IsJoinEntry()) worklist.Add(branch_block); 4686 if (branch_block->IsJoinEntry()) worklist.Add(branch_block);
4643 4687
4644 // Connect the branch to the true and false joins, via empty target 4688 // Connect the branch to the true and false joins, via empty target
4645 // blocks. 4689 // blocks.
4646 TargetEntryInstr* true_target = 4690 TargetEntryInstr* true_target =
4647 new TargetEntryInstr(flow_graph->max_block_id() + 1, 4691 new TargetEntryInstr(flow_graph->max_block_id() + 1,
4648 block->try_index()); 4692 block->try_index());
4693 true_target->InheritDeoptTarget(join_true);
4649 TargetEntryInstr* false_target = 4694 TargetEntryInstr* false_target =
4650 new TargetEntryInstr(flow_graph->max_block_id() + 2, 4695 new TargetEntryInstr(flow_graph->max_block_id() + 2,
4651 block->try_index()); 4696 block->try_index());
4697 false_target->InheritDeoptTarget(join_false);
4652 flow_graph->set_max_block_id(flow_graph->max_block_id() + 2); 4698 flow_graph->set_max_block_id(flow_graph->max_block_id() + 2);
4653 *new_branch->true_successor_address() = true_target; 4699 *new_branch->true_successor_address() = true_target;
4654 *new_branch->false_successor_address() = false_target; 4700 *new_branch->false_successor_address() = false_target;
4655 GotoInstr* goto_true = new GotoInstr(join_true); 4701 GotoInstr* goto_true = new GotoInstr(join_true);
4702 goto_true->InheritDeoptTarget(join_true);
4656 true_target->LinkTo(goto_true); 4703 true_target->LinkTo(goto_true);
4657 true_target->set_last_instruction(goto_true); 4704 true_target->set_last_instruction(goto_true);
4658 GotoInstr* goto_false = new GotoInstr(join_false); 4705 GotoInstr* goto_false = new GotoInstr(join_false);
4706 goto_false->InheritDeoptTarget(join_false);
4659 false_target->LinkTo(goto_false); 4707 false_target->LinkTo(goto_false);
4660 false_target->set_last_instruction(goto_false); 4708 false_target->set_last_instruction(goto_false);
4661 } 4709 }
4662 // When all predecessors have been rewritten, the original block is 4710 // When all predecessors have been rewritten, the original block is
4663 // unreachable from the graph. 4711 // unreachable from the graph.
4664 phi->UnuseAllInputs(); 4712 phi->UnuseAllInputs();
4665 branch->UnuseAllInputs(); 4713 branch->UnuseAllInputs();
4714 block->UnuseAllInputs();
4666 } 4715 }
4667 } 4716 }
4668 4717
4669 if (changed) { 4718 if (changed) {
4670 // We may have changed the block order and the dominator tree. 4719 // We may have changed the block order and the dominator tree.
4671 flow_graph->DiscoverBlocks(); 4720 flow_graph->DiscoverBlocks();
4672 GrowableArray<BitVector*> dominance_frontier; 4721 GrowableArray<BitVector*> dominance_frontier;
4673 flow_graph->ComputeDominators(&dominance_frontier); 4722 flow_graph->ComputeDominators(&dominance_frontier);
4674 } 4723 }
4675 } 4724 }
4676 4725
4677 4726
4678 } // namespace dart 4727 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.cc ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698