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

Side by Side Diff: src/hydrogen.cc

Issue 6366002: Begin changing Hydrogen branch instructions. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge/build/ia32
Patch Set: Rebase to HEAD> Created 9 years, 11 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 | « no previous file | src/hydrogen-instructions.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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 } 498 }
499 499
500 500
501 HConstant* HGraph::GetConstantFalse() { 501 HConstant* HGraph::GetConstantFalse() {
502 return GetConstant(&constant_false_, Heap::false_value()); 502 return GetConstant(&constant_false_, Heap::false_value());
503 } 503 }
504 504
505 505
506 void HSubgraph::AppendOptional(HSubgraph* graph, 506 void HSubgraph::AppendOptional(HSubgraph* graph,
507 bool on_true_branch, 507 bool on_true_branch,
508 HValue* boolean_value) { 508 HValue* value) {
509 ASSERT(HasExit() && graph->HasExit()); 509 ASSERT(HasExit() && graph->HasExit());
510 HBasicBlock* other_block = graph_->CreateBasicBlock(); 510 HBasicBlock* other_block = graph_->CreateBasicBlock();
511 HBasicBlock* join_block = graph_->CreateBasicBlock(); 511 HBasicBlock* join_block = graph_->CreateBasicBlock();
512 512
513 HBasicBlock* true_branch = other_block; 513 HTest* test = on_true_branch
514 HBasicBlock* false_branch = graph->entry_block(); 514 ? new HTest(value, graph->entry_block(), other_block)
515 if (on_true_branch) { 515 : new HTest(value, other_block, graph->entry_block());
516 true_branch = graph->entry_block(); 516 exit_block_->Finish(test);
517 false_branch = other_block;
518 }
519
520 exit_block_->Finish(new HBranch(true_branch, false_branch, boolean_value));
521 other_block->Goto(join_block); 517 other_block->Goto(join_block);
522 graph->exit_block()->Goto(join_block); 518 graph->exit_block()->Goto(join_block);
523 exit_block_ = join_block; 519 exit_block_ = join_block;
524 } 520 }
525 521
526 522
527 void HSubgraph::AppendJoin(HSubgraph* then_graph, 523 void HSubgraph::AppendJoin(HSubgraph* then_graph,
528 HSubgraph* else_graph, 524 HSubgraph* else_graph,
529 AstNode* node) { 525 AstNode* node) {
530 if (then_graph->HasExit() && else_graph->HasExit()) { 526 if (then_graph->HasExit() && else_graph->HasExit()) {
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
928 924
929 class HRangeAnalysis BASE_EMBEDDED { 925 class HRangeAnalysis BASE_EMBEDDED {
930 public: 926 public:
931 explicit HRangeAnalysis(HGraph* graph) : graph_(graph), changed_ranges_(16) {} 927 explicit HRangeAnalysis(HGraph* graph) : graph_(graph), changed_ranges_(16) {}
932 928
933 void Analyze(); 929 void Analyze();
934 930
935 private: 931 private:
936 void TraceRange(const char* msg, ...); 932 void TraceRange(const char* msg, ...);
937 void Analyze(HBasicBlock* block); 933 void Analyze(HBasicBlock* block);
938 void InferControlFlowRange(HBranch* branch, HBasicBlock* dest); 934 void InferControlFlowRange(HTest* test, HBasicBlock* dest);
939 void InferControlFlowRange(Token::Value op, HValue* value, HValue* other); 935 void InferControlFlowRange(Token::Value op, HValue* value, HValue* other);
940 void InferPhiRange(HPhi* phi); 936 void InferPhiRange(HPhi* phi);
941 void InferRange(HValue* value); 937 void InferRange(HValue* value);
942 void RollBackTo(int index); 938 void RollBackTo(int index);
943 void AddRange(HValue* value, Range* range); 939 void AddRange(HValue* value, Range* range);
944 940
945 HGraph* graph_; 941 HGraph* graph_;
946 ZoneList<HValue*> changed_ranges_; 942 ZoneList<HValue*> changed_ranges_;
947 }; 943 };
948 944
(...skipping 15 matching lines...) Expand all
964 960
965 961
966 void HRangeAnalysis::Analyze(HBasicBlock* block) { 962 void HRangeAnalysis::Analyze(HBasicBlock* block) {
967 TraceRange("Analyzing block B%d\n", block->block_id()); 963 TraceRange("Analyzing block B%d\n", block->block_id());
968 964
969 int last_changed_range = changed_ranges_.length() - 1; 965 int last_changed_range = changed_ranges_.length() - 1;
970 966
971 // Infer range based on control flow. 967 // Infer range based on control flow.
972 if (block->predecessors()->length() == 1) { 968 if (block->predecessors()->length() == 1) {
973 HBasicBlock* pred = block->predecessors()->first(); 969 HBasicBlock* pred = block->predecessors()->first();
974 if (pred->end()->IsBranch()) { 970 if (pred->end()->IsTest()) {
975 InferControlFlowRange(HBranch::cast(pred->end()), block); 971 InferControlFlowRange(HTest::cast(pred->end()), block);
976 } 972 }
977 } 973 }
978 974
979 // Process phi instructions. 975 // Process phi instructions.
980 for (int i = 0; i < block->phis()->length(); ++i) { 976 for (int i = 0; i < block->phis()->length(); ++i) {
981 HPhi* phi = block->phis()->at(i); 977 HPhi* phi = block->phis()->at(i);
982 InferPhiRange(phi); 978 InferPhiRange(phi);
983 } 979 }
984 980
985 // Go through all instructions of the current block. 981 // Go through all instructions of the current block.
986 HInstruction* instr = block->first(); 982 HInstruction* instr = block->first();
987 while (instr != block->end()) { 983 while (instr != block->end()) {
988 InferRange(instr); 984 InferRange(instr);
989 instr = instr->next(); 985 instr = instr->next();
990 } 986 }
991 987
992 // Continue analysis in all dominated blocks. 988 // Continue analysis in all dominated blocks.
993 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { 989 for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
994 Analyze(block->dominated_blocks()->at(i)); 990 Analyze(block->dominated_blocks()->at(i));
995 } 991 }
996 992
997 RollBackTo(last_changed_range); 993 RollBackTo(last_changed_range);
998 } 994 }
999 995
1000 996
1001 void HRangeAnalysis::InferControlFlowRange(HBranch* branch, HBasicBlock* dest) { 997 void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) {
1002 ASSERT(branch->FirstSuccessor() == dest || branch->SecondSuccessor() == dest); 998 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
1003 ASSERT(branch->FirstSuccessor() != dest || branch->SecondSuccessor() != dest); 999 if (test->value()->IsCompare()) {
1004 1000 HCompare* compare = HCompare::cast(test->value());
1005 if (branch->value()->IsCompare()) {
1006 HCompare* compare = HCompare::cast(branch->value());
1007 Token::Value op = compare->token(); 1001 Token::Value op = compare->token();
1008 if (branch->SecondSuccessor() == dest) { 1002 if (test->SecondSuccessor() == dest) {
1009 op = Token::NegateCompareOp(op); 1003 op = Token::NegateCompareOp(op);
1010 } 1004 }
1011 Token::Value inverted_op = Token::InvertCompareOp(op); 1005 Token::Value inverted_op = Token::InvertCompareOp(op);
1012 InferControlFlowRange(op, compare->left(), compare->right()); 1006 InferControlFlowRange(op, compare->left(), compare->right());
1013 InferControlFlowRange(inverted_op, compare->right(), compare->left()); 1007 InferControlFlowRange(inverted_op, compare->right(), compare->left());
1014 } 1008 }
1015 } 1009 }
1016 1010
1017 1011
1018 // We know that value [op] other. Use this information to update the range on 1012 // We know that value [op] other. Use this information to update the range on
(...skipping 1042 matching lines...) Expand 10 before | Expand all | Expand 10 after
2061 2055
2062 2056
2063 void TestContext::BuildBranch(HValue* value) { 2057 void TestContext::BuildBranch(HValue* value) {
2064 // We expect the graph to be in edge-split form: there is no edge that 2058 // We expect the graph to be in edge-split form: there is no edge that
2065 // connects a branch node to a join node. We conservatively ensure that 2059 // connects a branch node to a join node. We conservatively ensure that
2066 // property by always adding an empty block on the outgoing edges of this 2060 // property by always adding an empty block on the outgoing edges of this
2067 // branch. 2061 // branch.
2068 HGraphBuilder* builder = owner(); 2062 HGraphBuilder* builder = owner();
2069 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 2063 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2070 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 2064 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
2071 HBranch* branch = new HBranch(empty_true, empty_false, value); 2065 HTest* test = new HTest(value, empty_true, empty_false);
2072 builder->CurrentBlock()->Finish(branch); 2066 builder->CurrentBlock()->Finish(test);
2073 2067
2074 HValue* const no_return_value = NULL; 2068 HValue* const no_return_value = NULL;
2075 HBasicBlock* true_target = if_true(); 2069 HBasicBlock* true_target = if_true();
2076 if (true_target->IsInlineReturnTarget()) { 2070 if (true_target->IsInlineReturnTarget()) {
2077 empty_true->AddLeaveInlined(no_return_value, true_target); 2071 empty_true->AddLeaveInlined(no_return_value, true_target);
2078 } else { 2072 } else {
2079 empty_true->Goto(true_target); 2073 empty_true->Goto(true_target);
2080 } 2074 }
2081 2075
2082 HBasicBlock* false_target = if_false(); 2076 HBasicBlock* false_target = if_false();
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after
2590 CaseClause* clause = clauses->at(i); 2584 CaseClause* clause = clauses->at(i);
2591 if (clause->is_default()) continue; 2585 if (clause->is_default()) continue;
2592 2586
2593 // Finish the previous graph by connecting it to the current. 2587 // Finish the previous graph by connecting it to the current.
2594 HSubgraph* subgraph = compare_graphs.at(i); 2588 HSubgraph* subgraph = compare_graphs.at(i);
2595 if (prev_compare_inst == NULL) { 2589 if (prev_compare_inst == NULL) {
2596 ASSERT(prev_graph == current_subgraph_); 2590 ASSERT(prev_graph == current_subgraph_);
2597 prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block())); 2591 prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block()));
2598 } else { 2592 } else {
2599 HBasicBlock* empty = graph()->CreateBasicBlock(); 2593 HBasicBlock* empty = graph()->CreateBasicBlock();
2600 prev_graph->exit_block()->Finish(new HBranch(empty, 2594 prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
2601 subgraph->entry_block(), 2595 empty,
2602 prev_compare_inst)); 2596 subgraph->entry_block()));
2603 } 2597 }
2604 2598
2605 // Build instructions for current subgraph. 2599 // Build instructions for current subgraph.
2606 ASSERT(clause->IsSmiCompare()); 2600 ASSERT(clause->IsSmiCompare());
2607 prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause); 2601 prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause);
2608 if (HasStackOverflow()) return; 2602 if (HasStackOverflow()) return;
2609 2603
2610 prev_graph = subgraph; 2604 prev_graph = subgraph;
2611 } 2605 }
2612 2606
2613 // Finish last comparison if there was at least one comparison. 2607 // Finish last comparison if there was at least one comparison.
2614 // last_false_block is the (empty) false-block of the last comparison. If 2608 // last_false_block is the (empty) false-block of the last comparison. If
2615 // there are no comparisons at all (a single default clause), it is just 2609 // there are no comparisons at all (a single default clause), it is just
2616 // the last block of the current subgraph. 2610 // the last block of the current subgraph.
2617 HBasicBlock* last_false_block = current_subgraph_->exit_block(); 2611 HBasicBlock* last_false_block = current_subgraph_->exit_block();
2618 if (prev_graph != current_subgraph_) { 2612 if (prev_graph != current_subgraph_) {
2619 last_false_block = graph()->CreateBasicBlock(); 2613 last_false_block = graph()->CreateBasicBlock();
2620 HBasicBlock* empty = graph()->CreateBasicBlock(); 2614 HBasicBlock* empty = graph()->CreateBasicBlock();
2621 prev_graph->exit_block()->Finish(new HBranch(empty, 2615 prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
2622 last_false_block, 2616 empty,
2623 prev_compare_inst)); 2617 last_false_block));
2624 } 2618 }
2625 2619
2626 // If we have a non-smi compare clause, we deoptimize after trying 2620 // If we have a non-smi compare clause, we deoptimize after trying
2627 // all the previous compares. 2621 // all the previous compares.
2628 if (num_smi_clauses < num_clauses) { 2622 if (num_smi_clauses < num_clauses) {
2629 last_false_block->Finish(new HDeoptimize); 2623 last_false_block->Finish(new HDeoptimize);
2630 } 2624 }
2631 2625
2632 // Build statement blocks, connect them to their comparison block and 2626 // Build statement blocks, connect them to their comparison block and
2633 // to the previous statement block, if there is a fall-through. 2627 // to the previous statement block, if there is a fall-through.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2696 return statement->OsrEntryId() == info()->osr_ast_id(); 2690 return statement->OsrEntryId() == info()->osr_ast_id();
2697 } 2691 }
2698 2692
2699 2693
2700 void HSubgraph::PreProcessOsrEntry(IterationStatement* statement) { 2694 void HSubgraph::PreProcessOsrEntry(IterationStatement* statement) {
2701 if (!graph()->HasOsrEntryAt(statement)) return; 2695 if (!graph()->HasOsrEntryAt(statement)) return;
2702 2696
2703 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); 2697 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
2704 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); 2698 HBasicBlock* osr_entry = graph()->CreateBasicBlock();
2705 HValue* true_value = graph()->GetConstantTrue(); 2699 HValue* true_value = graph()->GetConstantTrue();
2706 HBranch* branch = new HBranch(non_osr_entry, osr_entry, true_value); 2700 HTest* test = new HTest(true_value, non_osr_entry, osr_entry);
2707 exit_block()->Finish(branch); 2701 exit_block()->Finish(test);
2708 2702
2709 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); 2703 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
2710 non_osr_entry->Goto(loop_predecessor); 2704 non_osr_entry->Goto(loop_predecessor);
2711 2705
2712 int osr_entry_id = statement->OsrEntryId(); 2706 int osr_entry_id = statement->OsrEntryId();
2713 // We want the correct environment at the OsrEntry instruction. Build 2707 // We want the correct environment at the OsrEntry instruction. Build
2714 // it explicitly. The expression stack should be empty. 2708 // it explicitly. The expression stack should be empty.
2715 int count = osr_entry->last_environment()->length(); 2709 int count = osr_entry->last_environment()->length();
2716 ASSERT(count == (osr_entry->last_environment()->parameter_count() + 2710 ASSERT(count == (osr_entry->last_environment()->parameter_count() +
2717 osr_entry->last_environment()->local_count())); 2711 osr_entry->last_environment()->local_count()));
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
3099 3093
3100 // Build map compare subgraphs for all but the first map. 3094 // Build map compare subgraphs for all but the first map.
3101 ZoneList<HSubgraph*> map_compare_subgraphs(maps->length() - 1); 3095 ZoneList<HSubgraph*> map_compare_subgraphs(maps->length() - 1);
3102 for (int i = maps->length() - 1; i > 0; --i) { 3096 for (int i = maps->length() - 1; i > 0; --i) {
3103 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3097 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3104 SubgraphScope scope(this, subgraph); 3098 SubgraphScope scope(this, subgraph);
3105 HSubgraph* else_subgraph = 3099 HSubgraph* else_subgraph =
3106 (i == (maps->length() - 1)) 3100 (i == (maps->length() - 1))
3107 ? subgraphs->last() 3101 ? subgraphs->last()
3108 : map_compare_subgraphs.last(); 3102 : map_compare_subgraphs.last();
3109 current_subgraph_->exit_block()->Finish( 3103 HCompareMap* compare = new HCompareMap(receiver,
3110 new HCompareMapAndBranch(receiver, 3104 maps->at(i),
3111 maps->at(i), 3105 subgraphs->at(i)->entry_block(),
3112 subgraphs->at(i)->entry_block(), 3106 else_subgraph->entry_block());
3113 else_subgraph->entry_block())); 3107 current_subgraph_->exit_block()->Finish(compare);
3114 map_compare_subgraphs.Add(subgraph); 3108 map_compare_subgraphs.Add(subgraph);
3115 } 3109 }
3116 3110
3117 // Generate first map check to end the current block. 3111 // Generate first map check to end the current block.
3118 AddInstruction(new HCheckNonSmi(receiver)); 3112 AddInstruction(new HCheckNonSmi(receiver));
3119 HSubgraph* else_subgraph = 3113 HSubgraph* else_subgraph =
3120 (maps->length() == 1) ? subgraphs->at(1) : map_compare_subgraphs.last(); 3114 (maps->length() == 1) ? subgraphs->at(1) : map_compare_subgraphs.last();
3121 current_subgraph_->exit_block()->Finish( 3115 HCompareMap* compare = new HCompareMap(receiver,
3122 new HCompareMapAndBranch(receiver, 3116 Handle<Map>(maps->first()),
3123 Handle<Map>(maps->first()), 3117 subgraphs->first()->entry_block(),
3124 subgraphs->first()->entry_block(), 3118 else_subgraph->entry_block());
3125 else_subgraph->entry_block())); 3119 current_subgraph_->exit_block()->Finish(compare);
3126 3120
3127 // Join all the call subgraphs in a new basic block and make 3121 // Join all the call subgraphs in a new basic block and make
3128 // this basic block the current basic block. 3122 // this basic block the current basic block.
3129 HBasicBlock* join_block = graph_->CreateBasicBlock(); 3123 HBasicBlock* join_block = graph_->CreateBasicBlock();
3130 for (int i = 0; i < subgraphs->length(); ++i) { 3124 for (int i = 0; i < subgraphs->length(); ++i) {
3131 HSubgraph* subgraph = subgraphs->at(i); 3125 HSubgraph* subgraph = subgraphs->at(i);
3132 if (subgraph->HasExit()) { 3126 if (subgraph->HasExit()) {
3133 // In an effect context the value of the type switch is not needed. 3127 // In an effect context the value of the type switch is not needed.
3134 // There is no need to merge it at the join block only to discard it. 3128 // There is no need to merge it at the join block only to discard it.
3135 HBasicBlock* subgraph_exit = subgraph->exit_block(); 3129 HBasicBlock* subgraph_exit = subgraph->exit_block();
(...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after
4069 ASSERT(function_return_ != NULL); 4063 ASSERT(function_return_ != NULL);
4070 body->exit_block()->AddLeaveInlined(return_value, function_return_); 4064 body->exit_block()->AddLeaveInlined(return_value, function_return_);
4071 } else { 4065 } else {
4072 // The graph builder assumes control can reach both branches of a 4066 // The graph builder assumes control can reach both branches of a
4073 // test, so we materialize the undefined value and test it rather than 4067 // test, so we materialize the undefined value and test it rather than
4074 // simply jumping to the false target. 4068 // simply jumping to the false target.
4075 // 4069 //
4076 // TODO(3168478): refactor to avoid this. 4070 // TODO(3168478): refactor to avoid this.
4077 HBasicBlock* empty_true = graph()->CreateBasicBlock(); 4071 HBasicBlock* empty_true = graph()->CreateBasicBlock();
4078 HBasicBlock* empty_false = graph()->CreateBasicBlock(); 4072 HBasicBlock* empty_false = graph()->CreateBasicBlock();
4079 HBranch* branch = 4073 HTest* test = new HTest(return_value, empty_true, empty_false);
4080 new HBranch(empty_true, empty_false, return_value); 4074 body->exit_block()->Finish(test);
4081 body->exit_block()->Finish(branch);
4082 4075
4083 HValue* const no_return_value = NULL; 4076 HValue* const no_return_value = NULL;
4084 empty_true->AddLeaveInlined(no_return_value, test_context->if_true()); 4077 empty_true->AddLeaveInlined(no_return_value, test_context->if_true());
4085 empty_false->AddLeaveInlined(no_return_value, test_context->if_false()); 4078 empty_false->AddLeaveInlined(no_return_value, test_context->if_false());
4086 } 4079 }
4087 body->set_exit_block(NULL); 4080 body->set_exit_block(NULL);
4088 } 4081 }
4089 4082
4090 // Record the environment at the inlined function call. 4083 // Record the environment at the inlined function call.
4091 AddSimulate(expr->ReturnId()); 4084 AddSimulate(expr->ReturnId());
(...skipping 1775 matching lines...) Expand 10 before | Expand all | Expand 10 after
5867 } 5860 }
5868 } 5861 }
5869 5862
5870 #ifdef DEBUG 5863 #ifdef DEBUG
5871 if (graph_ != NULL) graph_->Verify(); 5864 if (graph_ != NULL) graph_->Verify();
5872 if (allocator_ != NULL) allocator_->Verify(); 5865 if (allocator_ != NULL) allocator_->Verify();
5873 #endif 5866 #endif
5874 } 5867 }
5875 5868
5876 } } // namespace v8::internal 5869 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698