OLD | NEW |
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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 loop_information_(NULL), | 61 loop_information_(NULL), |
62 predecessors_(2), | 62 predecessors_(2), |
63 dominator_(NULL), | 63 dominator_(NULL), |
64 dominated_blocks_(4), | 64 dominated_blocks_(4), |
65 last_environment_(NULL), | 65 last_environment_(NULL), |
66 argument_count_(-1), | 66 argument_count_(-1), |
67 first_instruction_index_(-1), | 67 first_instruction_index_(-1), |
68 last_instruction_index_(-1), | 68 last_instruction_index_(-1), |
69 deleted_phis_(4), | 69 deleted_phis_(4), |
70 parent_loop_header_(NULL), | 70 parent_loop_header_(NULL), |
71 is_inline_return_target_(false) { } | 71 is_inline_return_target_(false), |
| 72 is_deoptimizing_(false) { } |
72 | 73 |
73 | 74 |
74 void HBasicBlock::AttachLoopInformation() { | 75 void HBasicBlock::AttachLoopInformation() { |
75 ASSERT(!IsLoopHeader()); | 76 ASSERT(!IsLoopHeader()); |
76 loop_information_ = new(zone()) HLoopInformation(this); | 77 loop_information_ = new(zone()) HLoopInformation(this); |
77 } | 78 } |
78 | 79 |
79 | 80 |
80 void HBasicBlock::DetachLoopInformation() { | 81 void HBasicBlock::DetachLoopInformation() { |
81 ASSERT(IsLoopHeader()); | 82 ASSERT(IsLoopHeader()); |
(...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
734 HPhase phase("Assign dominators", this); | 735 HPhase phase("Assign dominators", this); |
735 for (int i = 0; i < blocks_.length(); ++i) { | 736 for (int i = 0; i < blocks_.length(); ++i) { |
736 if (blocks_[i]->IsLoopHeader()) { | 737 if (blocks_[i]->IsLoopHeader()) { |
737 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->first()); | 738 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->first()); |
738 } else { | 739 } else { |
739 for (int j = 0; j < blocks_[i]->predecessors()->length(); ++j) { | 740 for (int j = 0; j < blocks_[i]->predecessors()->length(); ++j) { |
740 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); | 741 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); |
741 } | 742 } |
742 } | 743 } |
743 } | 744 } |
| 745 |
| 746 // Propagate flag marking blocks containing unconditional deoptimize. |
| 747 MarkAsDeoptimizingRecursively(entry_block()); |
744 } | 748 } |
745 | 749 |
746 | 750 |
| 751 // Mark all blocks that are dominated by an unconditional deoptimize. |
| 752 void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) { |
| 753 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { |
| 754 HBasicBlock* dominated = block->dominated_blocks()->at(i); |
| 755 if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing(); |
| 756 MarkAsDeoptimizingRecursively(dominated); |
| 757 } |
| 758 } |
| 759 |
747 void HGraph::EliminateRedundantPhis() { | 760 void HGraph::EliminateRedundantPhis() { |
748 HPhase phase("Redundant phi elimination", this); | 761 HPhase phase("Redundant phi elimination", this); |
749 | 762 |
750 // Worklist of phis that can potentially be eliminated. Initialized with | 763 // Worklist of phis that can potentially be eliminated. Initialized with |
751 // all phi nodes. When elimination of a phi node modifies another phi node | 764 // all phi nodes. When elimination of a phi node modifies another phi node |
752 // the modified phi node is added to the worklist. | 765 // the modified phi node is added to the worklist. |
753 ZoneList<HPhi*> worklist(blocks_.length()); | 766 ZoneList<HPhi*> worklist(blocks_.length()); |
754 for (int i = 0; i < blocks_.length(); ++i) { | 767 for (int i = 0; i < blocks_.length(); ++i) { |
755 worklist.AddAll(*blocks_[i]->phis()); | 768 worklist.AddAll(*blocks_[i]->phis()); |
756 } | 769 } |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
890 va_list arguments; | 903 va_list arguments; |
891 va_start(arguments, msg); | 904 va_start(arguments, msg); |
892 OS::VPrint(msg, arguments); | 905 OS::VPrint(msg, arguments); |
893 va_end(arguments); | 906 va_end(arguments); |
894 } | 907 } |
895 } | 908 } |
896 | 909 |
897 | 910 |
898 void HRangeAnalysis::Analyze() { | 911 void HRangeAnalysis::Analyze() { |
899 HPhase phase("Range analysis", graph_); | 912 HPhase phase("Range analysis", graph_); |
900 Analyze(graph_->blocks()->at(0)); | 913 Analyze(graph_->entry_block()); |
901 } | 914 } |
902 | 915 |
903 | 916 |
904 void HRangeAnalysis::Analyze(HBasicBlock* block) { | 917 void HRangeAnalysis::Analyze(HBasicBlock* block) { |
905 TraceRange("Analyzing block B%d\n", block->block_id()); | 918 TraceRange("Analyzing block B%d\n", block->block_id()); |
906 | 919 |
907 int last_changed_range = changed_ranges_.length() - 1; | 920 int last_changed_range = changed_ranges_.length() - 1; |
908 | 921 |
909 // Infer range based on control flow. | 922 // Infer range based on control flow. |
910 if (block->predecessors()->length() == 1) { | 923 if (block->predecessors()->length() == 1) { |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1348 SparseSet visited_on_paths_; | 1361 SparseSet visited_on_paths_; |
1349 }; | 1362 }; |
1350 | 1363 |
1351 | 1364 |
1352 void HGlobalValueNumberer::Analyze() { | 1365 void HGlobalValueNumberer::Analyze() { |
1353 ComputeBlockSideEffects(); | 1366 ComputeBlockSideEffects(); |
1354 if (FLAG_loop_invariant_code_motion) { | 1367 if (FLAG_loop_invariant_code_motion) { |
1355 LoopInvariantCodeMotion(); | 1368 LoopInvariantCodeMotion(); |
1356 } | 1369 } |
1357 HValueMap* map = new(zone()) HValueMap(); | 1370 HValueMap* map = new(zone()) HValueMap(); |
1358 AnalyzeBlock(graph_->blocks()->at(0), map); | 1371 AnalyzeBlock(graph_->entry_block(), map); |
1359 } | 1372 } |
1360 | 1373 |
1361 | 1374 |
1362 void HGlobalValueNumberer::ComputeBlockSideEffects() { | 1375 void HGlobalValueNumberer::ComputeBlockSideEffects() { |
1363 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { | 1376 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { |
1364 // Compute side effects for the block. | 1377 // Compute side effects for the block. |
1365 HBasicBlock* block = graph_->blocks()->at(i); | 1378 HBasicBlock* block = graph_->blocks()->at(i); |
1366 HInstruction* instr = block->first(); | 1379 HInstruction* instr = block->first(); |
1367 int id = block->block_id(); | 1380 int id = block->block_id(); |
1368 int side_effects = 0; | 1381 int side_effects = 0; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1440 } | 1453 } |
1441 | 1454 |
1442 | 1455 |
1443 bool HGlobalValueNumberer::AllowCodeMotion() { | 1456 bool HGlobalValueNumberer::AllowCodeMotion() { |
1444 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; | 1457 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; |
1445 } | 1458 } |
1446 | 1459 |
1447 | 1460 |
1448 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr, | 1461 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr, |
1449 HBasicBlock* loop_header) { | 1462 HBasicBlock* loop_header) { |
1450 // If we've disabled code motion, don't move any instructions. | 1463 // If we've disabled code motion or we're in a block that unconditionally |
1451 if (!AllowCodeMotion()) return false; | 1464 // deoptimizes, don't move any instructions. |
1452 | 1465 return AllowCodeMotion() && !instr->block()->IsDeoptimizing(); |
1453 // If --aggressive-loop-invariant-motion, move everything except change | |
1454 // instructions. | |
1455 if (FLAG_aggressive_loop_invariant_motion && !instr->IsChange()) { | |
1456 return true; | |
1457 } | |
1458 | |
1459 // Otherwise only move instructions that postdominate the loop header | |
1460 // (i.e. are always executed inside the loop). This is to avoid | |
1461 // unnecessary deoptimizations assuming the loop is executed at least | |
1462 // once. TODO(fschneider): Better type feedback should give us | |
1463 // information about code that was never executed. | |
1464 HBasicBlock* block = instr->block(); | |
1465 bool result = true; | |
1466 if (block != loop_header) { | |
1467 for (int i = 1; i < loop_header->predecessors()->length(); ++i) { | |
1468 bool found = false; | |
1469 HBasicBlock* pred = loop_header->predecessors()->at(i); | |
1470 while (pred != loop_header) { | |
1471 if (pred == block) found = true; | |
1472 pred = pred->dominator(); | |
1473 } | |
1474 if (!found) { | |
1475 result = false; | |
1476 break; | |
1477 } | |
1478 } | |
1479 } | |
1480 return result; | |
1481 } | 1466 } |
1482 | 1467 |
1483 | 1468 |
1484 int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock( | 1469 int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock( |
1485 HBasicBlock* dominator, HBasicBlock* dominated) { | 1470 HBasicBlock* dominator, HBasicBlock* dominated) { |
1486 int side_effects = 0; | 1471 int side_effects = 0; |
1487 for (int i = 0; i < dominated->predecessors()->length(); ++i) { | 1472 for (int i = 0; i < dominated->predecessors()->length(); ++i) { |
1488 HBasicBlock* block = dominated->predecessors()->at(i); | 1473 HBasicBlock* block = dominated->predecessors()->at(i); |
1489 if (dominator->block_id() < block->block_id() && | 1474 if (dominator->block_id() < block->block_id() && |
1490 block->block_id() < dominated->block_id() && | 1475 block->block_id() < dominated->block_id() && |
(...skipping 3356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4847 } | 4832 } |
4848 | 4833 |
4849 | 4834 |
4850 void HGraphBuilder::VisitSub(UnaryOperation* expr) { | 4835 void HGraphBuilder::VisitSub(UnaryOperation* expr) { |
4851 CHECK_ALIVE(VisitForValue(expr->expression())); | 4836 CHECK_ALIVE(VisitForValue(expr->expression())); |
4852 HValue* value = Pop(); | 4837 HValue* value = Pop(); |
4853 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstantMinus1()); | 4838 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstantMinus1()); |
4854 TypeInfo info = oracle()->UnaryType(expr); | 4839 TypeInfo info = oracle()->UnaryType(expr); |
4855 if (info.IsUninitialized()) { | 4840 if (info.IsUninitialized()) { |
4856 AddInstruction(new(zone()) HSoftDeoptimize); | 4841 AddInstruction(new(zone()) HSoftDeoptimize); |
| 4842 current_block()->MarkAsDeoptimizing(); |
4857 info = TypeInfo::Unknown(); | 4843 info = TypeInfo::Unknown(); |
4858 } | 4844 } |
4859 Representation rep = ToRepresentation(info); | 4845 Representation rep = ToRepresentation(info); |
4860 TraceRepresentation(expr->op(), info, instr, rep); | 4846 TraceRepresentation(expr->op(), info, instr, rep); |
4861 instr->AssumeRepresentation(rep); | 4847 instr->AssumeRepresentation(rep); |
4862 ast_context()->ReturnInstruction(instr, expr->id()); | 4848 ast_context()->ReturnInstruction(instr, expr->id()); |
4863 } | 4849 } |
4864 | 4850 |
4865 | 4851 |
4866 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 4852 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
4867 CHECK_ALIVE(VisitForValue(expr->expression())); | 4853 CHECK_ALIVE(VisitForValue(expr->expression())); |
4868 HValue* value = Pop(); | 4854 HValue* value = Pop(); |
4869 TypeInfo info = oracle()->UnaryType(expr); | 4855 TypeInfo info = oracle()->UnaryType(expr); |
4870 if (info.IsUninitialized()) { | 4856 if (info.IsUninitialized()) { |
4871 AddInstruction(new(zone()) HSoftDeoptimize); | 4857 AddInstruction(new(zone()) HSoftDeoptimize); |
| 4858 current_block()->MarkAsDeoptimizing(); |
4872 } | 4859 } |
4873 HInstruction* instr = new(zone()) HBitNot(value); | 4860 HInstruction* instr = new(zone()) HBitNot(value); |
4874 ast_context()->ReturnInstruction(instr, expr->id()); | 4861 ast_context()->ReturnInstruction(instr, expr->id()); |
4875 } | 4862 } |
4876 | 4863 |
4877 | 4864 |
4878 void HGraphBuilder::VisitNot(UnaryOperation* expr) { | 4865 void HGraphBuilder::VisitNot(UnaryOperation* expr) { |
4879 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here. | 4866 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here. |
4880 if (ast_context()->IsTest()) { | 4867 if (ast_context()->IsTest()) { |
4881 TestContext* context = TestContext::cast(ast_context()); | 4868 TestContext* context = TestContext::cast(ast_context()); |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5097 return new(zone()) HStringCharCodeAt(string, checked_index); | 5084 return new(zone()) HStringCharCodeAt(string, checked_index); |
5098 } | 5085 } |
5099 | 5086 |
5100 | 5087 |
5101 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, | 5088 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, |
5102 HValue* left, | 5089 HValue* left, |
5103 HValue* right) { | 5090 HValue* right) { |
5104 TypeInfo info = oracle()->BinaryType(expr); | 5091 TypeInfo info = oracle()->BinaryType(expr); |
5105 if (info.IsUninitialized()) { | 5092 if (info.IsUninitialized()) { |
5106 AddInstruction(new(zone()) HSoftDeoptimize); | 5093 AddInstruction(new(zone()) HSoftDeoptimize); |
| 5094 current_block()->MarkAsDeoptimizing(); |
5107 info = TypeInfo::Unknown(); | 5095 info = TypeInfo::Unknown(); |
5108 } | 5096 } |
5109 HInstruction* instr = NULL; | 5097 HInstruction* instr = NULL; |
5110 switch (expr->op()) { | 5098 switch (expr->op()) { |
5111 case Token::ADD: | 5099 case Token::ADD: |
5112 if (info.IsString()) { | 5100 if (info.IsString()) { |
5113 AddInstruction(new(zone()) HCheckNonSmi(left)); | 5101 AddInstruction(new(zone()) HCheckNonSmi(left)); |
5114 AddInstruction(HCheckInstanceType::NewIsString(left)); | 5102 AddInstruction(HCheckInstanceType::NewIsString(left)); |
5115 AddInstruction(new(zone()) HCheckNonSmi(right)); | 5103 AddInstruction(new(zone()) HCheckNonSmi(right)); |
5116 AddInstruction(HCheckInstanceType::NewIsString(right)); | 5104 AddInstruction(HCheckInstanceType::NewIsString(right)); |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5366 Handle<String>::cast(right_literal->handle())); | 5354 Handle<String>::cast(right_literal->handle())); |
5367 instr->set_position(expr->position()); | 5355 instr->set_position(expr->position()); |
5368 ast_context()->ReturnInstruction(instr, expr->id()); | 5356 ast_context()->ReturnInstruction(instr, expr->id()); |
5369 return; | 5357 return; |
5370 } | 5358 } |
5371 | 5359 |
5372 TypeInfo type_info = oracle()->CompareType(expr); | 5360 TypeInfo type_info = oracle()->CompareType(expr); |
5373 // Check if this expression was ever executed according to type feedback. | 5361 // Check if this expression was ever executed according to type feedback. |
5374 if (type_info.IsUninitialized()) { | 5362 if (type_info.IsUninitialized()) { |
5375 AddInstruction(new(zone()) HSoftDeoptimize); | 5363 AddInstruction(new(zone()) HSoftDeoptimize); |
| 5364 current_block()->MarkAsDeoptimizing(); |
5376 type_info = TypeInfo::Unknown(); | 5365 type_info = TypeInfo::Unknown(); |
5377 } | 5366 } |
5378 | 5367 |
5379 CHECK_ALIVE(VisitForValue(expr->left())); | 5368 CHECK_ALIVE(VisitForValue(expr->left())); |
5380 CHECK_ALIVE(VisitForValue(expr->right())); | 5369 CHECK_ALIVE(VisitForValue(expr->right())); |
5381 | 5370 |
5382 HValue* right = Pop(); | 5371 HValue* right = Pop(); |
5383 HValue* left = Pop(); | 5372 HValue* left = Pop(); |
5384 Token::Value op = expr->op(); | 5373 Token::Value op = expr->op(); |
5385 | 5374 |
(...skipping 1023 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6409 } | 6398 } |
6410 } | 6399 } |
6411 | 6400 |
6412 #ifdef DEBUG | 6401 #ifdef DEBUG |
6413 if (graph_ != NULL) graph_->Verify(); | 6402 if (graph_ != NULL) graph_->Verify(); |
6414 if (allocator_ != NULL) allocator_->Verify(); | 6403 if (allocator_ != NULL) allocator_->Verify(); |
6415 #endif | 6404 #endif |
6416 } | 6405 } |
6417 | 6406 |
6418 } } // namespace v8::internal | 6407 } } // namespace v8::internal |
OLD | NEW |