| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 19 matching lines...) Expand all Loading... |
| 30 #include <algorithm> | 30 #include <algorithm> |
| 31 | 31 |
| 32 #include "v8.h" | 32 #include "v8.h" |
| 33 #include "codegen.h" | 33 #include "codegen.h" |
| 34 #include "full-codegen.h" | 34 #include "full-codegen.h" |
| 35 #include "hashmap.h" | 35 #include "hashmap.h" |
| 36 #include "hydrogen-environment-liveness.h" | 36 #include "hydrogen-environment-liveness.h" |
| 37 #include "hydrogen-escape-analysis.h" | 37 #include "hydrogen-escape-analysis.h" |
| 38 #include "hydrogen-infer-representation.h" | 38 #include "hydrogen-infer-representation.h" |
| 39 #include "hydrogen-gvn.h" | 39 #include "hydrogen-gvn.h" |
| 40 #include "hydrogen-range-analysis.h" |
| 40 #include "lithium-allocator.h" | 41 #include "lithium-allocator.h" |
| 41 #include "parser.h" | 42 #include "parser.h" |
| 42 #include "scopeinfo.h" | 43 #include "scopeinfo.h" |
| 43 #include "scopes.h" | 44 #include "scopes.h" |
| 44 #include "stub-cache.h" | 45 #include "stub-cache.h" |
| 45 #include "typing.h" | 46 #include "typing.h" |
| 46 | 47 |
| 47 #if V8_TARGET_ARCH_IA32 | 48 #if V8_TARGET_ARCH_IA32 |
| 48 #include "ia32/lithium-codegen-ia32.h" | 49 #include "ia32/lithium-codegen-ia32.h" |
| 49 #elif V8_TARGET_ARCH_X64 | 50 #elif V8_TARGET_ARCH_X64 |
| (...skipping 2510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2560 if (!in_worklist.Contains(use->id())) { | 2561 if (!in_worklist.Contains(use->id())) { |
| 2561 in_worklist.Add(use->id()); | 2562 in_worklist.Add(use->id()); |
| 2562 worklist->Add(use, zone()); | 2563 worklist->Add(use, zone()); |
| 2563 } | 2564 } |
| 2564 } | 2565 } |
| 2565 } | 2566 } |
| 2566 } | 2567 } |
| 2567 } | 2568 } |
| 2568 | 2569 |
| 2569 | 2570 |
| 2570 class HRangeAnalysis BASE_EMBEDDED { | |
| 2571 public: | |
| 2572 explicit HRangeAnalysis(HGraph* graph) : | |
| 2573 graph_(graph), zone_(graph->zone()), changed_ranges_(16, zone_) { } | |
| 2574 | |
| 2575 void Analyze(); | |
| 2576 | |
| 2577 private: | |
| 2578 void TraceRange(const char* msg, ...); | |
| 2579 void Analyze(HBasicBlock* block); | |
| 2580 void InferControlFlowRange(HCompareIDAndBranch* test, HBasicBlock* dest); | |
| 2581 void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other); | |
| 2582 void InferRange(HValue* value); | |
| 2583 void RollBackTo(int index); | |
| 2584 void AddRange(HValue* value, Range* range); | |
| 2585 | |
| 2586 HGraph* graph_; | |
| 2587 Zone* zone_; | |
| 2588 ZoneList<HValue*> changed_ranges_; | |
| 2589 }; | |
| 2590 | |
| 2591 | |
| 2592 void HRangeAnalysis::TraceRange(const char* msg, ...) { | |
| 2593 if (FLAG_trace_range) { | |
| 2594 va_list arguments; | |
| 2595 va_start(arguments, msg); | |
| 2596 OS::VPrint(msg, arguments); | |
| 2597 va_end(arguments); | |
| 2598 } | |
| 2599 } | |
| 2600 | |
| 2601 | |
| 2602 void HRangeAnalysis::Analyze() { | |
| 2603 HPhase phase("H_Range analysis", graph_); | |
| 2604 Analyze(graph_->entry_block()); | |
| 2605 } | |
| 2606 | |
| 2607 | |
| 2608 void HRangeAnalysis::Analyze(HBasicBlock* block) { | |
| 2609 TraceRange("Analyzing block B%d\n", block->block_id()); | |
| 2610 | |
| 2611 int last_changed_range = changed_ranges_.length() - 1; | |
| 2612 | |
| 2613 // Infer range based on control flow. | |
| 2614 if (block->predecessors()->length() == 1) { | |
| 2615 HBasicBlock* pred = block->predecessors()->first(); | |
| 2616 if (pred->end()->IsCompareIDAndBranch()) { | |
| 2617 InferControlFlowRange(HCompareIDAndBranch::cast(pred->end()), block); | |
| 2618 } | |
| 2619 } | |
| 2620 | |
| 2621 // Process phi instructions. | |
| 2622 for (int i = 0; i < block->phis()->length(); ++i) { | |
| 2623 HPhi* phi = block->phis()->at(i); | |
| 2624 InferRange(phi); | |
| 2625 } | |
| 2626 | |
| 2627 // Go through all instructions of the current block. | |
| 2628 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { | |
| 2629 InferRange(it.Current()); | |
| 2630 } | |
| 2631 | |
| 2632 // Continue analysis in all dominated blocks. | |
| 2633 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { | |
| 2634 Analyze(block->dominated_blocks()->at(i)); | |
| 2635 } | |
| 2636 | |
| 2637 RollBackTo(last_changed_range); | |
| 2638 } | |
| 2639 | |
| 2640 | |
| 2641 void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test, | |
| 2642 HBasicBlock* dest) { | |
| 2643 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); | |
| 2644 if (test->representation().IsSmiOrInteger32()) { | |
| 2645 Token::Value op = test->token(); | |
| 2646 if (test->SecondSuccessor() == dest) { | |
| 2647 op = Token::NegateCompareOp(op); | |
| 2648 } | |
| 2649 Token::Value inverted_op = Token::ReverseCompareOp(op); | |
| 2650 UpdateControlFlowRange(op, test->left(), test->right()); | |
| 2651 UpdateControlFlowRange(inverted_op, test->right(), test->left()); | |
| 2652 } | |
| 2653 } | |
| 2654 | |
| 2655 | |
| 2656 // We know that value [op] other. Use this information to update the range on | |
| 2657 // value. | |
| 2658 void HRangeAnalysis::UpdateControlFlowRange(Token::Value op, | |
| 2659 HValue* value, | |
| 2660 HValue* other) { | |
| 2661 Range temp_range; | |
| 2662 Range* range = other->range() != NULL ? other->range() : &temp_range; | |
| 2663 Range* new_range = NULL; | |
| 2664 | |
| 2665 TraceRange("Control flow range infer %d %s %d\n", | |
| 2666 value->id(), | |
| 2667 Token::Name(op), | |
| 2668 other->id()); | |
| 2669 | |
| 2670 if (op == Token::EQ || op == Token::EQ_STRICT) { | |
| 2671 // The same range has to apply for value. | |
| 2672 new_range = range->Copy(zone_); | |
| 2673 } else if (op == Token::LT || op == Token::LTE) { | |
| 2674 new_range = range->CopyClearLower(zone_); | |
| 2675 if (op == Token::LT) { | |
| 2676 new_range->AddConstant(-1); | |
| 2677 } | |
| 2678 } else if (op == Token::GT || op == Token::GTE) { | |
| 2679 new_range = range->CopyClearUpper(zone_); | |
| 2680 if (op == Token::GT) { | |
| 2681 new_range->AddConstant(1); | |
| 2682 } | |
| 2683 } | |
| 2684 | |
| 2685 if (new_range != NULL && !new_range->IsMostGeneric()) { | |
| 2686 AddRange(value, new_range); | |
| 2687 } | |
| 2688 } | |
| 2689 | |
| 2690 | |
| 2691 void HRangeAnalysis::InferRange(HValue* value) { | |
| 2692 ASSERT(!value->HasRange()); | |
| 2693 if (!value->representation().IsNone()) { | |
| 2694 value->ComputeInitialRange(zone_); | |
| 2695 Range* range = value->range(); | |
| 2696 TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n", | |
| 2697 value->id(), | |
| 2698 value->Mnemonic(), | |
| 2699 range->lower(), | |
| 2700 range->upper()); | |
| 2701 } | |
| 2702 } | |
| 2703 | |
| 2704 | |
| 2705 void HRangeAnalysis::RollBackTo(int index) { | |
| 2706 for (int i = index + 1; i < changed_ranges_.length(); ++i) { | |
| 2707 changed_ranges_[i]->RemoveLastAddedRange(); | |
| 2708 } | |
| 2709 changed_ranges_.Rewind(index + 1); | |
| 2710 } | |
| 2711 | |
| 2712 | |
| 2713 void HRangeAnalysis::AddRange(HValue* value, Range* range) { | |
| 2714 Range* original_range = value->range(); | |
| 2715 value->AddNewRange(range, zone_); | |
| 2716 changed_ranges_.Add(value, zone_); | |
| 2717 Range* new_range = value->range(); | |
| 2718 TraceRange("Updated range of %d set to [%d,%d]\n", | |
| 2719 value->id(), | |
| 2720 new_range->lower(), | |
| 2721 new_range->upper()); | |
| 2722 if (original_range != NULL) { | |
| 2723 TraceRange("Original range was [%d,%d]\n", | |
| 2724 original_range->lower(), | |
| 2725 original_range->upper()); | |
| 2726 } | |
| 2727 TraceRange("New information was [%d,%d]\n", | |
| 2728 range->lower(), | |
| 2729 range->upper()); | |
| 2730 } | |
| 2731 | |
| 2732 | |
| 2733 class HStackCheckEliminator BASE_EMBEDDED { | 2571 class HStackCheckEliminator BASE_EMBEDDED { |
| 2734 public: | 2572 public: |
| 2735 explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { } | 2573 explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { } |
| 2736 | 2574 |
| 2737 void Process(); | 2575 void Process(); |
| 2738 | 2576 |
| 2739 private: | 2577 private: |
| 2740 HGraph* graph_; | 2578 HGraph* graph_; |
| 2741 }; | 2579 }; |
| 2742 | 2580 |
| (...skipping 1072 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3815 | 3653 |
| 3816 if (FLAG_use_canonicalizing) Canonicalize(); | 3654 if (FLAG_use_canonicalizing) Canonicalize(); |
| 3817 | 3655 |
| 3818 if (FLAG_use_escape_analysis) { | 3656 if (FLAG_use_escape_analysis) { |
| 3819 HEscapeAnalysis escape_analysis(this); | 3657 HEscapeAnalysis escape_analysis(this); |
| 3820 escape_analysis.Analyze(); | 3658 escape_analysis.Analyze(); |
| 3821 } | 3659 } |
| 3822 | 3660 |
| 3823 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); | 3661 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); |
| 3824 | 3662 |
| 3825 if (FLAG_use_range) { | 3663 if (FLAG_use_range) Run<HRangeAnalysisPhase>(); |
| 3826 HRangeAnalysis range_analysis(this); | 3664 |
| 3827 range_analysis.Analyze(); | |
| 3828 } | |
| 3829 ComputeMinusZeroChecks(); | 3665 ComputeMinusZeroChecks(); |
| 3830 | 3666 |
| 3831 // Eliminate redundant stack checks on backwards branches. | 3667 // Eliminate redundant stack checks on backwards branches. |
| 3832 HStackCheckEliminator sce(this); | 3668 HStackCheckEliminator sce(this); |
| 3833 sce.Process(); | 3669 sce.Process(); |
| 3834 | 3670 |
| 3835 if (FLAG_idefs) SetupInformativeDefinitions(); | 3671 if (FLAG_idefs) SetupInformativeDefinitions(); |
| 3836 if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) { | 3672 if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) { |
| 3837 EliminateRedundantBoundsChecks(); | 3673 EliminateRedundantBoundsChecks(); |
| 3838 } | 3674 } |
| (...skipping 7405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11244 if (ShouldProduceTraceOutput()) { | 11080 if (ShouldProduceTraceOutput()) { |
| 11245 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11081 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 11246 } | 11082 } |
| 11247 | 11083 |
| 11248 #ifdef DEBUG | 11084 #ifdef DEBUG |
| 11249 graph_->Verify(false); // No full verify. | 11085 graph_->Verify(false); // No full verify. |
| 11250 #endif | 11086 #endif |
| 11251 } | 11087 } |
| 11252 | 11088 |
| 11253 } } // namespace v8::internal | 11089 } } // namespace v8::internal |
| OLD | NEW |