| 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 |