Chromium Code Reviews| 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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 131 | 131 |
| 132 return instr; | 132 return instr; |
| 133 } | 133 } |
| 134 | 134 |
| 135 | 135 |
| 136 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, | 136 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, |
| 137 RemovableSimulate removable) { | 137 RemovableSimulate removable) { |
| 138 ASSERT(HasEnvironment()); | 138 ASSERT(HasEnvironment()); |
| 139 HEnvironment* environment = last_environment(); | 139 HEnvironment* environment = last_environment(); |
| 140 ASSERT(ast_id.IsNone() || | 140 ASSERT(ast_id.IsNone() || |
| 141 ast_id == BailoutId::StubEntry() || | |
| 141 environment->closure()->shared()->VerifyBailoutId(ast_id)); | 142 environment->closure()->shared()->VerifyBailoutId(ast_id)); |
| 142 | 143 |
| 143 int push_count = environment->push_count(); | 144 int push_count = environment->push_count(); |
| 144 int pop_count = environment->pop_count(); | 145 int pop_count = environment->pop_count(); |
| 145 | 146 |
| 146 HSimulate* instr = | 147 HSimulate* instr = |
| 147 new(zone()) HSimulate(ast_id, pop_count, zone(), removable); | 148 new(zone()) HSimulate(ast_id, pop_count, zone(), removable); |
| 148 // Order of pushed values: newest (top of stack) first. This allows | 149 // Order of pushed values: newest (top of stack) first. This allows |
| 149 // HSimulate::MergeInto() to easily append additional pushed values | 150 // HSimulate::MergeInto() to easily append additional pushed values |
| 150 // that are older (from further down the stack). | 151 // that are older (from further down the stack). |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 614 HConstant* HGraph::GetConstantFalse() { | 615 HConstant* HGraph::GetConstantFalse() { |
| 615 return GetConstant(&constant_false_, isolate()->factory()->false_value()); | 616 return GetConstant(&constant_false_, isolate()->factory()->false_value()); |
| 616 } | 617 } |
| 617 | 618 |
| 618 | 619 |
| 619 HConstant* HGraph::GetConstantHole() { | 620 HConstant* HGraph::GetConstantHole() { |
| 620 return GetConstant(&constant_hole_, isolate()->factory()->the_hole_value()); | 621 return GetConstant(&constant_hole_, isolate()->factory()->the_hole_value()); |
| 621 } | 622 } |
| 622 | 623 |
| 623 | 624 |
| 624 HGraphBuilder::HGraphBuilder(CompilationInfo* info, | 625 HGraph* HGraphBuilder::CreateGraph() { |
| 625 TypeFeedbackOracle* oracle) | 626 graph_ = new(zone()) HGraph(info_); |
| 626 : function_state_(NULL), | 627 if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info_); |
| 628 { | |
|
Jakob Kummerow
2012/11/28 16:28:22
why this block? Shouldn't make a difference if you
danno
2012/11/30 16:23:24
Done.
| |
| 629 HPhase phase("H_Block building"); | |
| 630 set_current_block(graph()->entry_block()); | |
| 631 if (!BuildGraph()) return NULL; | |
| 632 } | |
| 633 return graph_; | |
| 634 } | |
| 635 | |
| 636 | |
| 637 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | |
| 638 ASSERT(current_block() != NULL); | |
| 639 current_block()->AddInstruction(instr); | |
| 640 return instr; | |
| 641 } | |
| 642 | |
| 643 | |
| 644 void HGraphBuilder::AddSimulate(BailoutId id, | |
| 645 RemovableSimulate removable) { | |
| 646 ASSERT(current_block() != NULL); | |
| 647 current_block()->AddSimulate(id, removable); | |
| 648 } | |
| 649 | |
| 650 | |
| 651 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( | |
| 652 HValue* external_elements, | |
| 653 HValue* checked_key, | |
| 654 HValue* val, | |
| 655 HValue* dependency, | |
| 656 ElementsKind elements_kind, | |
| 657 bool is_store) { | |
| 658 Zone* zone = this->zone(); | |
| 659 if (is_store) { | |
| 660 ASSERT(val != NULL); | |
| 661 switch (elements_kind) { | |
| 662 case EXTERNAL_PIXEL_ELEMENTS: { | |
| 663 val = AddInstruction(new(zone) HClampToUint8(val)); | |
| 664 break; | |
| 665 } | |
| 666 case EXTERNAL_BYTE_ELEMENTS: | |
| 667 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
| 668 case EXTERNAL_SHORT_ELEMENTS: | |
| 669 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
| 670 case EXTERNAL_INT_ELEMENTS: | |
| 671 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { | |
| 672 break; | |
| 673 } | |
| 674 case EXTERNAL_FLOAT_ELEMENTS: | |
| 675 case EXTERNAL_DOUBLE_ELEMENTS: | |
| 676 break; | |
| 677 case FAST_SMI_ELEMENTS: | |
| 678 case FAST_ELEMENTS: | |
| 679 case FAST_DOUBLE_ELEMENTS: | |
| 680 case FAST_HOLEY_SMI_ELEMENTS: | |
| 681 case FAST_HOLEY_ELEMENTS: | |
| 682 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
| 683 case DICTIONARY_ELEMENTS: | |
| 684 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
| 685 UNREACHABLE(); | |
| 686 break; | |
| 687 } | |
| 688 return new(zone) HStoreKeyed(external_elements, checked_key, | |
| 689 val, elements_kind); | |
| 690 } else { | |
| 691 ASSERT(val == NULL); | |
| 692 HLoadKeyed* load = | |
| 693 new(zone) HLoadKeyed( | |
| 694 external_elements, checked_key, dependency, elements_kind); | |
| 695 if (FLAG_opt_safe_uint32_operations && | |
| 696 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { | |
| 697 graph()->RecordUint32Instruction(load); | |
| 698 } | |
| 699 return load; | |
| 700 } | |
| 701 } | |
| 702 | |
| 703 | |
| 704 HInstruction* HGraphBuilder::BuildFastElementAccess( | |
| 705 HValue* elements, | |
| 706 HValue* checked_key, | |
| 707 HValue* val, | |
| 708 HValue* load_dependency, | |
| 709 ElementsKind elements_kind, | |
| 710 bool is_store) { | |
| 711 Zone* zone = this->zone(); | |
| 712 if (is_store) { | |
| 713 ASSERT(val != NULL); | |
| 714 switch (elements_kind) { | |
| 715 case FAST_SMI_ELEMENTS: | |
| 716 case FAST_HOLEY_SMI_ELEMENTS: | |
| 717 // Smi-only arrays need a smi check. | |
| 718 AddInstruction(new(zone) HCheckSmi(val)); | |
| 719 // Fall through. | |
| 720 case FAST_ELEMENTS: | |
| 721 case FAST_HOLEY_ELEMENTS: | |
| 722 case FAST_DOUBLE_ELEMENTS: | |
| 723 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
| 724 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind); | |
| 725 default: | |
| 726 UNREACHABLE(); | |
| 727 return NULL; | |
| 728 } | |
| 729 } | |
| 730 // It's an element load (!is_store). | |
| 731 return new(zone) HLoadKeyed(elements, | |
| 732 checked_key, | |
| 733 load_dependency, | |
| 734 elements_kind); | |
| 735 } | |
| 736 | |
| 737 | |
| 738 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | |
| 739 HValue* object, | |
| 740 HValue* key, | |
| 741 HValue* val, | |
| 742 HCheckMaps* mapcheck, | |
| 743 bool is_js_array, | |
| 744 ElementsKind elements_kind, | |
| 745 bool is_store) { | |
| 746 Zone* zone = this->zone(); | |
| 747 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | |
| 748 // on a HElementsTransition instruction. The flag can also be removed if the | |
| 749 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | |
| 750 // ElementsKind transitions. Finally, the dependency can be removed for stores | |
| 751 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | |
| 752 // generated store code. | |
| 753 if ((elements_kind == FAST_HOLEY_ELEMENTS) || | |
| 754 (elements_kind == FAST_ELEMENTS && is_store)) { | |
| 755 if (mapcheck != NULL) { | |
| 756 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | |
| 757 } | |
| 758 } | |
| 759 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); | |
| 760 bool fast_elements = IsFastObjectElementsKind(elements_kind); | |
| 761 HInstruction* elements = | |
| 762 AddInstruction(new(zone) HLoadElements(object, mapcheck)); | |
| 763 if (is_store && (fast_elements || fast_smi_only_elements)) { | |
| 764 HCheckMaps* check_cow_map = new(zone) HCheckMaps( | |
| 765 elements, Isolate::Current()->factory()->fixed_array_map(), zone); | |
| 766 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | |
| 767 AddInstruction(check_cow_map); | |
| 768 } | |
| 769 HInstruction* length = NULL; | |
| 770 HInstruction* checked_key = NULL; | |
| 771 if (IsExternalArrayElementsKind(elements_kind)) { | |
| 772 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | |
| 773 checked_key = AddInstruction(new(zone) HBoundsCheck(key, length, | |
| 774 ALLOW_SMI_KEY)); | |
| 775 HLoadExternalArrayPointer* external_elements = | |
| 776 new(zone) HLoadExternalArrayPointer(elements); | |
| 777 AddInstruction(external_elements); | |
| 778 return BuildExternalArrayElementAccess( | |
| 779 external_elements, checked_key, val, mapcheck, | |
| 780 elements_kind, is_store); | |
| 781 } | |
| 782 ASSERT(fast_smi_only_elements || | |
| 783 fast_elements || | |
| 784 IsFastDoubleElementsKind(elements_kind)); | |
| 785 if (is_js_array) { | |
| 786 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck, | |
| 787 HType::Smi())); | |
| 788 } else { | |
| 789 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | |
| 790 } | |
| 791 checked_key = AddInstruction(new(zone) HBoundsCheck(key, length, | |
| 792 ALLOW_SMI_KEY)); | |
| 793 return BuildFastElementAccess(elements, checked_key, val, mapcheck, | |
| 794 elements_kind, is_store); | |
| 795 } | |
| 796 | |
| 797 | |
| 798 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, | |
| 799 TypeFeedbackOracle* oracle) | |
| 800 : HGraphBuilder(info), | |
| 801 function_state_(NULL), | |
| 627 initial_function_state_(this, info, oracle, NORMAL_RETURN), | 802 initial_function_state_(this, info, oracle, NORMAL_RETURN), |
| 628 ast_context_(NULL), | 803 ast_context_(NULL), |
| 629 break_scope_(NULL), | 804 break_scope_(NULL), |
| 630 graph_(NULL), | |
| 631 current_block_(NULL), | |
| 632 inlined_count_(0), | 805 inlined_count_(0), |
| 633 globals_(10, info->zone()), | 806 globals_(10, info->zone()), |
| 634 zone_(info->zone()), | |
| 635 inline_bailout_(false) { | 807 inline_bailout_(false) { |
| 636 // This is not initialized in the initializer list because the | 808 // This is not initialized in the initializer list because the |
| 637 // constructor for the initial state relies on function_state_ == NULL | 809 // constructor for the initial state relies on function_state_ == NULL |
| 638 // to know it's the initial state. | 810 // to know it's the initial state. |
| 639 function_state_= &initial_function_state_; | 811 function_state_= &initial_function_state_; |
| 640 } | 812 InitializeAstVisitor(); |
| 641 | 813 } |
| 642 HBasicBlock* HGraphBuilder::CreateJoin(HBasicBlock* first, | 814 |
| 643 HBasicBlock* second, | 815 |
| 644 BailoutId join_id) { | 816 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, |
| 817 HBasicBlock* second, | |
| 818 BailoutId join_id) { | |
| 645 if (first == NULL) { | 819 if (first == NULL) { |
| 646 return second; | 820 return second; |
| 647 } else if (second == NULL) { | 821 } else if (second == NULL) { |
| 648 return first; | 822 return first; |
| 649 } else { | 823 } else { |
| 650 HBasicBlock* join_block = graph_->CreateBasicBlock(); | 824 HBasicBlock* join_block = graph()->CreateBasicBlock(); |
| 651 first->Goto(join_block); | 825 first->Goto(join_block); |
| 652 second->Goto(join_block); | 826 second->Goto(join_block); |
| 653 join_block->SetJoinId(join_id); | 827 join_block->SetJoinId(join_id); |
| 654 return join_block; | 828 return join_block; |
| 655 } | 829 } |
| 656 } | 830 } |
| 657 | 831 |
| 658 | 832 |
| 659 HBasicBlock* HGraphBuilder::JoinContinue(IterationStatement* statement, | 833 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement, |
| 660 HBasicBlock* exit_block, | 834 HBasicBlock* exit_block, |
| 661 HBasicBlock* continue_block) { | 835 HBasicBlock* continue_block) { |
| 662 if (continue_block != NULL) { | 836 if (continue_block != NULL) { |
| 663 if (exit_block != NULL) exit_block->Goto(continue_block); | 837 if (exit_block != NULL) exit_block->Goto(continue_block); |
| 664 continue_block->SetJoinId(statement->ContinueId()); | 838 continue_block->SetJoinId(statement->ContinueId()); |
| 665 return continue_block; | 839 return continue_block; |
| 666 } | 840 } |
| 667 return exit_block; | 841 return exit_block; |
| 668 } | 842 } |
| 669 | 843 |
| 670 | 844 |
| 671 HBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement, | 845 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement, |
| 672 HBasicBlock* loop_entry, | 846 HBasicBlock* loop_entry, |
| 673 HBasicBlock* body_exit, | 847 HBasicBlock* body_exit, |
| 674 HBasicBlock* loop_successor, | 848 HBasicBlock* loop_successor, |
| 675 HBasicBlock* break_block) { | 849 HBasicBlock* break_block) { |
| 676 if (body_exit != NULL) body_exit->Goto(loop_entry); | 850 if (body_exit != NULL) body_exit->Goto(loop_entry); |
| 677 loop_entry->PostProcessLoopHeader(statement); | 851 loop_entry->PostProcessLoopHeader(statement); |
| 678 if (break_block != NULL) { | 852 if (break_block != NULL) { |
| 679 if (loop_successor != NULL) loop_successor->Goto(break_block); | 853 if (loop_successor != NULL) loop_successor->Goto(break_block); |
| 680 break_block->SetJoinId(statement->ExitId()); | 854 break_block->SetJoinId(statement->ExitId()); |
| 681 return break_block; | 855 return break_block; |
| 682 } | 856 } |
| 683 return loop_successor; | 857 return loop_successor; |
| 684 } | 858 } |
| 685 | 859 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 696 entry_block_(NULL), | 870 entry_block_(NULL), |
| 697 blocks_(8, info->zone()), | 871 blocks_(8, info->zone()), |
| 698 values_(16, info->zone()), | 872 values_(16, info->zone()), |
| 699 phi_list_(NULL), | 873 phi_list_(NULL), |
| 700 uint32_instructions_(NULL), | 874 uint32_instructions_(NULL), |
| 701 info_(info), | 875 info_(info), |
| 702 zone_(info->zone()), | 876 zone_(info->zone()), |
| 703 is_recursive_(false), | 877 is_recursive_(false), |
| 704 use_optimistic_licm_(false), | 878 use_optimistic_licm_(false), |
| 705 type_change_checksum_(0) { | 879 type_change_checksum_(0) { |
| 706 start_environment_ = | 880 if (info->IsStub()) { |
| 707 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); | 881 start_environment_ = |
| 882 new(zone_) HEnvironment(zone_); | |
| 883 } else { | |
| 884 start_environment_ = | |
| 885 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); | |
| 886 } | |
| 708 start_environment_->set_ast_id(BailoutId::FunctionEntry()); | 887 start_environment_->set_ast_id(BailoutId::FunctionEntry()); |
| 709 entry_block_ = CreateBasicBlock(); | 888 entry_block_ = CreateBasicBlock(); |
| 710 entry_block_->SetInitialEnvironment(start_environment_); | 889 entry_block_->SetInitialEnvironment(start_environment_); |
| 711 } | 890 } |
| 712 | 891 |
| 713 | 892 |
| 714 HBasicBlock* HGraph::CreateBasicBlock() { | 893 HBasicBlock* HGraph::CreateBasicBlock() { |
| 715 HBasicBlock* result = new(zone()) HBasicBlock(this); | 894 HBasicBlock* result = new(zone()) HBasicBlock(this); |
| 716 blocks_.Add(result, zone()); | 895 blocks_.Add(result, zone()); |
| 717 return result; | 896 return result; |
| (...skipping 2168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2886 visited.Clear(); | 3065 visited.Clear(); |
| 2887 } | 3066 } |
| 2888 } | 3067 } |
| 2889 } | 3068 } |
| 2890 } | 3069 } |
| 2891 } | 3070 } |
| 2892 | 3071 |
| 2893 | 3072 |
| 2894 // Implementation of utility class to encapsulate the translation state for | 3073 // Implementation of utility class to encapsulate the translation state for |
| 2895 // a (possibly inlined) function. | 3074 // a (possibly inlined) function. |
| 2896 FunctionState::FunctionState(HGraphBuilder* owner, | 3075 FunctionState::FunctionState(HOptimizedGraphBuilder* owner, |
| 2897 CompilationInfo* info, | 3076 CompilationInfo* info, |
| 2898 TypeFeedbackOracle* oracle, | 3077 TypeFeedbackOracle* oracle, |
| 2899 InliningKind inlining_kind) | 3078 InliningKind inlining_kind) |
| 2900 : owner_(owner), | 3079 : owner_(owner), |
| 2901 compilation_info_(info), | 3080 compilation_info_(info), |
| 2902 oracle_(oracle), | 3081 oracle_(oracle), |
| 2903 call_context_(NULL), | 3082 call_context_(NULL), |
| 2904 inlining_kind_(inlining_kind), | 3083 inlining_kind_(inlining_kind), |
| 2905 function_return_(NULL), | 3084 function_return_(NULL), |
| 2906 test_context_(NULL), | 3085 test_context_(NULL), |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 2935 | 3114 |
| 2936 | 3115 |
| 2937 FunctionState::~FunctionState() { | 3116 FunctionState::~FunctionState() { |
| 2938 delete test_context_; | 3117 delete test_context_; |
| 2939 owner_->set_function_state(outer_); | 3118 owner_->set_function_state(outer_); |
| 2940 } | 3119 } |
| 2941 | 3120 |
| 2942 | 3121 |
| 2943 // Implementation of utility classes to represent an expression's context in | 3122 // Implementation of utility classes to represent an expression's context in |
| 2944 // the AST. | 3123 // the AST. |
| 2945 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) | 3124 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind) |
| 2946 : owner_(owner), | 3125 : owner_(owner), |
| 2947 kind_(kind), | 3126 kind_(kind), |
| 2948 outer_(owner->ast_context()), | 3127 outer_(owner->ast_context()), |
| 2949 for_typeof_(false) { | 3128 for_typeof_(false) { |
| 2950 owner->set_ast_context(this); // Push. | 3129 owner->set_ast_context(this); // Push. |
| 2951 #ifdef DEBUG | 3130 #ifdef DEBUG |
| 2952 ASSERT(owner->environment()->frame_type() == JS_FUNCTION); | 3131 ASSERT(owner->environment()->frame_type() == JS_FUNCTION); |
| 2953 original_length_ = owner->environment()->length(); | 3132 original_length_ = owner->environment()->length(); |
| 2954 #endif | 3133 #endif |
| 2955 } | 3134 } |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3046 owner()->set_current_block(materialize_false); | 3225 owner()->set_current_block(materialize_false); |
| 3047 owner()->Push(owner()->graph()->GetConstantFalse()); | 3226 owner()->Push(owner()->graph()->GetConstantFalse()); |
| 3048 HBasicBlock* join = | 3227 HBasicBlock* join = |
| 3049 owner()->CreateJoin(materialize_true, materialize_false, ast_id); | 3228 owner()->CreateJoin(materialize_true, materialize_false, ast_id); |
| 3050 owner()->set_current_block(join); | 3229 owner()->set_current_block(join); |
| 3051 } | 3230 } |
| 3052 | 3231 |
| 3053 | 3232 |
| 3054 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 3233 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
| 3055 ASSERT(!instr->IsControlInstruction()); | 3234 ASSERT(!instr->IsControlInstruction()); |
| 3056 HGraphBuilder* builder = owner(); | 3235 HOptimizedGraphBuilder* builder = owner(); |
| 3057 builder->AddInstruction(instr); | 3236 builder->AddInstruction(instr); |
| 3058 // We expect a simulate after every expression with side effects, though | 3237 // We expect a simulate after every expression with side effects, though |
| 3059 // this one isn't actually needed (and wouldn't work if it were targeted). | 3238 // this one isn't actually needed (and wouldn't work if it were targeted). |
| 3060 if (instr->HasObservableSideEffects()) { | 3239 if (instr->HasObservableSideEffects()) { |
| 3061 builder->Push(instr); | 3240 builder->Push(instr); |
| 3062 builder->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 3241 builder->AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 3063 builder->Pop(); | 3242 builder->Pop(); |
| 3064 } | 3243 } |
| 3065 BuildBranch(instr); | 3244 BuildBranch(instr); |
| 3066 } | 3245 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 3077 empty_false->Goto(if_false(), owner()->function_state()); | 3256 empty_false->Goto(if_false(), owner()->function_state()); |
| 3078 owner()->set_current_block(NULL); | 3257 owner()->set_current_block(NULL); |
| 3079 } | 3258 } |
| 3080 | 3259 |
| 3081 | 3260 |
| 3082 void TestContext::BuildBranch(HValue* value) { | 3261 void TestContext::BuildBranch(HValue* value) { |
| 3083 // We expect the graph to be in edge-split form: there is no edge that | 3262 // We expect the graph to be in edge-split form: there is no edge that |
| 3084 // connects a branch node to a join node. We conservatively ensure that | 3263 // connects a branch node to a join node. We conservatively ensure that |
| 3085 // property by always adding an empty block on the outgoing edges of this | 3264 // property by always adding an empty block on the outgoing edges of this |
| 3086 // branch. | 3265 // branch. |
| 3087 HGraphBuilder* builder = owner(); | 3266 HOptimizedGraphBuilder* builder = owner(); |
| 3088 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { | 3267 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { |
| 3089 builder->Bailout("arguments object value in a test context"); | 3268 builder->Bailout("arguments object value in a test context"); |
| 3090 } | 3269 } |
| 3091 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); | 3270 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); |
| 3092 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); | 3271 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); |
| 3093 TypeFeedbackId test_id = condition()->test_id(); | 3272 TypeFeedbackId test_id = condition()->test_id(); |
| 3094 ToBooleanStub::Types expected(oracle()->ToBooleanTypes(test_id)); | 3273 ToBooleanStub::Types expected(oracle()->ToBooleanTypes(test_id)); |
| 3095 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected); | 3274 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected); |
| 3096 builder->current_block()->Finish(test); | 3275 builder->current_block()->Finish(test); |
| 3097 | 3276 |
| 3098 empty_true->Goto(if_true(), owner()->function_state()); | 3277 empty_true->Goto(if_true(), owner()->function_state()); |
| 3099 empty_false->Goto(if_false(), owner()->function_state()); | 3278 empty_false->Goto(if_false(), owner()->function_state()); |
| 3100 builder->set_current_block(NULL); | 3279 builder->set_current_block(NULL); |
| 3101 } | 3280 } |
| 3102 | 3281 |
| 3103 | 3282 |
| 3104 // HGraphBuilder infrastructure for bailing out and checking bailouts. | 3283 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. |
| 3105 #define CHECK_BAILOUT(call) \ | 3284 #define CHECK_BAILOUT(call) \ |
| 3106 do { \ | 3285 do { \ |
| 3107 call; \ | 3286 call; \ |
| 3108 if (HasStackOverflow()) return; \ | 3287 if (HasStackOverflow()) return; \ |
| 3109 } while (false) | 3288 } while (false) |
| 3110 | 3289 |
| 3111 | 3290 |
| 3112 #define CHECK_ALIVE(call) \ | 3291 #define CHECK_ALIVE(call) \ |
| 3113 do { \ | 3292 do { \ |
| 3114 call; \ | 3293 call; \ |
| 3115 if (HasStackOverflow() || current_block() == NULL) return; \ | 3294 if (HasStackOverflow() || current_block() == NULL) return; \ |
| 3116 } while (false) | 3295 } while (false) |
| 3117 | 3296 |
| 3118 | 3297 |
| 3119 void HGraphBuilder::Bailout(const char* reason) { | 3298 void HOptimizedGraphBuilder::Bailout(const char* reason) { |
| 3120 info()->set_bailout_reason(reason); | 3299 info()->set_bailout_reason(reason); |
| 3121 SetStackOverflow(); | 3300 SetStackOverflow(); |
| 3122 } | 3301 } |
| 3123 | 3302 |
| 3124 | 3303 |
| 3125 void HGraphBuilder::VisitForEffect(Expression* expr) { | 3304 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { |
| 3126 EffectContext for_effect(this); | 3305 EffectContext for_effect(this); |
| 3127 Visit(expr); | 3306 Visit(expr); |
| 3128 } | 3307 } |
| 3129 | 3308 |
| 3130 | 3309 |
| 3131 void HGraphBuilder::VisitForValue(Expression* expr, ArgumentsAllowedFlag flag) { | 3310 void HOptimizedGraphBuilder::VisitForValue(Expression* expr, |
| 3311 ArgumentsAllowedFlag flag) { | |
| 3132 ValueContext for_value(this, flag); | 3312 ValueContext for_value(this, flag); |
| 3133 Visit(expr); | 3313 Visit(expr); |
| 3134 } | 3314 } |
| 3135 | 3315 |
| 3136 | 3316 |
| 3137 void HGraphBuilder::VisitForTypeOf(Expression* expr) { | 3317 void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) { |
| 3138 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); | 3318 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
| 3139 for_value.set_for_typeof(true); | 3319 for_value.set_for_typeof(true); |
| 3140 Visit(expr); | 3320 Visit(expr); |
| 3141 } | 3321 } |
| 3142 | 3322 |
| 3143 | 3323 |
| 3144 | 3324 |
| 3145 void HGraphBuilder::VisitForControl(Expression* expr, | 3325 void HOptimizedGraphBuilder::VisitForControl( |
| 3146 HBasicBlock* true_block, | 3326 Expression* expr, |
|
Jakob Kummerow
2012/11/28 16:28:22
nit: line break before first argument not necessar
danno
2012/11/30 16:23:24
Done.
| |
| 3147 HBasicBlock* false_block) { | 3327 HBasicBlock* true_block, |
| 3328 HBasicBlock* false_block) { | |
| 3148 TestContext for_test(this, expr, oracle(), true_block, false_block); | 3329 TestContext for_test(this, expr, oracle(), true_block, false_block); |
| 3149 Visit(expr); | 3330 Visit(expr); |
| 3150 } | 3331 } |
| 3151 | 3332 |
| 3152 | 3333 |
| 3153 void HGraphBuilder::VisitArgument(Expression* expr) { | 3334 void HOptimizedGraphBuilder::VisitArgument(Expression* expr) { |
| 3154 CHECK_ALIVE(VisitForValue(expr)); | 3335 CHECK_ALIVE(VisitForValue(expr)); |
| 3155 Push(AddInstruction(new(zone()) HPushArgument(Pop()))); | 3336 Push(AddInstruction(new(zone()) HPushArgument(Pop()))); |
| 3156 } | 3337 } |
| 3157 | 3338 |
| 3158 | 3339 |
| 3159 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { | 3340 void HOptimizedGraphBuilder::VisitArgumentList( |
| 3341 ZoneList<Expression*>* arguments) { | |
| 3160 for (int i = 0; i < arguments->length(); i++) { | 3342 for (int i = 0; i < arguments->length(); i++) { |
| 3161 CHECK_ALIVE(VisitArgument(arguments->at(i))); | 3343 CHECK_ALIVE(VisitArgument(arguments->at(i))); |
| 3162 } | 3344 } |
| 3163 } | 3345 } |
| 3164 | 3346 |
| 3165 | 3347 |
| 3166 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { | 3348 void HOptimizedGraphBuilder::VisitExpressions( |
| 3349 ZoneList<Expression*>* exprs) { | |
| 3167 for (int i = 0; i < exprs->length(); ++i) { | 3350 for (int i = 0; i < exprs->length(); ++i) { |
| 3168 CHECK_ALIVE(VisitForValue(exprs->at(i))); | 3351 CHECK_ALIVE(VisitForValue(exprs->at(i))); |
| 3169 } | 3352 } |
| 3170 } | 3353 } |
| 3171 | 3354 |
| 3172 | 3355 |
| 3173 HGraph* HGraphBuilder::CreateGraph() { | 3356 bool HOptimizedGraphBuilder::BuildGraph() { |
| 3174 graph_ = new(zone()) HGraph(info()); | 3357 Scope* scope = info()->scope(); |
| 3175 if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info()); | 3358 if (scope->HasIllegalRedeclaration()) { |
| 3359 Bailout("function with illegal redeclaration"); | |
| 3360 return false; | |
| 3361 } | |
| 3362 if (scope->calls_eval()) { | |
| 3363 Bailout("function calls eval"); | |
| 3364 return false; | |
| 3365 } | |
| 3366 SetUpScope(scope); | |
| 3176 | 3367 |
| 3177 { | 3368 // Add an edge to the body entry. This is warty: the graph's start |
| 3178 HPhase phase("H_Block building"); | 3369 // environment will be used by the Lithium translation as the initial |
| 3179 current_block_ = graph()->entry_block(); | 3370 // environment on graph entry, but it has now been mutated by the |
| 3371 // Hydrogen translation of the instructions in the start block. This | |
| 3372 // environment uses values which have not been defined yet. These | |
| 3373 // Hydrogen instructions will then be replayed by the Lithium | |
| 3374 // translation, so they cannot have an environment effect. The edge to | |
| 3375 // the body's entry block (along with some special logic for the start | |
| 3376 // block in HInstruction::InsertAfter) seals the start block from | |
| 3377 // getting unwanted instructions inserted. | |
| 3378 // | |
| 3379 // TODO(kmillikin): Fix this. Stop mutating the initial environment. | |
| 3380 // Make the Hydrogen instructions in the initial block into Hydrogen | |
| 3381 // values (but not instructions), present in the initial environment and | |
| 3382 // not replayed by the Lithium translation. | |
| 3383 HEnvironment* initial_env = environment()->CopyWithoutHistory(); | |
| 3384 HBasicBlock* body_entry = CreateBasicBlock(initial_env); | |
| 3385 current_block()->Goto(body_entry); | |
| 3386 body_entry->SetJoinId(BailoutId::FunctionEntry()); | |
| 3387 set_current_block(body_entry); | |
| 3180 | 3388 |
| 3181 Scope* scope = info()->scope(); | 3389 // Handle implicit declaration of the function name in named function |
| 3182 if (scope->HasIllegalRedeclaration()) { | 3390 // expressions before other declarations. |
| 3183 Bailout("function with illegal redeclaration"); | 3391 if (scope->is_function_scope() && scope->function() != NULL) { |
| 3184 return NULL; | 3392 VisitVariableDeclaration(scope->function()); |
| 3185 } | 3393 } |
| 3186 if (scope->calls_eval()) { | 3394 VisitDeclarations(scope->declarations()); |
| 3187 Bailout("function calls eval"); | 3395 AddSimulate(BailoutId::Declarations()); |
| 3188 return NULL; | |
| 3189 } | |
| 3190 SetUpScope(scope); | |
| 3191 | 3396 |
| 3192 // Add an edge to the body entry. This is warty: the graph's start | 3397 HValue* context = environment()->LookupContext(); |
| 3193 // environment will be used by the Lithium translation as the initial | 3398 AddInstruction( |
| 3194 // environment on graph entry, but it has now been mutated by the | 3399 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); |
| 3195 // Hydrogen translation of the instructions in the start block. This | |
| 3196 // environment uses values which have not been defined yet. These | |
| 3197 // Hydrogen instructions will then be replayed by the Lithium | |
| 3198 // translation, so they cannot have an environment effect. The edge to | |
| 3199 // the body's entry block (along with some special logic for the start | |
| 3200 // block in HInstruction::InsertAfter) seals the start block from | |
| 3201 // getting unwanted instructions inserted. | |
| 3202 // | |
| 3203 // TODO(kmillikin): Fix this. Stop mutating the initial environment. | |
| 3204 // Make the Hydrogen instructions in the initial block into Hydrogen | |
| 3205 // values (but not instructions), present in the initial environment and | |
| 3206 // not replayed by the Lithium translation. | |
| 3207 HEnvironment* initial_env = environment()->CopyWithoutHistory(); | |
| 3208 HBasicBlock* body_entry = CreateBasicBlock(initial_env); | |
| 3209 current_block()->Goto(body_entry); | |
| 3210 body_entry->SetJoinId(BailoutId::FunctionEntry()); | |
| 3211 set_current_block(body_entry); | |
| 3212 | 3400 |
| 3213 // Handle implicit declaration of the function name in named function | 3401 VisitStatements(info()->function()->body()); |
| 3214 // expressions before other declarations. | 3402 if (HasStackOverflow()) return false; |
| 3215 if (scope->is_function_scope() && scope->function() != NULL) { | |
| 3216 VisitVariableDeclaration(scope->function()); | |
| 3217 } | |
| 3218 VisitDeclarations(scope->declarations()); | |
| 3219 AddSimulate(BailoutId::Declarations()); | |
| 3220 | 3403 |
| 3221 HValue* context = environment()->LookupContext(); | 3404 if (current_block() != NULL) { |
| 3222 AddInstruction( | 3405 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined()); |
| 3223 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); | 3406 current_block()->FinishExit(instr); |
| 3224 | 3407 set_current_block(NULL); |
| 3225 VisitStatements(info()->function()->body()); | |
| 3226 if (HasStackOverflow()) return NULL; | |
| 3227 | |
| 3228 if (current_block() != NULL) { | |
| 3229 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined()); | |
| 3230 current_block()->FinishExit(instr); | |
| 3231 set_current_block(NULL); | |
| 3232 } | |
| 3233 | |
| 3234 // If the checksum of the number of type info changes is the same as the | |
| 3235 // last time this function was compiled, then this recompile is likely not | |
| 3236 // due to missing/inadequate type feedback, but rather too aggressive | |
| 3237 // optimization. Disable optimistic LICM in that case. | |
| 3238 Handle<Code> unoptimized_code(info()->shared_info()->code()); | |
| 3239 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | |
| 3240 Handle<TypeFeedbackInfo> type_info( | |
| 3241 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); | |
| 3242 int checksum = type_info->own_type_change_checksum(); | |
| 3243 int composite_checksum = graph()->update_type_change_checksum(checksum); | |
| 3244 graph()->set_use_optimistic_licm( | |
| 3245 !type_info->matches_inlined_type_change_checksum(composite_checksum)); | |
| 3246 type_info->set_inlined_type_change_checksum(composite_checksum); | |
| 3247 } | 3408 } |
| 3248 | 3409 |
| 3249 return graph(); | 3410 // If the checksum of the number of type info changes is the same as the |
| 3411 // last time this function was compiled, then this recompile is likely not | |
| 3412 // due to missing/inadequate type feedback, but rather too aggressive | |
| 3413 // optimization. Disable optimistic LICM in that case. | |
| 3414 Handle<Code> unoptimized_code(info()->shared_info()->code()); | |
| 3415 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | |
| 3416 Handle<TypeFeedbackInfo> type_info( | |
| 3417 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); | |
| 3418 int checksum = type_info->own_type_change_checksum(); | |
| 3419 int composite_checksum = graph()->update_type_change_checksum(checksum); | |
| 3420 graph()->set_use_optimistic_licm( | |
| 3421 !type_info->matches_inlined_type_change_checksum(composite_checksum)); | |
| 3422 type_info->set_inlined_type_change_checksum(composite_checksum); | |
| 3423 | |
| 3424 return true; | |
| 3250 } | 3425 } |
| 3251 | 3426 |
| 3427 | |
| 3252 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { | 3428 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { |
| 3253 *bailout_reason = SmartArrayPointer<char>(); | 3429 *bailout_reason = SmartArrayPointer<char>(); |
| 3254 OrderBlocks(); | 3430 OrderBlocks(); |
| 3255 AssignDominators(); | 3431 AssignDominators(); |
| 3256 | 3432 |
| 3257 #ifdef DEBUG | 3433 #ifdef DEBUG |
| 3258 // Do a full verify after building the graph and computing dominators. | 3434 // Do a full verify after building the graph and computing dominators. |
| 3259 Verify(true); | 3435 Verify(true); |
| 3260 #endif | 3436 #endif |
| 3261 | 3437 |
| (...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3765 } | 3941 } |
| 3766 instr->DeleteAndReplaceWith(NULL); | 3942 instr->DeleteAndReplaceWith(NULL); |
| 3767 for (int i = 0; i < instr->OperandCount(); ++i) { | 3943 for (int i = 0; i < instr->OperandCount(); ++i) { |
| 3768 HValue* operand = instr->OperandAt(i); | 3944 HValue* operand = instr->OperandAt(i); |
| 3769 if (operand->IsDead()) worklist.Add(HInstruction::cast(operand), zone()); | 3945 if (operand->IsDead()) worklist.Add(HInstruction::cast(operand), zone()); |
| 3770 } | 3946 } |
| 3771 } | 3947 } |
| 3772 } | 3948 } |
| 3773 | 3949 |
| 3774 | 3950 |
| 3775 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 3951 void HOptimizedGraphBuilder::AddPhi(HPhi* instr) { |
| 3776 ASSERT(current_block() != NULL); | |
| 3777 current_block()->AddInstruction(instr); | |
| 3778 return instr; | |
| 3779 } | |
| 3780 | |
| 3781 | |
| 3782 void HGraphBuilder::AddSimulate(BailoutId ast_id, RemovableSimulate removable) { | |
| 3783 ASSERT(current_block() != NULL); | |
| 3784 current_block()->AddSimulate(ast_id, removable); | |
| 3785 } | |
| 3786 | |
| 3787 | |
| 3788 void HGraphBuilder::AddPhi(HPhi* instr) { | |
| 3789 ASSERT(current_block() != NULL); | 3952 ASSERT(current_block() != NULL); |
| 3790 current_block()->AddPhi(instr); | 3953 current_block()->AddPhi(instr); |
| 3791 } | 3954 } |
| 3792 | 3955 |
| 3793 | 3956 |
| 3794 void HGraphBuilder::PushAndAdd(HInstruction* instr) { | 3957 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { |
| 3795 Push(instr); | 3958 Push(instr); |
| 3796 AddInstruction(instr); | 3959 AddInstruction(instr); |
| 3797 } | 3960 } |
| 3798 | 3961 |
| 3799 | 3962 |
| 3800 template <class Instruction> | 3963 template <class Instruction> |
| 3801 HInstruction* HGraphBuilder::PreProcessCall(Instruction* call) { | 3964 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { |
| 3802 int count = call->argument_count(); | 3965 int count = call->argument_count(); |
| 3803 ZoneList<HValue*> arguments(count, zone()); | 3966 ZoneList<HValue*> arguments(count, zone()); |
| 3804 for (int i = 0; i < count; ++i) { | 3967 for (int i = 0; i < count; ++i) { |
| 3805 arguments.Add(Pop(), zone()); | 3968 arguments.Add(Pop(), zone()); |
| 3806 } | 3969 } |
| 3807 | 3970 |
| 3808 while (!arguments.is_empty()) { | 3971 while (!arguments.is_empty()) { |
| 3809 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); | 3972 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); |
| 3810 } | 3973 } |
| 3811 return call; | 3974 return call; |
| 3812 } | 3975 } |
| 3813 | 3976 |
| 3814 | 3977 |
| 3815 void HGraphBuilder::SetUpScope(Scope* scope) { | 3978 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { |
| 3816 HConstant* undefined_constant = new(zone()) HConstant( | 3979 HConstant* undefined_constant = new(zone()) HConstant( |
| 3817 isolate()->factory()->undefined_value(), Representation::Tagged()); | 3980 isolate()->factory()->undefined_value(), Representation::Tagged()); |
| 3818 AddInstruction(undefined_constant); | 3981 AddInstruction(undefined_constant); |
| 3819 graph_->set_undefined_constant(undefined_constant); | 3982 graph()->set_undefined_constant(undefined_constant); |
| 3820 | 3983 |
| 3821 HArgumentsObject* object = new(zone()) HArgumentsObject; | 3984 HArgumentsObject* object = new(zone()) HArgumentsObject; |
| 3822 AddInstruction(object); | 3985 AddInstruction(object); |
| 3823 graph()->SetArgumentsObject(object); | 3986 graph()->SetArgumentsObject(object); |
| 3824 | 3987 |
| 3825 // Set the initial values of parameters including "this". "This" has | 3988 // Set the initial values of parameters including "this". "This" has |
| 3826 // parameter index 0. | 3989 // parameter index 0. |
| 3827 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); | 3990 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); |
| 3828 | 3991 |
| 3829 for (int i = 0; i < environment()->parameter_count(); ++i) { | 3992 for (int i = 0; i < environment()->parameter_count(); ++i) { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 3848 if (!scope->arguments()->IsStackAllocated()) { | 4011 if (!scope->arguments()->IsStackAllocated()) { |
| 3849 return Bailout("context-allocated arguments"); | 4012 return Bailout("context-allocated arguments"); |
| 3850 } | 4013 } |
| 3851 | 4014 |
| 3852 environment()->Bind(scope->arguments(), | 4015 environment()->Bind(scope->arguments(), |
| 3853 graph()->GetArgumentsObject()); | 4016 graph()->GetArgumentsObject()); |
| 3854 } | 4017 } |
| 3855 } | 4018 } |
| 3856 | 4019 |
| 3857 | 4020 |
| 3858 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { | 4021 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { |
| 3859 for (int i = 0; i < statements->length(); i++) { | 4022 for (int i = 0; i < statements->length(); i++) { |
| 3860 CHECK_ALIVE(Visit(statements->at(i))); | 4023 CHECK_ALIVE(Visit(statements->at(i))); |
| 3861 } | 4024 } |
| 3862 } | 4025 } |
| 3863 | 4026 |
| 3864 | 4027 |
| 3865 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { | 4028 HBasicBlock* HOptimizedGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
| 3866 HBasicBlock* b = graph()->CreateBasicBlock(); | 4029 HBasicBlock* b = graph()->CreateBasicBlock(); |
| 3867 b->SetInitialEnvironment(env); | 4030 b->SetInitialEnvironment(env); |
| 3868 return b; | 4031 return b; |
| 3869 } | 4032 } |
| 3870 | 4033 |
| 3871 | 4034 |
| 3872 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { | 4035 HBasicBlock* HOptimizedGraphBuilder::CreateLoopHeaderBlock() { |
| 3873 HBasicBlock* header = graph()->CreateBasicBlock(); | 4036 HBasicBlock* header = graph()->CreateBasicBlock(); |
| 3874 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 4037 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
| 3875 header->SetInitialEnvironment(entry_env); | 4038 header->SetInitialEnvironment(entry_env); |
| 3876 header->AttachLoopInformation(); | 4039 header->AttachLoopInformation(); |
| 3877 return header; | 4040 return header; |
| 3878 } | 4041 } |
| 3879 | 4042 |
| 3880 | 4043 |
| 3881 void HGraphBuilder::VisitBlock(Block* stmt) { | 4044 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) { |
| 3882 ASSERT(!HasStackOverflow()); | 4045 ASSERT(!HasStackOverflow()); |
| 3883 ASSERT(current_block() != NULL); | 4046 ASSERT(current_block() != NULL); |
| 3884 ASSERT(current_block()->HasPredecessor()); | 4047 ASSERT(current_block()->HasPredecessor()); |
| 3885 if (stmt->scope() != NULL) { | 4048 if (stmt->scope() != NULL) { |
| 3886 return Bailout("ScopedBlock"); | 4049 return Bailout("ScopedBlock"); |
| 3887 } | 4050 } |
| 3888 BreakAndContinueInfo break_info(stmt); | 4051 BreakAndContinueInfo break_info(stmt); |
| 3889 { BreakAndContinueScope push(&break_info, this); | 4052 { BreakAndContinueScope push(&break_info, this); |
| 3890 CHECK_BAILOUT(VisitStatements(stmt->statements())); | 4053 CHECK_BAILOUT(VisitStatements(stmt->statements())); |
| 3891 } | 4054 } |
| 3892 HBasicBlock* break_block = break_info.break_block(); | 4055 HBasicBlock* break_block = break_info.break_block(); |
| 3893 if (break_block != NULL) { | 4056 if (break_block != NULL) { |
| 3894 if (current_block() != NULL) current_block()->Goto(break_block); | 4057 if (current_block() != NULL) current_block()->Goto(break_block); |
| 3895 break_block->SetJoinId(stmt->ExitId()); | 4058 break_block->SetJoinId(stmt->ExitId()); |
| 3896 set_current_block(break_block); | 4059 set_current_block(break_block); |
| 3897 } | 4060 } |
| 3898 } | 4061 } |
| 3899 | 4062 |
| 3900 | 4063 |
| 3901 void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { | 4064 void HOptimizedGraphBuilder::VisitExpressionStatement( |
| 4065 ExpressionStatement* stmt) { | |
| 3902 ASSERT(!HasStackOverflow()); | 4066 ASSERT(!HasStackOverflow()); |
| 3903 ASSERT(current_block() != NULL); | 4067 ASSERT(current_block() != NULL); |
| 3904 ASSERT(current_block()->HasPredecessor()); | 4068 ASSERT(current_block()->HasPredecessor()); |
| 3905 VisitForEffect(stmt->expression()); | 4069 VisitForEffect(stmt->expression()); |
| 3906 } | 4070 } |
| 3907 | 4071 |
| 3908 | 4072 |
| 3909 void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { | 4073 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { |
| 3910 ASSERT(!HasStackOverflow()); | 4074 ASSERT(!HasStackOverflow()); |
| 3911 ASSERT(current_block() != NULL); | 4075 ASSERT(current_block() != NULL); |
| 3912 ASSERT(current_block()->HasPredecessor()); | 4076 ASSERT(current_block()->HasPredecessor()); |
| 3913 } | 4077 } |
| 3914 | 4078 |
| 3915 | 4079 |
| 3916 void HGraphBuilder::VisitIfStatement(IfStatement* stmt) { | 4080 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
| 3917 ASSERT(!HasStackOverflow()); | 4081 ASSERT(!HasStackOverflow()); |
| 3918 ASSERT(current_block() != NULL); | 4082 ASSERT(current_block() != NULL); |
| 3919 ASSERT(current_block()->HasPredecessor()); | 4083 ASSERT(current_block()->HasPredecessor()); |
| 3920 if (stmt->condition()->ToBooleanIsTrue()) { | 4084 if (stmt->condition()->ToBooleanIsTrue()) { |
| 3921 AddSimulate(stmt->ThenId()); | 4085 AddSimulate(stmt->ThenId()); |
| 3922 Visit(stmt->then_statement()); | 4086 Visit(stmt->then_statement()); |
| 3923 } else if (stmt->condition()->ToBooleanIsFalse()) { | 4087 } else if (stmt->condition()->ToBooleanIsFalse()) { |
| 3924 AddSimulate(stmt->ElseId()); | 4088 AddSimulate(stmt->ElseId()); |
| 3925 Visit(stmt->else_statement()); | 4089 Visit(stmt->else_statement()); |
| 3926 } else { | 4090 } else { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 3945 } else { | 4109 } else { |
| 3946 cond_false = NULL; | 4110 cond_false = NULL; |
| 3947 } | 4111 } |
| 3948 | 4112 |
| 3949 HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId()); | 4113 HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId()); |
| 3950 set_current_block(join); | 4114 set_current_block(join); |
| 3951 } | 4115 } |
| 3952 } | 4116 } |
| 3953 | 4117 |
| 3954 | 4118 |
| 3955 HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get( | 4119 HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get( |
| 3956 BreakableStatement* stmt, | 4120 BreakableStatement* stmt, |
| 3957 BreakType type, | 4121 BreakType type, |
| 3958 int* drop_extra) { | 4122 int* drop_extra) { |
| 3959 *drop_extra = 0; | 4123 *drop_extra = 0; |
| 3960 BreakAndContinueScope* current = this; | 4124 BreakAndContinueScope* current = this; |
| 3961 while (current != NULL && current->info()->target() != stmt) { | 4125 while (current != NULL && current->info()->target() != stmt) { |
| 3962 *drop_extra += current->info()->drop_extra(); | 4126 *drop_extra += current->info()->drop_extra(); |
| 3963 current = current->next(); | 4127 current = current->next(); |
| 3964 } | 4128 } |
| 3965 ASSERT(current != NULL); // Always found (unless stack is malformed). | 4129 ASSERT(current != NULL); // Always found (unless stack is malformed). |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 3984 block = current->owner()->graph()->CreateBasicBlock(); | 4148 block = current->owner()->graph()->CreateBasicBlock(); |
| 3985 current->info()->set_continue_block(block); | 4149 current->info()->set_continue_block(block); |
| 3986 } | 4150 } |
| 3987 break; | 4151 break; |
| 3988 } | 4152 } |
| 3989 | 4153 |
| 3990 return block; | 4154 return block; |
| 3991 } | 4155 } |
| 3992 | 4156 |
| 3993 | 4157 |
| 3994 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { | 4158 void HOptimizedGraphBuilder::VisitContinueStatement( |
| 4159 ContinueStatement* stmt) { | |
| 3995 ASSERT(!HasStackOverflow()); | 4160 ASSERT(!HasStackOverflow()); |
| 3996 ASSERT(current_block() != NULL); | 4161 ASSERT(current_block() != NULL); |
| 3997 ASSERT(current_block()->HasPredecessor()); | 4162 ASSERT(current_block()->HasPredecessor()); |
| 3998 int drop_extra = 0; | 4163 int drop_extra = 0; |
| 3999 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), | 4164 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), |
| 4000 CONTINUE, | 4165 CONTINUE, |
| 4001 &drop_extra); | 4166 &drop_extra); |
| 4002 Drop(drop_extra); | 4167 Drop(drop_extra); |
| 4003 current_block()->Goto(continue_block); | 4168 current_block()->Goto(continue_block); |
| 4004 set_current_block(NULL); | 4169 set_current_block(NULL); |
| 4005 } | 4170 } |
| 4006 | 4171 |
| 4007 | 4172 |
| 4008 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 4173 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
| 4009 ASSERT(!HasStackOverflow()); | 4174 ASSERT(!HasStackOverflow()); |
| 4010 ASSERT(current_block() != NULL); | 4175 ASSERT(current_block() != NULL); |
| 4011 ASSERT(current_block()->HasPredecessor()); | 4176 ASSERT(current_block()->HasPredecessor()); |
| 4012 int drop_extra = 0; | 4177 int drop_extra = 0; |
| 4013 HBasicBlock* break_block = break_scope()->Get(stmt->target(), | 4178 HBasicBlock* break_block = break_scope()->Get(stmt->target(), |
| 4014 BREAK, | 4179 BREAK, |
| 4015 &drop_extra); | 4180 &drop_extra); |
| 4016 Drop(drop_extra); | 4181 Drop(drop_extra); |
| 4017 current_block()->Goto(break_block); | 4182 current_block()->Goto(break_block); |
| 4018 set_current_block(NULL); | 4183 set_current_block(NULL); |
| 4019 } | 4184 } |
| 4020 | 4185 |
| 4021 | 4186 |
| 4022 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 4187 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
| 4023 ASSERT(!HasStackOverflow()); | 4188 ASSERT(!HasStackOverflow()); |
| 4024 ASSERT(current_block() != NULL); | 4189 ASSERT(current_block() != NULL); |
| 4025 ASSERT(current_block()->HasPredecessor()); | 4190 ASSERT(current_block()->HasPredecessor()); |
| 4026 FunctionState* state = function_state(); | 4191 FunctionState* state = function_state(); |
| 4027 AstContext* context = call_context(); | 4192 AstContext* context = call_context(); |
| 4028 if (context == NULL) { | 4193 if (context == NULL) { |
| 4029 // Not an inlined return, so an actual one. | 4194 // Not an inlined return, so an actual one. |
| 4030 CHECK_ALIVE(VisitForValue(stmt->expression())); | 4195 CHECK_ALIVE(VisitForValue(stmt->expression())); |
| 4031 HValue* result = environment()->Pop(); | 4196 HValue* result = environment()->Pop(); |
| 4032 current_block()->FinishExit(new(zone()) HReturn(result)); | 4197 current_block()->FinishExit(new(zone()) HReturn(result)); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4084 } else { | 4249 } else { |
| 4085 ASSERT(context->IsValue()); | 4250 ASSERT(context->IsValue()); |
| 4086 CHECK_ALIVE(VisitForValue(stmt->expression())); | 4251 CHECK_ALIVE(VisitForValue(stmt->expression())); |
| 4087 current_block()->AddLeaveInlined(Pop(), state); | 4252 current_block()->AddLeaveInlined(Pop(), state); |
| 4088 } | 4253 } |
| 4089 } | 4254 } |
| 4090 set_current_block(NULL); | 4255 set_current_block(NULL); |
| 4091 } | 4256 } |
| 4092 | 4257 |
| 4093 | 4258 |
| 4094 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { | 4259 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { |
| 4095 ASSERT(!HasStackOverflow()); | 4260 ASSERT(!HasStackOverflow()); |
| 4096 ASSERT(current_block() != NULL); | 4261 ASSERT(current_block() != NULL); |
| 4097 ASSERT(current_block()->HasPredecessor()); | 4262 ASSERT(current_block()->HasPredecessor()); |
| 4098 return Bailout("WithStatement"); | 4263 return Bailout("WithStatement"); |
| 4099 } | 4264 } |
| 4100 | 4265 |
| 4101 | 4266 |
| 4102 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 4267 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
| 4103 ASSERT(!HasStackOverflow()); | 4268 ASSERT(!HasStackOverflow()); |
| 4104 ASSERT(current_block() != NULL); | 4269 ASSERT(current_block() != NULL); |
| 4105 ASSERT(current_block()->HasPredecessor()); | 4270 ASSERT(current_block()->HasPredecessor()); |
| 4106 // We only optimize switch statements with smi-literal smi comparisons, | 4271 // We only optimize switch statements with smi-literal smi comparisons, |
| 4107 // with a bounded number of clauses. | 4272 // with a bounded number of clauses. |
| 4108 const int kCaseClauseLimit = 128; | 4273 const int kCaseClauseLimit = 128; |
| 4109 ZoneList<CaseClause*>* clauses = stmt->cases(); | 4274 ZoneList<CaseClause*>* clauses = stmt->cases(); |
| 4110 int clause_count = clauses->length(); | 4275 int clause_count = clauses->length(); |
| 4111 if (clause_count > kCaseClauseLimit) { | 4276 if (clause_count > kCaseClauseLimit) { |
| 4112 return Bailout("SwitchStatement: too many clauses"); | 4277 return Bailout("SwitchStatement: too many clauses"); |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4278 stmt->ExitId())); | 4443 stmt->ExitId())); |
| 4279 } else { | 4444 } else { |
| 4280 if (fall_through_block != NULL) fall_through_block->Goto(break_block); | 4445 if (fall_through_block != NULL) fall_through_block->Goto(break_block); |
| 4281 if (last_block != NULL) last_block->Goto(break_block); | 4446 if (last_block != NULL) last_block->Goto(break_block); |
| 4282 break_block->SetJoinId(stmt->ExitId()); | 4447 break_block->SetJoinId(stmt->ExitId()); |
| 4283 set_current_block(break_block); | 4448 set_current_block(break_block); |
| 4284 } | 4449 } |
| 4285 } | 4450 } |
| 4286 | 4451 |
| 4287 | 4452 |
| 4288 bool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { | 4453 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { |
| 4289 return statement->OsrEntryId() == info()->osr_ast_id(); | 4454 return statement->OsrEntryId() == info()->osr_ast_id(); |
| 4290 } | 4455 } |
| 4291 | 4456 |
| 4292 | 4457 |
| 4293 bool HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { | 4458 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { |
| 4294 if (!HasOsrEntryAt(statement)) return false; | 4459 if (!HasOsrEntryAt(statement)) return false; |
| 4295 | 4460 |
| 4296 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); | 4461 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); |
| 4297 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); | 4462 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); |
| 4298 HValue* true_value = graph()->GetConstantTrue(); | 4463 HValue* true_value = graph()->GetConstantTrue(); |
| 4299 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); | 4464 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); |
| 4300 current_block()->Finish(test); | 4465 current_block()->Finish(test); |
| 4301 | 4466 |
| 4302 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); | 4467 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); |
| 4303 non_osr_entry->Goto(loop_predecessor); | 4468 non_osr_entry->Goto(loop_predecessor); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 4333 HContext* context = new(zone()) HContext; | 4498 HContext* context = new(zone()) HContext; |
| 4334 AddInstruction(context); | 4499 AddInstruction(context); |
| 4335 environment()->BindContext(context); | 4500 environment()->BindContext(context); |
| 4336 current_block()->Goto(loop_predecessor); | 4501 current_block()->Goto(loop_predecessor); |
| 4337 loop_predecessor->SetJoinId(statement->EntryId()); | 4502 loop_predecessor->SetJoinId(statement->EntryId()); |
| 4338 set_current_block(loop_predecessor); | 4503 set_current_block(loop_predecessor); |
| 4339 return true; | 4504 return true; |
| 4340 } | 4505 } |
| 4341 | 4506 |
| 4342 | 4507 |
| 4343 void HGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 4508 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
| 4344 HBasicBlock* loop_entry, | 4509 HBasicBlock* loop_entry, |
| 4345 BreakAndContinueInfo* break_info) { | 4510 BreakAndContinueInfo* break_info) { |
| 4346 BreakAndContinueScope push(break_info, this); | 4511 BreakAndContinueScope push(break_info, this); |
| 4347 AddSimulate(stmt->StackCheckId()); | 4512 AddSimulate(stmt->StackCheckId()); |
| 4348 HValue* context = environment()->LookupContext(); | 4513 HValue* context = environment()->LookupContext(); |
| 4349 HStackCheck* stack_check = | 4514 HStackCheck* stack_check = |
| 4350 new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch); | 4515 new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch); |
| 4351 AddInstruction(stack_check); | 4516 AddInstruction(stack_check); |
| 4352 ASSERT(loop_entry->IsLoopHeader()); | 4517 ASSERT(loop_entry->IsLoopHeader()); |
| 4353 loop_entry->loop_information()->set_stack_check(stack_check); | 4518 loop_entry->loop_information()->set_stack_check(stack_check); |
| 4354 CHECK_BAILOUT(Visit(stmt->body())); | 4519 CHECK_BAILOUT(Visit(stmt->body())); |
| 4355 } | 4520 } |
| 4356 | 4521 |
| 4357 | 4522 |
| 4358 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 4523 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 4359 ASSERT(!HasStackOverflow()); | 4524 ASSERT(!HasStackOverflow()); |
| 4360 ASSERT(current_block() != NULL); | 4525 ASSERT(current_block() != NULL); |
| 4361 ASSERT(current_block()->HasPredecessor()); | 4526 ASSERT(current_block()->HasPredecessor()); |
| 4362 ASSERT(current_block() != NULL); | 4527 ASSERT(current_block() != NULL); |
| 4363 bool osr_entry = PreProcessOsrEntry(stmt); | 4528 bool osr_entry = PreProcessOsrEntry(stmt); |
| 4364 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 4529 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
| 4365 current_block()->Goto(loop_entry); | 4530 current_block()->Goto(loop_entry); |
| 4366 set_current_block(loop_entry); | 4531 set_current_block(loop_entry); |
| 4367 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | 4532 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); |
| 4368 | 4533 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 4391 } | 4556 } |
| 4392 HBasicBlock* loop_exit = CreateLoop(stmt, | 4557 HBasicBlock* loop_exit = CreateLoop(stmt, |
| 4393 loop_entry, | 4558 loop_entry, |
| 4394 body_exit, | 4559 body_exit, |
| 4395 loop_successor, | 4560 loop_successor, |
| 4396 break_info.break_block()); | 4561 break_info.break_block()); |
| 4397 set_current_block(loop_exit); | 4562 set_current_block(loop_exit); |
| 4398 } | 4563 } |
| 4399 | 4564 |
| 4400 | 4565 |
| 4401 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 4566 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
| 4402 ASSERT(!HasStackOverflow()); | 4567 ASSERT(!HasStackOverflow()); |
| 4403 ASSERT(current_block() != NULL); | 4568 ASSERT(current_block() != NULL); |
| 4404 ASSERT(current_block()->HasPredecessor()); | 4569 ASSERT(current_block()->HasPredecessor()); |
| 4405 ASSERT(current_block() != NULL); | 4570 ASSERT(current_block() != NULL); |
| 4406 bool osr_entry = PreProcessOsrEntry(stmt); | 4571 bool osr_entry = PreProcessOsrEntry(stmt); |
| 4407 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 4572 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
| 4408 current_block()->Goto(loop_entry); | 4573 current_block()->Goto(loop_entry); |
| 4409 set_current_block(loop_entry); | 4574 set_current_block(loop_entry); |
| 4410 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | 4575 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); |
| 4411 | 4576 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 4435 JoinContinue(stmt, current_block(), break_info.continue_block()); | 4600 JoinContinue(stmt, current_block(), break_info.continue_block()); |
| 4436 HBasicBlock* loop_exit = CreateLoop(stmt, | 4601 HBasicBlock* loop_exit = CreateLoop(stmt, |
| 4437 loop_entry, | 4602 loop_entry, |
| 4438 body_exit, | 4603 body_exit, |
| 4439 loop_successor, | 4604 loop_successor, |
| 4440 break_info.break_block()); | 4605 break_info.break_block()); |
| 4441 set_current_block(loop_exit); | 4606 set_current_block(loop_exit); |
| 4442 } | 4607 } |
| 4443 | 4608 |
| 4444 | 4609 |
| 4445 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { | 4610 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) { |
| 4446 ASSERT(!HasStackOverflow()); | 4611 ASSERT(!HasStackOverflow()); |
| 4447 ASSERT(current_block() != NULL); | 4612 ASSERT(current_block() != NULL); |
| 4448 ASSERT(current_block()->HasPredecessor()); | 4613 ASSERT(current_block()->HasPredecessor()); |
| 4449 if (stmt->init() != NULL) { | 4614 if (stmt->init() != NULL) { |
| 4450 CHECK_ALIVE(Visit(stmt->init())); | 4615 CHECK_ALIVE(Visit(stmt->init())); |
| 4451 } | 4616 } |
| 4452 ASSERT(current_block() != NULL); | 4617 ASSERT(current_block() != NULL); |
| 4453 bool osr_entry = PreProcessOsrEntry(stmt); | 4618 bool osr_entry = PreProcessOsrEntry(stmt); |
| 4454 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 4619 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
| 4455 current_block()->Goto(loop_entry); | 4620 current_block()->Goto(loop_entry); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4487 | 4652 |
| 4488 HBasicBlock* loop_exit = CreateLoop(stmt, | 4653 HBasicBlock* loop_exit = CreateLoop(stmt, |
| 4489 loop_entry, | 4654 loop_entry, |
| 4490 body_exit, | 4655 body_exit, |
| 4491 loop_successor, | 4656 loop_successor, |
| 4492 break_info.break_block()); | 4657 break_info.break_block()); |
| 4493 set_current_block(loop_exit); | 4658 set_current_block(loop_exit); |
| 4494 } | 4659 } |
| 4495 | 4660 |
| 4496 | 4661 |
| 4497 void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 4662 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
| 4498 ASSERT(!HasStackOverflow()); | 4663 ASSERT(!HasStackOverflow()); |
| 4499 ASSERT(current_block() != NULL); | 4664 ASSERT(current_block() != NULL); |
| 4500 ASSERT(current_block()->HasPredecessor()); | 4665 ASSERT(current_block()->HasPredecessor()); |
| 4501 | 4666 |
| 4502 if (!FLAG_optimize_for_in) { | 4667 if (!FLAG_optimize_for_in) { |
| 4503 return Bailout("ForInStatement optimization is disabled"); | 4668 return Bailout("ForInStatement optimization is disabled"); |
| 4504 } | 4669 } |
| 4505 | 4670 |
| 4506 if (!oracle()->IsForInFastCase(stmt)) { | 4671 if (!oracle()->IsForInFastCase(stmt)) { |
| 4507 return Bailout("ForInStatement is not fast case"); | 4672 return Bailout("ForInStatement is not fast case"); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4608 HBasicBlock* loop_exit = CreateLoop(stmt, | 4773 HBasicBlock* loop_exit = CreateLoop(stmt, |
| 4609 loop_entry, | 4774 loop_entry, |
| 4610 body_exit, | 4775 body_exit, |
| 4611 loop_successor, | 4776 loop_successor, |
| 4612 break_info.break_block()); | 4777 break_info.break_block()); |
| 4613 | 4778 |
| 4614 set_current_block(loop_exit); | 4779 set_current_block(loop_exit); |
| 4615 } | 4780 } |
| 4616 | 4781 |
| 4617 | 4782 |
| 4618 void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 4783 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 4619 ASSERT(!HasStackOverflow()); | 4784 ASSERT(!HasStackOverflow()); |
| 4620 ASSERT(current_block() != NULL); | 4785 ASSERT(current_block() != NULL); |
| 4621 ASSERT(current_block()->HasPredecessor()); | 4786 ASSERT(current_block()->HasPredecessor()); |
| 4622 return Bailout("TryCatchStatement"); | 4787 return Bailout("TryCatchStatement"); |
| 4623 } | 4788 } |
| 4624 | 4789 |
| 4625 | 4790 |
| 4626 void HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 4791 void HOptimizedGraphBuilder::VisitTryFinallyStatement( |
| 4792 TryFinallyStatement* stmt) { | |
| 4627 ASSERT(!HasStackOverflow()); | 4793 ASSERT(!HasStackOverflow()); |
| 4628 ASSERT(current_block() != NULL); | 4794 ASSERT(current_block() != NULL); |
| 4629 ASSERT(current_block()->HasPredecessor()); | 4795 ASSERT(current_block()->HasPredecessor()); |
| 4630 return Bailout("TryFinallyStatement"); | 4796 return Bailout("TryFinallyStatement"); |
| 4631 } | 4797 } |
| 4632 | 4798 |
| 4633 | 4799 |
| 4634 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 4800 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 4635 ASSERT(!HasStackOverflow()); | 4801 ASSERT(!HasStackOverflow()); |
| 4636 ASSERT(current_block() != NULL); | 4802 ASSERT(current_block() != NULL); |
| 4637 ASSERT(current_block()->HasPredecessor()); | 4803 ASSERT(current_block()->HasPredecessor()); |
| 4638 return Bailout("DebuggerStatement"); | 4804 return Bailout("DebuggerStatement"); |
| 4639 } | 4805 } |
| 4640 | 4806 |
| 4641 | 4807 |
| 4642 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( | 4808 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( |
| 4643 Code* unoptimized_code, FunctionLiteral* expr) { | 4809 Code* unoptimized_code, FunctionLiteral* expr) { |
| 4644 int start_position = expr->start_position(); | 4810 int start_position = expr->start_position(); |
| 4645 RelocIterator it(unoptimized_code); | 4811 RelocIterator it(unoptimized_code); |
| 4646 for (;!it.done(); it.next()) { | 4812 for (;!it.done(); it.next()) { |
| 4647 RelocInfo* rinfo = it.rinfo(); | 4813 RelocInfo* rinfo = it.rinfo(); |
| 4648 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; | 4814 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; |
| 4649 Object* obj = rinfo->target_object(); | 4815 Object* obj = rinfo->target_object(); |
| 4650 if (obj->IsSharedFunctionInfo()) { | 4816 if (obj->IsSharedFunctionInfo()) { |
| 4651 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 4817 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
| 4652 if (shared->start_position() == start_position) { | 4818 if (shared->start_position() == start_position) { |
| 4653 return Handle<SharedFunctionInfo>(shared); | 4819 return Handle<SharedFunctionInfo>(shared); |
| 4654 } | 4820 } |
| 4655 } | 4821 } |
| 4656 } | 4822 } |
| 4657 | 4823 |
| 4658 return Handle<SharedFunctionInfo>(); | 4824 return Handle<SharedFunctionInfo>(); |
| 4659 } | 4825 } |
| 4660 | 4826 |
| 4661 | 4827 |
| 4662 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 4828 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 4663 ASSERT(!HasStackOverflow()); | 4829 ASSERT(!HasStackOverflow()); |
| 4664 ASSERT(current_block() != NULL); | 4830 ASSERT(current_block() != NULL); |
| 4665 ASSERT(current_block()->HasPredecessor()); | 4831 ASSERT(current_block()->HasPredecessor()); |
| 4666 Handle<SharedFunctionInfo> shared_info = | 4832 Handle<SharedFunctionInfo> shared_info = |
| 4667 SearchSharedFunctionInfo(info()->shared_info()->code(), | 4833 SearchSharedFunctionInfo(info()->shared_info()->code(), |
| 4668 expr); | 4834 expr); |
| 4669 if (shared_info.is_null()) { | 4835 if (shared_info.is_null()) { |
| 4670 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); | 4836 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); |
| 4671 } | 4837 } |
| 4672 // We also have a stack overflow if the recursive compilation did. | 4838 // We also have a stack overflow if the recursive compilation did. |
| 4673 if (HasStackOverflow()) return; | 4839 if (HasStackOverflow()) return; |
| 4674 HValue* context = environment()->LookupContext(); | 4840 HValue* context = environment()->LookupContext(); |
| 4675 HFunctionLiteral* instr = | 4841 HFunctionLiteral* instr = |
| 4676 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); | 4842 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); |
| 4677 return ast_context()->ReturnInstruction(instr, expr->id()); | 4843 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4678 } | 4844 } |
| 4679 | 4845 |
| 4680 | 4846 |
| 4681 void HGraphBuilder::VisitSharedFunctionInfoLiteral( | 4847 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( |
| 4682 SharedFunctionInfoLiteral* expr) { | 4848 SharedFunctionInfoLiteral* expr) { |
| 4683 ASSERT(!HasStackOverflow()); | 4849 ASSERT(!HasStackOverflow()); |
| 4684 ASSERT(current_block() != NULL); | 4850 ASSERT(current_block() != NULL); |
| 4685 ASSERT(current_block()->HasPredecessor()); | 4851 ASSERT(current_block()->HasPredecessor()); |
| 4686 return Bailout("SharedFunctionInfoLiteral"); | 4852 return Bailout("SharedFunctionInfoLiteral"); |
| 4687 } | 4853 } |
| 4688 | 4854 |
| 4689 | 4855 |
| 4690 void HGraphBuilder::VisitConditional(Conditional* expr) { | 4856 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) { |
| 4691 ASSERT(!HasStackOverflow()); | 4857 ASSERT(!HasStackOverflow()); |
| 4692 ASSERT(current_block() != NULL); | 4858 ASSERT(current_block() != NULL); |
| 4693 ASSERT(current_block()->HasPredecessor()); | 4859 ASSERT(current_block()->HasPredecessor()); |
| 4694 HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 4860 HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
| 4695 HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 4861 HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
| 4696 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); | 4862 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); |
| 4697 | 4863 |
| 4698 // Visit the true and false subexpressions in the same AST context as the | 4864 // Visit the true and false subexpressions in the same AST context as the |
| 4699 // whole expression. | 4865 // whole expression. |
| 4700 if (cond_true->HasPredecessor()) { | 4866 if (cond_true->HasPredecessor()) { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 4718 if (!ast_context()->IsTest()) { | 4884 if (!ast_context()->IsTest()) { |
| 4719 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); | 4885 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); |
| 4720 set_current_block(join); | 4886 set_current_block(join); |
| 4721 if (join != NULL && !ast_context()->IsEffect()) { | 4887 if (join != NULL && !ast_context()->IsEffect()) { |
| 4722 return ast_context()->ReturnValue(Pop()); | 4888 return ast_context()->ReturnValue(Pop()); |
| 4723 } | 4889 } |
| 4724 } | 4890 } |
| 4725 } | 4891 } |
| 4726 | 4892 |
| 4727 | 4893 |
| 4728 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( | 4894 HOptimizedGraphBuilder::GlobalPropertyAccess |
| 4895 HOptimizedGraphBuilder::LookupGlobalProperty( | |
|
Jakob Kummerow
2012/11/28 16:28:22
nit: I think I'd indent this line (by 4 spaces; an
danno
2012/11/30 16:23:24
Done.
| |
| 4729 Variable* var, LookupResult* lookup, bool is_store) { | 4896 Variable* var, LookupResult* lookup, bool is_store) { |
| 4730 if (var->is_this() || !info()->has_global_object()) { | 4897 if (var->is_this() || !info()->has_global_object()) { |
| 4731 return kUseGeneric; | 4898 return kUseGeneric; |
| 4732 } | 4899 } |
| 4733 Handle<GlobalObject> global(info()->global_object()); | 4900 Handle<GlobalObject> global(info()->global_object()); |
| 4734 global->Lookup(*var->name(), lookup); | 4901 global->Lookup(*var->name(), lookup); |
| 4735 if (!lookup->IsNormal() || | 4902 if (!lookup->IsNormal() || |
| 4736 (is_store && lookup->IsReadOnly()) || | 4903 (is_store && lookup->IsReadOnly()) || |
| 4737 lookup->holder() != *global) { | 4904 lookup->holder() != *global) { |
| 4738 return kUseGeneric; | 4905 return kUseGeneric; |
| 4739 } | 4906 } |
| 4740 | 4907 |
| 4741 return kUseCell; | 4908 return kUseCell; |
| 4742 } | 4909 } |
| 4743 | 4910 |
| 4744 | 4911 |
| 4745 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { | 4912 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { |
| 4746 ASSERT(var->IsContextSlot()); | 4913 ASSERT(var->IsContextSlot()); |
| 4747 HValue* context = environment()->LookupContext(); | 4914 HValue* context = environment()->LookupContext(); |
| 4748 int length = info()->scope()->ContextChainLength(var->scope()); | 4915 int length = info()->scope()->ContextChainLength(var->scope()); |
| 4749 while (length-- > 0) { | 4916 while (length-- > 0) { |
| 4750 HInstruction* context_instruction = new(zone()) HOuterContext(context); | 4917 HInstruction* context_instruction = new(zone()) HOuterContext(context); |
| 4751 AddInstruction(context_instruction); | 4918 AddInstruction(context_instruction); |
| 4752 context = context_instruction; | 4919 context = context_instruction; |
| 4753 } | 4920 } |
| 4754 return context; | 4921 return context; |
| 4755 } | 4922 } |
| 4756 | 4923 |
| 4757 | 4924 |
| 4758 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 4925 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 4759 ASSERT(!HasStackOverflow()); | 4926 ASSERT(!HasStackOverflow()); |
| 4760 ASSERT(current_block() != NULL); | 4927 ASSERT(current_block() != NULL); |
| 4761 ASSERT(current_block()->HasPredecessor()); | 4928 ASSERT(current_block()->HasPredecessor()); |
| 4762 Variable* variable = expr->var(); | 4929 Variable* variable = expr->var(); |
| 4763 switch (variable->location()) { | 4930 switch (variable->location()) { |
| 4764 case Variable::UNALLOCATED: { | 4931 case Variable::UNALLOCATED: { |
| 4765 if (IsLexicalVariableMode(variable->mode())) { | 4932 if (IsLexicalVariableMode(variable->mode())) { |
| 4766 // TODO(rossberg): should this be an ASSERT? | 4933 // TODO(rossberg): should this be an ASSERT? |
| 4767 return Bailout("reference to global lexical variable"); | 4934 return Bailout("reference to global lexical variable"); |
| 4768 } | 4935 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4821 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable); | 4988 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable); |
| 4822 return ast_context()->ReturnInstruction(instr, expr->id()); | 4989 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4823 } | 4990 } |
| 4824 | 4991 |
| 4825 case Variable::LOOKUP: | 4992 case Variable::LOOKUP: |
| 4826 return Bailout("reference to a variable which requires dynamic lookup"); | 4993 return Bailout("reference to a variable which requires dynamic lookup"); |
| 4827 } | 4994 } |
| 4828 } | 4995 } |
| 4829 | 4996 |
| 4830 | 4997 |
| 4831 void HGraphBuilder::VisitLiteral(Literal* expr) { | 4998 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { |
| 4832 ASSERT(!HasStackOverflow()); | 4999 ASSERT(!HasStackOverflow()); |
| 4833 ASSERT(current_block() != NULL); | 5000 ASSERT(current_block() != NULL); |
| 4834 ASSERT(current_block()->HasPredecessor()); | 5001 ASSERT(current_block()->HasPredecessor()); |
| 4835 HConstant* instr = | 5002 HConstant* instr = |
| 4836 new(zone()) HConstant(expr->handle(), Representation::None()); | 5003 new(zone()) HConstant(expr->handle(), Representation::None()); |
| 4837 return ast_context()->ReturnInstruction(instr, expr->id()); | 5004 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4838 } | 5005 } |
| 4839 | 5006 |
| 4840 | 5007 |
| 4841 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 5008 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 4842 ASSERT(!HasStackOverflow()); | 5009 ASSERT(!HasStackOverflow()); |
| 4843 ASSERT(current_block() != NULL); | 5010 ASSERT(current_block() != NULL); |
| 4844 ASSERT(current_block()->HasPredecessor()); | 5011 ASSERT(current_block()->HasPredecessor()); |
| 4845 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 5012 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 4846 Handle<FixedArray> literals(closure->literals()); | 5013 Handle<FixedArray> literals(closure->literals()); |
| 4847 HValue* context = environment()->LookupContext(); | 5014 HValue* context = environment()->LookupContext(); |
| 4848 | 5015 |
| 4849 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, | 5016 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, |
| 4850 literals, | 5017 literals, |
| 4851 expr->pattern(), | 5018 expr->pattern(), |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4990 } | 5157 } |
| 4991 } | 5158 } |
| 4992 } | 5159 } |
| 4993 } | 5160 } |
| 4994 | 5161 |
| 4995 *total_size += boilerplate->map()->instance_size(); | 5162 *total_size += boilerplate->map()->instance_size(); |
| 4996 return true; | 5163 return true; |
| 4997 } | 5164 } |
| 4998 | 5165 |
| 4999 | 5166 |
| 5000 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 5167 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| 5001 ASSERT(!HasStackOverflow()); | 5168 ASSERT(!HasStackOverflow()); |
| 5002 ASSERT(current_block() != NULL); | 5169 ASSERT(current_block() != NULL); |
| 5003 ASSERT(current_block()->HasPredecessor()); | 5170 ASSERT(current_block()->HasPredecessor()); |
| 5004 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 5171 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 5005 HValue* context = environment()->LookupContext(); | 5172 HValue* context = environment()->LookupContext(); |
| 5006 HInstruction* literal; | 5173 HInstruction* literal; |
| 5007 | 5174 |
| 5008 // Check whether to use fast or slow deep-copying for boilerplate. | 5175 // Check whether to use fast or slow deep-copying for boilerplate. |
| 5009 int total_size = 0; | 5176 int total_size = 0; |
| 5010 int max_properties = HFastLiteral::kMaxLiteralProperties; | 5177 int max_properties = HFastLiteral::kMaxLiteralProperties; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5095 // (e.g. because of code motion). | 5262 // (e.g. because of code motion). |
| 5096 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); | 5263 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); |
| 5097 AddInstruction(result); | 5264 AddInstruction(result); |
| 5098 return ast_context()->ReturnValue(result); | 5265 return ast_context()->ReturnValue(result); |
| 5099 } else { | 5266 } else { |
| 5100 return ast_context()->ReturnValue(Pop()); | 5267 return ast_context()->ReturnValue(Pop()); |
| 5101 } | 5268 } |
| 5102 } | 5269 } |
| 5103 | 5270 |
| 5104 | 5271 |
| 5105 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 5272 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| 5106 ASSERT(!HasStackOverflow()); | 5273 ASSERT(!HasStackOverflow()); |
| 5107 ASSERT(current_block() != NULL); | 5274 ASSERT(current_block() != NULL); |
| 5108 ASSERT(current_block()->HasPredecessor()); | 5275 ASSERT(current_block()->HasPredecessor()); |
| 5109 ZoneList<Expression*>* subexprs = expr->values(); | 5276 ZoneList<Expression*>* subexprs = expr->values(); |
| 5110 int length = subexprs->length(); | 5277 int length = subexprs->length(); |
| 5111 HValue* context = environment()->LookupContext(); | 5278 HValue* context = environment()->LookupContext(); |
| 5112 HInstruction* literal; | 5279 HInstruction* literal; |
| 5113 | 5280 |
| 5114 Handle<FixedArray> literals(environment()->closure()->literals()); | 5281 Handle<FixedArray> literals(environment()->closure()->literals()); |
| 5115 Handle<Object> raw_boilerplate(literals->get(expr->literal_index())); | 5282 Handle<Object> raw_boilerplate(literals->get(expr->literal_index())); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5229 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); | 5396 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); |
| 5230 if (lookup->IsField()) { | 5397 if (lookup->IsField()) { |
| 5231 return lookup->GetLocalFieldIndexFromMap(*type); | 5398 return lookup->GetLocalFieldIndexFromMap(*type); |
| 5232 } else { | 5399 } else { |
| 5233 Map* transition = lookup->GetTransitionMapFromMap(*type); | 5400 Map* transition = lookup->GetTransitionMapFromMap(*type); |
| 5234 return transition->PropertyIndexFor(*name) - type->inobject_properties(); | 5401 return transition->PropertyIndexFor(*name) - type->inobject_properties(); |
| 5235 } | 5402 } |
| 5236 } | 5403 } |
| 5237 | 5404 |
| 5238 | 5405 |
| 5239 void HGraphBuilder::AddCheckMapsWithTransitions(HValue* object, | 5406 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, |
| 5240 Handle<Map> map) { | 5407 Handle<Map> map) { |
| 5241 AddInstruction(new(zone()) HCheckNonSmi(object)); | 5408 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 5242 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); | 5409 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
| 5243 } | 5410 } |
| 5244 | 5411 |
| 5245 | 5412 |
| 5246 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, | 5413 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( |
| 5247 Handle<String> name, | 5414 HValue* object, |
| 5248 HValue* value, | 5415 Handle<String> name, |
| 5249 Handle<Map> map, | 5416 HValue* value, |
| 5250 LookupResult* lookup) { | 5417 Handle<Map> map, |
| 5418 LookupResult* lookup) { | |
| 5251 ASSERT(lookup->IsFound()); | 5419 ASSERT(lookup->IsFound()); |
| 5252 // If the property does not exist yet, we have to check that it wasn't made | 5420 // If the property does not exist yet, we have to check that it wasn't made |
| 5253 // readonly or turned into a setter by some meanwhile modifications on the | 5421 // readonly or turned into a setter by some meanwhile modifications on the |
| 5254 // prototype chain. | 5422 // prototype chain. |
| 5255 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { | 5423 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { |
| 5256 Object* proto = map->prototype(); | 5424 Object* proto = map->prototype(); |
| 5257 // First check that the prototype chain isn't affected already. | 5425 // First check that the prototype chain isn't affected already. |
| 5258 LookupResult proto_result(isolate()); | 5426 LookupResult proto_result(isolate()); |
| 5259 proto->Lookup(*name, &proto_result); | 5427 proto->Lookup(*name, &proto_result); |
| 5260 if (proto_result.IsProperty()) { | 5428 if (proto_result.IsProperty()) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5292 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 5460 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
| 5293 instr->set_transition(transition); | 5461 instr->set_transition(transition); |
| 5294 // TODO(fschneider): Record the new map type of the object in the IR to | 5462 // TODO(fschneider): Record the new map type of the object in the IR to |
| 5295 // enable elimination of redundant checks after the transition store. | 5463 // enable elimination of redundant checks after the transition store. |
| 5296 instr->SetGVNFlag(kChangesMaps); | 5464 instr->SetGVNFlag(kChangesMaps); |
| 5297 } | 5465 } |
| 5298 return instr; | 5466 return instr; |
| 5299 } | 5467 } |
| 5300 | 5468 |
| 5301 | 5469 |
| 5302 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, | 5470 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( |
| 5303 Handle<String> name, | 5471 HValue* object, |
| 5304 HValue* value) { | 5472 Handle<String> name, |
| 5473 HValue* value) { | |
| 5305 HValue* context = environment()->LookupContext(); | 5474 HValue* context = environment()->LookupContext(); |
| 5306 return new(zone()) HStoreNamedGeneric( | 5475 return new(zone()) HStoreNamedGeneric( |
| 5307 context, | 5476 context, |
| 5308 object, | 5477 object, |
| 5309 name, | 5478 name, |
| 5310 value, | 5479 value, |
| 5311 function_strict_mode_flag()); | 5480 function_strict_mode_flag()); |
| 5312 } | 5481 } |
| 5313 | 5482 |
| 5314 | 5483 |
| 5315 HInstruction* HGraphBuilder::BuildCallSetter(HValue* object, | 5484 HInstruction* HOptimizedGraphBuilder::BuildCallSetter( |
| 5316 HValue* value, | 5485 HValue* object, |
| 5317 Handle<Map> map, | 5486 HValue* value, |
| 5318 Handle<JSFunction> setter, | 5487 Handle<Map> map, |
| 5319 Handle<JSObject> holder) { | 5488 Handle<JSFunction> setter, |
| 5489 Handle<JSObject> holder) { | |
| 5320 AddCheckConstantFunction(holder, object, map); | 5490 AddCheckConstantFunction(holder, object, map); |
| 5321 AddInstruction(new(zone()) HPushArgument(object)); | 5491 AddInstruction(new(zone()) HPushArgument(object)); |
| 5322 AddInstruction(new(zone()) HPushArgument(value)); | 5492 AddInstruction(new(zone()) HPushArgument(value)); |
| 5323 return new(zone()) HCallConstantFunction(setter, 2); | 5493 return new(zone()) HCallConstantFunction(setter, 2); |
| 5324 } | 5494 } |
| 5325 | 5495 |
| 5326 | 5496 |
| 5327 HInstruction* HGraphBuilder::BuildStoreNamedMonomorphic(HValue* object, | 5497 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( |
| 5328 Handle<String> name, | 5498 HValue* object, |
| 5329 HValue* value, | 5499 Handle<String> name, |
| 5330 Handle<Map> map) { | 5500 HValue* value, |
| 5501 Handle<Map> map) { | |
| 5331 // Handle a store to a known field. | 5502 // Handle a store to a known field. |
| 5332 LookupResult lookup(isolate()); | 5503 LookupResult lookup(isolate()); |
| 5333 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 5504 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| 5334 AddCheckMapsWithTransitions(object, map); | 5505 AddCheckMapsWithTransitions(object, map); |
| 5335 return BuildStoreNamedField(object, name, value, map, &lookup); | 5506 return BuildStoreNamedField(object, name, value, map, &lookup); |
| 5336 } | 5507 } |
| 5337 | 5508 |
| 5338 // No luck, do a generic store. | 5509 // No luck, do a generic store. |
| 5339 return BuildStoreNamedGeneric(object, name, value); | 5510 return BuildStoreNamedGeneric(object, name, value); |
| 5340 } | 5511 } |
| 5341 | 5512 |
| 5342 | 5513 |
| 5343 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, | 5514 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
| 5344 HValue* object, | 5515 Property* expr, |
| 5345 SmallMapList* types, | 5516 HValue* object, |
| 5346 Handle<String> name) { | 5517 SmallMapList* types, |
| 5518 Handle<String> name) { | |
| 5347 int count = 0; | 5519 int count = 0; |
| 5348 int previous_field_offset = 0; | 5520 int previous_field_offset = 0; |
| 5349 bool previous_field_is_in_object = false; | 5521 bool previous_field_is_in_object = false; |
| 5350 bool is_monomorphic_field = true; | 5522 bool is_monomorphic_field = true; |
| 5351 Handle<Map> map; | 5523 Handle<Map> map; |
| 5352 LookupResult lookup(isolate()); | 5524 LookupResult lookup(isolate()); |
| 5353 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 5525 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
| 5354 map = types->at(i); | 5526 map = types->at(i); |
| 5355 if (ComputeLoadStoreField(map, name, &lookup, false)) { | 5527 if (ComputeLoadStoreField(map, name, &lookup, false)) { |
| 5356 int index = ComputeLoadStoreFieldIndex(map, name, &lookup); | 5528 int index = ComputeLoadStoreFieldIndex(map, name, &lookup); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5388 types, | 5560 types, |
| 5389 name, | 5561 name, |
| 5390 zone()); | 5562 zone()); |
| 5391 } | 5563 } |
| 5392 | 5564 |
| 5393 instr->set_position(expr->position()); | 5565 instr->set_position(expr->position()); |
| 5394 return ast_context()->ReturnInstruction(instr, expr->id()); | 5566 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5395 } | 5567 } |
| 5396 | 5568 |
| 5397 | 5569 |
| 5398 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, | 5570 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| 5399 HValue* object, | 5571 Assignment* expr, |
| 5400 HValue* value, | 5572 HValue* object, |
| 5401 SmallMapList* types, | 5573 HValue* value, |
| 5402 Handle<String> name) { | 5574 SmallMapList* types, |
| 5575 Handle<String> name) { | |
| 5403 // TODO(ager): We should recognize when the prototype chains for different | 5576 // TODO(ager): We should recognize when the prototype chains for different |
| 5404 // maps are identical. In that case we can avoid repeatedly generating the | 5577 // maps are identical. In that case we can avoid repeatedly generating the |
| 5405 // same prototype map checks. | 5578 // same prototype map checks. |
| 5406 int count = 0; | 5579 int count = 0; |
| 5407 HBasicBlock* join = NULL; | 5580 HBasicBlock* join = NULL; |
| 5408 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 5581 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
| 5409 Handle<Map> map = types->at(i); | 5582 Handle<Map> map = types->at(i); |
| 5410 LookupResult lookup(isolate()); | 5583 LookupResult lookup(isolate()); |
| 5411 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 5584 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| 5412 if (count == 0) { | 5585 if (count == 0) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5464 } | 5637 } |
| 5465 } | 5638 } |
| 5466 | 5639 |
| 5467 ASSERT(join != NULL); | 5640 ASSERT(join != NULL); |
| 5468 join->SetJoinId(expr->id()); | 5641 join->SetJoinId(expr->id()); |
| 5469 set_current_block(join); | 5642 set_current_block(join); |
| 5470 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 5643 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
| 5471 } | 5644 } |
| 5472 | 5645 |
| 5473 | 5646 |
| 5474 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 5647 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 5475 Property* prop = expr->target()->AsProperty(); | 5648 Property* prop = expr->target()->AsProperty(); |
| 5476 ASSERT(prop != NULL); | 5649 ASSERT(prop != NULL); |
| 5477 expr->RecordTypeFeedback(oracle(), zone()); | 5650 expr->RecordTypeFeedback(oracle(), zone()); |
| 5478 CHECK_ALIVE(VisitForValue(prop->obj())); | 5651 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 5479 | 5652 |
| 5480 if (prop->key()->IsPropertyName()) { | 5653 if (prop->key()->IsPropertyName()) { |
| 5481 // Named store. | 5654 // Named store. |
| 5482 CHECK_ALIVE(VisitForValue(expr->value())); | 5655 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5483 HValue* value = environment()->ExpressionStackAt(0); | 5656 HValue* value = environment()->ExpressionStackAt(0); |
| 5484 HValue* object = environment()->ExpressionStackAt(1); | 5657 HValue* object = environment()->ExpressionStackAt(1); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5547 ASSERT(has_side_effects); // Stores always have side effects. | 5720 ASSERT(has_side_effects); // Stores always have side effects. |
| 5548 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5721 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 5549 return ast_context()->ReturnValue(Pop()); | 5722 return ast_context()->ReturnValue(Pop()); |
| 5550 } | 5723 } |
| 5551 } | 5724 } |
| 5552 | 5725 |
| 5553 | 5726 |
| 5554 // Because not every expression has a position and there is not common | 5727 // Because not every expression has a position and there is not common |
| 5555 // superclass of Assignment and CountOperation, we cannot just pass the | 5728 // superclass of Assignment and CountOperation, we cannot just pass the |
| 5556 // owning expression instead of position and ast_id separately. | 5729 // owning expression instead of position and ast_id separately. |
| 5557 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, | 5730 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
| 5558 HValue* value, | 5731 Variable* var, |
| 5559 int position, | 5732 HValue* value, |
| 5560 BailoutId ast_id) { | 5733 int position, |
| 5734 BailoutId ast_id) { | |
| 5561 LookupResult lookup(isolate()); | 5735 LookupResult lookup(isolate()); |
| 5562 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 5736 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| 5563 if (type == kUseCell) { | 5737 if (type == kUseCell) { |
| 5564 Handle<GlobalObject> global(info()->global_object()); | 5738 Handle<GlobalObject> global(info()->global_object()); |
| 5565 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 5739 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 5566 HInstruction* instr = | 5740 HInstruction* instr = |
| 5567 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); | 5741 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); |
| 5568 instr->set_position(position); | 5742 instr->set_position(position); |
| 5569 AddInstruction(instr); | 5743 AddInstruction(instr); |
| 5570 if (instr->HasObservableSideEffects()) { | 5744 if (instr->HasObservableSideEffects()) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 5581 value, | 5755 value, |
| 5582 function_strict_mode_flag()); | 5756 function_strict_mode_flag()); |
| 5583 instr->set_position(position); | 5757 instr->set_position(position); |
| 5584 AddInstruction(instr); | 5758 AddInstruction(instr); |
| 5585 ASSERT(instr->HasObservableSideEffects()); | 5759 ASSERT(instr->HasObservableSideEffects()); |
| 5586 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 5760 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 5587 } | 5761 } |
| 5588 } | 5762 } |
| 5589 | 5763 |
| 5590 | 5764 |
| 5591 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5765 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 5592 Expression* target = expr->target(); | 5766 Expression* target = expr->target(); |
| 5593 VariableProxy* proxy = target->AsVariableProxy(); | 5767 VariableProxy* proxy = target->AsVariableProxy(); |
| 5594 Property* prop = target->AsProperty(); | 5768 Property* prop = target->AsProperty(); |
| 5595 ASSERT(proxy == NULL || prop == NULL); | 5769 ASSERT(proxy == NULL || prop == NULL); |
| 5596 | 5770 |
| 5597 // We have a second position recorded in the FullCodeGenerator to have | 5771 // We have a second position recorded in the FullCodeGenerator to have |
| 5598 // type feedback for the binary operation. | 5772 // type feedback for the binary operation. |
| 5599 BinaryOperation* operation = expr->binary_operation(); | 5773 BinaryOperation* operation = expr->binary_operation(); |
| 5600 | 5774 |
| 5601 if (proxy != NULL) { | 5775 if (proxy != NULL) { |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5778 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5952 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 5779 return ast_context()->ReturnValue(Pop()); | 5953 return ast_context()->ReturnValue(Pop()); |
| 5780 } | 5954 } |
| 5781 | 5955 |
| 5782 } else { | 5956 } else { |
| 5783 return Bailout("invalid lhs in compound assignment"); | 5957 return Bailout("invalid lhs in compound assignment"); |
| 5784 } | 5958 } |
| 5785 } | 5959 } |
| 5786 | 5960 |
| 5787 | 5961 |
| 5788 void HGraphBuilder::VisitAssignment(Assignment* expr) { | 5962 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { |
| 5789 ASSERT(!HasStackOverflow()); | 5963 ASSERT(!HasStackOverflow()); |
| 5790 ASSERT(current_block() != NULL); | 5964 ASSERT(current_block() != NULL); |
| 5791 ASSERT(current_block()->HasPredecessor()); | 5965 ASSERT(current_block()->HasPredecessor()); |
| 5792 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 5966 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
| 5793 Property* prop = expr->target()->AsProperty(); | 5967 Property* prop = expr->target()->AsProperty(); |
| 5794 ASSERT(proxy == NULL || prop == NULL); | 5968 ASSERT(proxy == NULL || prop == NULL); |
| 5795 | 5969 |
| 5796 if (expr->is_compound()) { | 5970 if (expr->is_compound()) { |
| 5797 HandleCompoundAssignment(expr); | 5971 HandleCompoundAssignment(expr); |
| 5798 return; | 5972 return; |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5905 | 6079 |
| 5906 case Variable::LOOKUP: | 6080 case Variable::LOOKUP: |
| 5907 return Bailout("assignment to LOOKUP variable"); | 6081 return Bailout("assignment to LOOKUP variable"); |
| 5908 } | 6082 } |
| 5909 } else { | 6083 } else { |
| 5910 return Bailout("invalid left-hand side in assignment"); | 6084 return Bailout("invalid left-hand side in assignment"); |
| 5911 } | 6085 } |
| 5912 } | 6086 } |
| 5913 | 6087 |
| 5914 | 6088 |
| 5915 void HGraphBuilder::VisitThrow(Throw* expr) { | 6089 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) { |
| 5916 ASSERT(!HasStackOverflow()); | 6090 ASSERT(!HasStackOverflow()); |
| 5917 ASSERT(current_block() != NULL); | 6091 ASSERT(current_block() != NULL); |
| 5918 ASSERT(current_block()->HasPredecessor()); | 6092 ASSERT(current_block()->HasPredecessor()); |
| 5919 // We don't optimize functions with invalid left-hand sides in | 6093 // We don't optimize functions with invalid left-hand sides in |
| 5920 // assignments, count operations, or for-in. Consequently throw can | 6094 // assignments, count operations, or for-in. Consequently throw can |
| 5921 // currently only occur in an effect context. | 6095 // currently only occur in an effect context. |
| 5922 ASSERT(ast_context()->IsEffect()); | 6096 ASSERT(ast_context()->IsEffect()); |
| 5923 CHECK_ALIVE(VisitForValue(expr->exception())); | 6097 CHECK_ALIVE(VisitForValue(expr->exception())); |
| 5924 | 6098 |
| 5925 HValue* context = environment()->LookupContext(); | 6099 HValue* context = environment()->LookupContext(); |
| 5926 HValue* value = environment()->Pop(); | 6100 HValue* value = environment()->Pop(); |
| 5927 HThrow* instr = new(zone()) HThrow(context, value); | 6101 HThrow* instr = new(zone()) HThrow(context, value); |
| 5928 instr->set_position(expr->position()); | 6102 instr->set_position(expr->position()); |
| 5929 AddInstruction(instr); | 6103 AddInstruction(instr); |
| 5930 AddSimulate(expr->id()); | 6104 AddSimulate(expr->id()); |
| 5931 current_block()->FinishExit(new(zone()) HAbnormalExit); | 6105 current_block()->FinishExit(new(zone()) HAbnormalExit); |
| 5932 set_current_block(NULL); | 6106 set_current_block(NULL); |
| 5933 } | 6107 } |
| 5934 | 6108 |
| 5935 | 6109 |
| 5936 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 6110 HLoadNamedField* HOptimizedGraphBuilder::BuildLoadNamedField( |
| 5937 Handle<Map> map, | 6111 HValue* object, |
| 5938 LookupResult* lookup) { | 6112 Handle<Map> map, |
| 6113 LookupResult* lookup) { | |
| 5939 int index = lookup->GetLocalFieldIndexFromMap(*map); | 6114 int index = lookup->GetLocalFieldIndexFromMap(*map); |
| 5940 if (index < 0) { | 6115 if (index < 0) { |
| 5941 // Negative property indices are in-object properties, indexed | 6116 // Negative property indices are in-object properties, indexed |
| 5942 // from the end of the fixed part of the object. | 6117 // from the end of the fixed part of the object. |
| 5943 int offset = (index * kPointerSize) + map->instance_size(); | 6118 int offset = (index * kPointerSize) + map->instance_size(); |
| 5944 return new(zone()) HLoadNamedField(object, true, offset); | 6119 return new(zone()) HLoadNamedField(object, true, offset); |
| 5945 } else { | 6120 } else { |
| 5946 // Non-negative property indices are in the properties array. | 6121 // Non-negative property indices are in the properties array. |
| 5947 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | 6122 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; |
| 5948 return new(zone()) HLoadNamedField(object, false, offset); | 6123 return new(zone()) HLoadNamedField(object, false, offset); |
| 5949 } | 6124 } |
| 5950 } | 6125 } |
| 5951 | 6126 |
| 5952 | 6127 |
| 5953 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* object, | 6128 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
| 5954 Handle<String> name, | 6129 HValue* object, |
| 5955 Property* expr) { | 6130 Handle<String> name, |
| 6131 Property* expr) { | |
| 5956 if (expr->IsUninitialized() && !FLAG_always_opt) { | 6132 if (expr->IsUninitialized() && !FLAG_always_opt) { |
| 5957 AddInstruction(new(zone()) HSoftDeoptimize); | 6133 AddInstruction(new(zone()) HSoftDeoptimize); |
| 5958 current_block()->MarkAsDeoptimizing(); | 6134 current_block()->MarkAsDeoptimizing(); |
| 5959 } | 6135 } |
| 5960 HValue* context = environment()->LookupContext(); | 6136 HValue* context = environment()->LookupContext(); |
| 5961 return new(zone()) HLoadNamedGeneric(context, object, name); | 6137 return new(zone()) HLoadNamedGeneric(context, object, name); |
| 5962 } | 6138 } |
| 5963 | 6139 |
| 5964 | 6140 |
| 5965 HInstruction* HGraphBuilder::BuildCallGetter(HValue* object, | 6141 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( |
| 5966 Handle<Map> map, | 6142 HValue* object, |
| 5967 Handle<JSFunction> getter, | 6143 Handle<Map> map, |
| 5968 Handle<JSObject> holder) { | 6144 Handle<JSFunction> getter, |
| 6145 Handle<JSObject> holder) { | |
| 5969 AddCheckConstantFunction(holder, object, map); | 6146 AddCheckConstantFunction(holder, object, map); |
| 5970 AddInstruction(new(zone()) HPushArgument(object)); | 6147 AddInstruction(new(zone()) HPushArgument(object)); |
| 5971 return new(zone()) HCallConstantFunction(getter, 1); | 6148 return new(zone()) HCallConstantFunction(getter, 1); |
| 5972 } | 6149 } |
| 5973 | 6150 |
| 5974 | 6151 |
| 5975 HInstruction* HGraphBuilder::BuildLoadNamedMonomorphic(HValue* object, | 6152 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( |
| 5976 Handle<String> name, | 6153 HValue* object, |
| 5977 Property* expr, | 6154 Handle<String> name, |
| 5978 Handle<Map> map) { | 6155 Property* expr, |
| 6156 Handle<Map> map) { | |
| 5979 // Handle a load from a known field. | 6157 // Handle a load from a known field. |
| 5980 ASSERT(!map->is_dictionary_map()); | 6158 ASSERT(!map->is_dictionary_map()); |
| 5981 LookupResult lookup(isolate()); | 6159 LookupResult lookup(isolate()); |
| 5982 map->LookupDescriptor(NULL, *name, &lookup); | 6160 map->LookupDescriptor(NULL, *name, &lookup); |
| 5983 if (lookup.IsField()) { | 6161 if (lookup.IsField()) { |
| 5984 AddCheckMapsWithTransitions(object, map); | 6162 AddCheckMapsWithTransitions(object, map); |
| 5985 return BuildLoadNamedField(object, map, &lookup); | 6163 return BuildLoadNamedField(object, map, &lookup); |
| 5986 } | 6164 } |
| 5987 | 6165 |
| 5988 // Handle a load of a constant known function. | 6166 // Handle a load of a constant known function. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 6002 HInstruction* holder_value = | 6180 HInstruction* holder_value = |
| 6003 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder)); | 6181 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder)); |
| 6004 return BuildLoadNamedField(holder_value, holder_map, &lookup); | 6182 return BuildLoadNamedField(holder_value, holder_map, &lookup); |
| 6005 } | 6183 } |
| 6006 | 6184 |
| 6007 // No luck, do a generic load. | 6185 // No luck, do a generic load. |
| 6008 return BuildLoadNamedGeneric(object, name, expr); | 6186 return BuildLoadNamedGeneric(object, name, expr); |
| 6009 } | 6187 } |
| 6010 | 6188 |
| 6011 | 6189 |
| 6012 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 6190 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
| 6013 HValue* key) { | 6191 HValue* key) { |
| 6014 HValue* context = environment()->LookupContext(); | 6192 HValue* context = environment()->LookupContext(); |
| 6015 return new(zone()) HLoadKeyedGeneric(context, object, key); | 6193 return new(zone()) HLoadKeyedGeneric(context, object, key); |
| 6016 } | 6194 } |
| 6017 | 6195 |
| 6018 | 6196 |
| 6019 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( | 6197 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( |
| 6020 HValue* external_elements, | 6198 HValue* object, |
| 6021 HValue* checked_key, | 6199 HValue* key, |
| 6022 HValue* val, | 6200 HValue* val, |
| 6023 HValue* dependency, | 6201 HValue* dependency, |
| 6024 ElementsKind elements_kind, | 6202 Handle<Map> map, |
| 6025 bool is_store) { | 6203 bool is_store) { |
| 6026 if (is_store) { | |
| 6027 ASSERT(val != NULL); | |
| 6028 switch (elements_kind) { | |
| 6029 case EXTERNAL_PIXEL_ELEMENTS: { | |
| 6030 val = AddInstruction(new(zone()) HClampToUint8(val)); | |
| 6031 break; | |
| 6032 } | |
| 6033 case EXTERNAL_BYTE_ELEMENTS: | |
| 6034 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
| 6035 case EXTERNAL_SHORT_ELEMENTS: | |
| 6036 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
| 6037 case EXTERNAL_INT_ELEMENTS: | |
| 6038 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { | |
| 6039 break; | |
| 6040 } | |
| 6041 case EXTERNAL_FLOAT_ELEMENTS: | |
| 6042 case EXTERNAL_DOUBLE_ELEMENTS: | |
| 6043 break; | |
| 6044 case FAST_SMI_ELEMENTS: | |
| 6045 case FAST_ELEMENTS: | |
| 6046 case FAST_DOUBLE_ELEMENTS: | |
| 6047 case FAST_HOLEY_SMI_ELEMENTS: | |
| 6048 case FAST_HOLEY_ELEMENTS: | |
| 6049 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
| 6050 case DICTIONARY_ELEMENTS: | |
| 6051 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
| 6052 UNREACHABLE(); | |
| 6053 break; | |
| 6054 } | |
| 6055 return new(zone()) HStoreKeyed(external_elements, | |
| 6056 checked_key, | |
| 6057 val, | |
| 6058 elements_kind); | |
| 6059 } else { | |
| 6060 ASSERT(val == NULL); | |
| 6061 HLoadKeyed* load = | |
| 6062 new(zone()) HLoadKeyed( | |
| 6063 external_elements, checked_key, dependency, elements_kind); | |
| 6064 if (FLAG_opt_safe_uint32_operations && | |
| 6065 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { | |
| 6066 graph()->RecordUint32Instruction(load); | |
| 6067 } | |
| 6068 return load; | |
| 6069 } | |
| 6070 } | |
| 6071 | |
| 6072 | |
| 6073 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, | |
| 6074 HValue* checked_key, | |
| 6075 HValue* val, | |
| 6076 HValue* load_dependency, | |
| 6077 ElementsKind elements_kind, | |
| 6078 bool is_store) { | |
| 6079 if (is_store) { | |
| 6080 ASSERT(val != NULL); | |
| 6081 switch (elements_kind) { | |
| 6082 case FAST_SMI_ELEMENTS: | |
| 6083 case FAST_HOLEY_SMI_ELEMENTS: | |
| 6084 // Smi-only arrays need a smi check. | |
| 6085 AddInstruction(new(zone()) HCheckSmi(val)); | |
| 6086 // Fall through. | |
| 6087 case FAST_ELEMENTS: | |
| 6088 case FAST_HOLEY_ELEMENTS: | |
| 6089 case FAST_DOUBLE_ELEMENTS: | |
| 6090 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
| 6091 return new(zone()) HStoreKeyed( | |
| 6092 elements, checked_key, val, elements_kind); | |
| 6093 default: | |
| 6094 UNREACHABLE(); | |
| 6095 return NULL; | |
| 6096 } | |
| 6097 } | |
| 6098 // It's an element load (!is_store). | |
| 6099 return new(zone()) HLoadKeyed(elements, | |
| 6100 checked_key, | |
| 6101 load_dependency, | |
| 6102 elements_kind); | |
| 6103 } | |
| 6104 | |
| 6105 | |
| 6106 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, | |
| 6107 HValue* key, | |
| 6108 HValue* val, | |
| 6109 HValue* dependency, | |
| 6110 Handle<Map> map, | |
| 6111 bool is_store) { | |
| 6112 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, | 6204 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, |
| 6113 zone(), dependency); | 6205 zone(), dependency); |
| 6114 AddInstruction(mapcheck); | 6206 AddInstruction(mapcheck); |
| 6115 if (dependency) { | 6207 if (dependency) { |
| 6116 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 6208 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
| 6117 } | 6209 } |
| 6118 return BuildUncheckedMonomorphicElementAccess(object, key, val, | 6210 return BuildUncheckedMonomorphicElementAccess( |
| 6119 mapcheck, map, is_store); | 6211 object, key, val, |
| 6212 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | |
| 6213 map->elements_kind(), is_store); | |
| 6120 } | 6214 } |
| 6121 | 6215 |
| 6122 | 6216 |
| 6123 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 6217 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( |
| 6124 HValue* object, | 6218 HValue* object, |
| 6125 HValue* key, | 6219 HValue* key, |
| 6126 HValue* val, | 6220 HValue* val, |
| 6127 HCheckMaps* mapcheck, | |
| 6128 Handle<Map> map, | |
| 6129 bool is_store) { | |
| 6130 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | |
| 6131 // on a HElementsTransition instruction. The flag can also be removed if the | |
| 6132 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | |
| 6133 // ElementsKind transitions. Finally, the dependency can be removed for stores | |
| 6134 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | |
| 6135 // generated store code. | |
| 6136 if ((map->elements_kind() == FAST_HOLEY_ELEMENTS) || | |
| 6137 (map->elements_kind() == FAST_ELEMENTS && is_store)) { | |
| 6138 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | |
| 6139 } | |
| 6140 bool fast_smi_only_elements = map->has_fast_smi_elements(); | |
| 6141 bool fast_elements = map->has_fast_object_elements(); | |
| 6142 HInstruction* elements = | |
| 6143 AddInstruction(new(zone()) HLoadElements(object, mapcheck)); | |
| 6144 if (is_store && (fast_elements || fast_smi_only_elements)) { | |
| 6145 HCheckMaps* check_cow_map = new(zone()) HCheckMaps( | |
| 6146 elements, isolate()->factory()->fixed_array_map(), zone()); | |
| 6147 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | |
| 6148 AddInstruction(check_cow_map); | |
| 6149 } | |
| 6150 HInstruction* length = NULL; | |
| 6151 HInstruction* checked_key = NULL; | |
| 6152 if (map->has_external_array_elements()) { | |
| 6153 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | |
| 6154 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length, | |
| 6155 ALLOW_SMI_KEY)); | |
| 6156 HLoadExternalArrayPointer* external_elements = | |
| 6157 new(zone()) HLoadExternalArrayPointer(elements); | |
| 6158 AddInstruction(external_elements); | |
| 6159 return BuildExternalArrayElementAccess( | |
| 6160 external_elements, checked_key, val, mapcheck, | |
| 6161 map->elements_kind(), is_store); | |
| 6162 } | |
| 6163 ASSERT(fast_smi_only_elements || | |
| 6164 fast_elements || | |
| 6165 map->has_fast_double_elements()); | |
| 6166 if (map->instance_type() == JS_ARRAY_TYPE) { | |
| 6167 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck, | |
| 6168 HType::Smi())); | |
| 6169 } else { | |
| 6170 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | |
| 6171 } | |
| 6172 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length, | |
| 6173 ALLOW_SMI_KEY)); | |
| 6174 return BuildFastElementAccess(elements, checked_key, val, mapcheck, | |
| 6175 map->elements_kind(), is_store); | |
| 6176 } | |
| 6177 | |
| 6178 | |
| 6179 HInstruction* HGraphBuilder::TryBuildConsolidatedElementLoad( | |
| 6180 HValue* object, | |
| 6181 HValue* key, | |
| 6182 HValue* val, | |
| 6183 SmallMapList* maps) { | 6221 SmallMapList* maps) { |
| 6184 // For polymorphic loads of similar elements kinds (i.e. all tagged or all | 6222 // For polymorphic loads of similar elements kinds (i.e. all tagged or all |
| 6185 // double), always use the "worst case" code without a transition. This is | 6223 // double), always use the "worst case" code without a transition. This is |
| 6186 // much faster than transitioning the elements to the worst case, trading a | 6224 // much faster than transitioning the elements to the worst case, trading a |
| 6187 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. | 6225 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. |
| 6188 bool has_double_maps = false; | 6226 bool has_double_maps = false; |
| 6189 bool has_smi_or_object_maps = false; | 6227 bool has_smi_or_object_maps = false; |
| 6190 bool has_js_array_access = false; | 6228 bool has_js_array_access = false; |
| 6191 bool has_non_js_array_access = false; | 6229 bool has_non_js_array_access = false; |
| 6192 Handle<Map> most_general_consolidated_map; | 6230 Handle<Map> most_general_consolidated_map; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 6217 most_general_consolidated_map->elements_kind(), | 6255 most_general_consolidated_map->elements_kind(), |
| 6218 map->elements_kind())) { | 6256 map->elements_kind())) { |
| 6219 most_general_consolidated_map = map; | 6257 most_general_consolidated_map = map; |
| 6220 } | 6258 } |
| 6221 } | 6259 } |
| 6222 if (!has_double_maps && !has_smi_or_object_maps) return NULL; | 6260 if (!has_double_maps && !has_smi_or_object_maps) return NULL; |
| 6223 | 6261 |
| 6224 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); | 6262 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); |
| 6225 AddInstruction(check_maps); | 6263 AddInstruction(check_maps); |
| 6226 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( | 6264 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( |
| 6227 object, key, val, check_maps, most_general_consolidated_map, false); | 6265 object, key, val, check_maps, |
| 6266 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, | |
| 6267 most_general_consolidated_map->elements_kind(), | |
| 6268 false); | |
| 6228 return instr; | 6269 return instr; |
| 6229 } | 6270 } |
| 6230 | 6271 |
| 6231 | 6272 |
| 6232 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, | 6273 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( |
| 6233 HValue* key, | 6274 HValue* object, |
| 6234 HValue* val, | 6275 HValue* key, |
| 6235 Expression* prop, | 6276 HValue* val, |
| 6236 BailoutId ast_id, | 6277 Expression* prop, |
| 6237 int position, | 6278 BailoutId ast_id, |
| 6238 bool is_store, | 6279 int position, |
| 6239 bool* has_side_effects) { | 6280 bool is_store, |
| 6281 bool* has_side_effects) { | |
| 6240 *has_side_effects = false; | 6282 *has_side_effects = false; |
| 6241 AddInstruction(new(zone()) HCheckNonSmi(object)); | 6283 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 6242 SmallMapList* maps = prop->GetReceiverTypes(); | 6284 SmallMapList* maps = prop->GetReceiverTypes(); |
| 6243 bool todo_external_array = false; | 6285 bool todo_external_array = false; |
| 6244 | 6286 |
| 6245 if (!is_store) { | 6287 if (!is_store) { |
| 6246 HInstruction* consolidated_load = | 6288 HInstruction* consolidated_load = |
| 6247 TryBuildConsolidatedElementLoad(object, key, val, maps); | 6289 TryBuildConsolidatedElementLoad(object, key, val, maps); |
| 6248 if (consolidated_load != NULL) { | 6290 if (consolidated_load != NULL) { |
| 6249 AddInstruction(consolidated_load); | 6291 AddInstruction(consolidated_load); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6414 elements, checked_key, val, elements_kind_branch, | 6456 elements, checked_key, val, elements_kind_branch, |
| 6415 elements_kind, is_store)); | 6457 elements_kind, is_store)); |
| 6416 } else if (elements_kind == DICTIONARY_ELEMENTS) { | 6458 } else if (elements_kind == DICTIONARY_ELEMENTS) { |
| 6417 if (is_store) { | 6459 if (is_store) { |
| 6418 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); | 6460 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); |
| 6419 } else { | 6461 } else { |
| 6420 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); | 6462 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); |
| 6421 } | 6463 } |
| 6422 } else { // External array elements. | 6464 } else { // External array elements. |
| 6423 access = AddInstruction(BuildExternalArrayElementAccess( | 6465 access = AddInstruction(BuildExternalArrayElementAccess( |
| 6424 external_elements, checked_key, val, elements_kind_branch, | 6466 external_elements, checked_key, val, |
| 6425 elements_kind, is_store)); | 6467 elements_kind_branch, elements_kind, is_store)); |
| 6426 } | 6468 } |
| 6427 *has_side_effects |= access->HasObservableSideEffects(); | 6469 *has_side_effects |= access->HasObservableSideEffects(); |
| 6428 if (position != RelocInfo::kNoPosition) access->set_position(position); | 6470 if (position != RelocInfo::kNoPosition) access->set_position(position); |
| 6429 if (!is_store) { | 6471 if (!is_store) { |
| 6430 Push(access); | 6472 Push(access); |
| 6431 } | 6473 } |
| 6432 current_block()->Goto(join); | 6474 current_block()->Goto(join); |
| 6433 set_current_block(if_false); | 6475 set_current_block(if_false); |
| 6434 } | 6476 } |
| 6435 } | 6477 } |
| 6436 | 6478 |
| 6437 // Deopt if none of the cases matched. | 6479 // Deopt if none of the cases matched. |
| 6438 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 6480 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); |
| 6439 join->SetJoinId(ast_id); | 6481 join->SetJoinId(ast_id); |
| 6440 set_current_block(join); | 6482 set_current_block(join); |
| 6441 return is_store ? NULL : Pop(); | 6483 return is_store ? NULL : Pop(); |
| 6442 } | 6484 } |
| 6443 | 6485 |
| 6444 | 6486 |
| 6445 HValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj, | 6487 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
| 6446 HValue* key, | 6488 HValue* obj, |
| 6447 HValue* val, | 6489 HValue* key, |
| 6448 Expression* expr, | 6490 HValue* val, |
| 6449 BailoutId ast_id, | 6491 Expression* expr, |
| 6450 int position, | 6492 BailoutId ast_id, |
| 6451 bool is_store, | 6493 int position, |
| 6452 bool* has_side_effects) { | 6494 bool is_store, |
| 6495 bool* has_side_effects) { | |
| 6453 ASSERT(!expr->IsPropertyName()); | 6496 ASSERT(!expr->IsPropertyName()); |
| 6454 HInstruction* instr = NULL; | 6497 HInstruction* instr = NULL; |
| 6455 if (expr->IsMonomorphic()) { | 6498 if (expr->IsMonomorphic()) { |
| 6456 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 6499 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
| 6457 if (map->has_slow_elements_kind()) { | 6500 if (map->has_slow_elements_kind()) { |
| 6458 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) | 6501 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) |
| 6459 : BuildLoadKeyedGeneric(obj, key); | 6502 : BuildLoadKeyedGeneric(obj, key); |
| 6460 } else { | 6503 } else { |
| 6461 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 6504 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
| 6462 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); | 6505 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); |
| 6463 } | 6506 } |
| 6464 } else if (expr->GetReceiverTypes() != NULL && | 6507 } else if (expr->GetReceiverTypes() != NULL && |
| 6465 !expr->GetReceiverTypes()->is_empty()) { | 6508 !expr->GetReceiverTypes()->is_empty()) { |
| 6466 return HandlePolymorphicElementAccess( | 6509 return HandlePolymorphicElementAccess( |
| 6467 obj, key, val, expr, ast_id, position, is_store, has_side_effects); | 6510 obj, key, val, expr, ast_id, position, is_store, has_side_effects); |
| 6468 } else { | 6511 } else { |
| 6469 if (is_store) { | 6512 if (is_store) { |
| 6470 instr = BuildStoreKeyedGeneric(obj, key, val); | 6513 instr = BuildStoreKeyedGeneric(obj, key, val); |
| 6471 } else { | 6514 } else { |
| 6472 instr = BuildLoadKeyedGeneric(obj, key); | 6515 instr = BuildLoadKeyedGeneric(obj, key); |
| 6473 } | 6516 } |
| 6474 } | 6517 } |
| 6475 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 6518 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
| 6476 AddInstruction(instr); | 6519 AddInstruction(instr); |
| 6477 *has_side_effects = instr->HasObservableSideEffects(); | 6520 *has_side_effects = instr->HasObservableSideEffects(); |
| 6478 return instr; | 6521 return instr; |
| 6479 } | 6522 } |
| 6480 | 6523 |
| 6481 | 6524 |
| 6482 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, | 6525 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( |
| 6483 HValue* key, | 6526 HValue* object, |
| 6484 HValue* value) { | 6527 HValue* key, |
| 6528 HValue* value) { | |
| 6485 HValue* context = environment()->LookupContext(); | 6529 HValue* context = environment()->LookupContext(); |
| 6486 return new(zone()) HStoreKeyedGeneric( | 6530 return new(zone()) HStoreKeyedGeneric( |
| 6487 context, | 6531 context, |
| 6488 object, | 6532 object, |
| 6489 key, | 6533 key, |
| 6490 value, | 6534 value, |
| 6491 function_strict_mode_flag()); | 6535 function_strict_mode_flag()); |
| 6492 } | 6536 } |
| 6493 | 6537 |
| 6494 | 6538 |
| 6495 void HGraphBuilder::EnsureArgumentsArePushedForAccess() { | 6539 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { |
| 6496 // Outermost function already has arguments on the stack. | 6540 // Outermost function already has arguments on the stack. |
| 6497 if (function_state()->outer() == NULL) return; | 6541 if (function_state()->outer() == NULL) return; |
| 6498 | 6542 |
| 6499 if (function_state()->arguments_pushed()) return; | 6543 if (function_state()->arguments_pushed()) return; |
| 6500 | 6544 |
| 6501 // Push arguments when entering inlined function. | 6545 // Push arguments when entering inlined function. |
| 6502 HEnterInlined* entry = function_state()->entry(); | 6546 HEnterInlined* entry = function_state()->entry(); |
| 6503 entry->set_arguments_pushed(); | 6547 entry->set_arguments_pushed(); |
| 6504 | 6548 |
| 6505 ZoneList<HValue*>* arguments_values = entry->arguments_values(); | 6549 ZoneList<HValue*>* arguments_values = entry->arguments_values(); |
| 6506 | 6550 |
| 6507 HInstruction* insert_after = entry; | 6551 HInstruction* insert_after = entry; |
| 6508 for (int i = 0; i < arguments_values->length(); i++) { | 6552 for (int i = 0; i < arguments_values->length(); i++) { |
| 6509 HValue* argument = arguments_values->at(i); | 6553 HValue* argument = arguments_values->at(i); |
| 6510 HInstruction* push_argument = new(zone()) HPushArgument(argument); | 6554 HInstruction* push_argument = new(zone()) HPushArgument(argument); |
| 6511 push_argument->InsertAfter(insert_after); | 6555 push_argument->InsertAfter(insert_after); |
| 6512 insert_after = push_argument; | 6556 insert_after = push_argument; |
| 6513 } | 6557 } |
| 6514 | 6558 |
| 6515 HArgumentsElements* arguments_elements = | 6559 HArgumentsElements* arguments_elements = |
| 6516 new(zone()) HArgumentsElements(true); | 6560 new(zone()) HArgumentsElements(true); |
| 6517 arguments_elements->ClearFlag(HValue::kUseGVN); | 6561 arguments_elements->ClearFlag(HValue::kUseGVN); |
| 6518 arguments_elements->InsertAfter(insert_after); | 6562 arguments_elements->InsertAfter(insert_after); |
| 6519 function_state()->set_arguments_elements(arguments_elements); | 6563 function_state()->set_arguments_elements(arguments_elements); |
| 6520 } | 6564 } |
| 6521 | 6565 |
| 6522 | 6566 |
| 6523 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { | 6567 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) { |
| 6524 VariableProxy* proxy = expr->obj()->AsVariableProxy(); | 6568 VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
| 6525 if (proxy == NULL) return false; | 6569 if (proxy == NULL) return false; |
| 6526 if (!proxy->var()->IsStackAllocated()) return false; | 6570 if (!proxy->var()->IsStackAllocated()) return false; |
| 6527 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { | 6571 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { |
| 6528 return false; | 6572 return false; |
| 6529 } | 6573 } |
| 6530 | 6574 |
| 6531 HInstruction* result = NULL; | 6575 HInstruction* result = NULL; |
| 6532 if (expr->key()->IsPropertyName()) { | 6576 if (expr->key()->IsPropertyName()) { |
| 6533 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 6577 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6572 HInstruction* checked_key = | 6616 HInstruction* checked_key = |
| 6573 AddInstruction(new(zone()) HBoundsCheck(key, length)); | 6617 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 6574 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); | 6618 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); |
| 6575 } | 6619 } |
| 6576 } | 6620 } |
| 6577 ast_context()->ReturnInstruction(result, expr->id()); | 6621 ast_context()->ReturnInstruction(result, expr->id()); |
| 6578 return true; | 6622 return true; |
| 6579 } | 6623 } |
| 6580 | 6624 |
| 6581 | 6625 |
| 6582 void HGraphBuilder::VisitProperty(Property* expr) { | 6626 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { |
| 6583 ASSERT(!HasStackOverflow()); | 6627 ASSERT(!HasStackOverflow()); |
| 6584 ASSERT(current_block() != NULL); | 6628 ASSERT(current_block() != NULL); |
| 6585 ASSERT(current_block()->HasPredecessor()); | 6629 ASSERT(current_block()->HasPredecessor()); |
| 6586 expr->RecordTypeFeedback(oracle(), zone()); | 6630 expr->RecordTypeFeedback(oracle(), zone()); |
| 6587 | 6631 |
| 6588 if (TryArgumentsAccess(expr)) return; | 6632 if (TryArgumentsAccess(expr)) return; |
| 6589 | 6633 |
| 6590 CHECK_ALIVE(VisitForValue(expr->obj())); | 6634 CHECK_ALIVE(VisitForValue(expr->obj())); |
| 6591 | 6635 |
| 6592 HInstruction* instr = NULL; | 6636 HInstruction* instr = NULL; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6663 Drop(1); | 6707 Drop(1); |
| 6664 } | 6708 } |
| 6665 } | 6709 } |
| 6666 return ast_context()->ReturnValue(load); | 6710 return ast_context()->ReturnValue(load); |
| 6667 } | 6711 } |
| 6668 instr->set_position(expr->position()); | 6712 instr->set_position(expr->position()); |
| 6669 return ast_context()->ReturnInstruction(instr, expr->id()); | 6713 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 6670 } | 6714 } |
| 6671 | 6715 |
| 6672 | 6716 |
| 6673 void HGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 6717 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
| 6674 Handle<Map> receiver_map) { | 6718 Handle<Map> receiver_map) { |
| 6675 if (!holder.is_null()) { | 6719 if (!holder.is_null()) { |
| 6676 AddInstruction(new(zone()) HCheckPrototypeMaps( | 6720 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 6677 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), holder)); | 6721 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), holder)); |
| 6678 } | 6722 } |
| 6679 } | 6723 } |
| 6680 | 6724 |
| 6681 | 6725 |
| 6682 void HGraphBuilder::AddCheckConstantFunction(Handle<JSObject> holder, | 6726 void HOptimizedGraphBuilder::AddCheckConstantFunction( |
| 6683 HValue* receiver, | 6727 Handle<JSObject> holder, |
| 6684 Handle<Map> receiver_map) { | 6728 HValue* receiver, |
| 6729 Handle<Map> receiver_map) { | |
| 6685 // Constant functions have the nice property that the map will change if they | 6730 // Constant functions have the nice property that the map will change if they |
| 6686 // are overwritten. Therefore it is enough to check the map of the holder and | 6731 // are overwritten. Therefore it is enough to check the map of the holder and |
| 6687 // its prototypes. | 6732 // its prototypes. |
| 6688 AddCheckMapsWithTransitions(receiver, receiver_map); | 6733 AddCheckMapsWithTransitions(receiver, receiver_map); |
| 6689 AddCheckPrototypeMaps(holder, receiver_map); | 6734 AddCheckPrototypeMaps(holder, receiver_map); |
| 6690 } | 6735 } |
| 6691 | 6736 |
| 6692 | 6737 |
| 6693 class FunctionSorter { | 6738 class FunctionSorter { |
| 6694 public: | 6739 public: |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 6716 FunctionSorter const* function1 = reinterpret_cast<FunctionSorter const*>(a); | 6761 FunctionSorter const* function1 = reinterpret_cast<FunctionSorter const*>(a); |
| 6717 FunctionSorter const* function2 = reinterpret_cast<FunctionSorter const*>(b); | 6762 FunctionSorter const* function2 = reinterpret_cast<FunctionSorter const*>(b); |
| 6718 int diff = function1->ticks() - function2->ticks(); | 6763 int diff = function1->ticks() - function2->ticks(); |
| 6719 if (diff != 0) return -diff; | 6764 if (diff != 0) return -diff; |
| 6720 diff = function1->ast_length() - function2->ast_length(); | 6765 diff = function1->ast_length() - function2->ast_length(); |
| 6721 if (diff != 0) return diff; | 6766 if (diff != 0) return diff; |
| 6722 return function1->src_length() - function2->src_length(); | 6767 return function1->src_length() - function2->src_length(); |
| 6723 } | 6768 } |
| 6724 | 6769 |
| 6725 | 6770 |
| 6726 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, | 6771 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( |
| 6727 HValue* receiver, | 6772 Call* expr, |
| 6728 SmallMapList* types, | 6773 HValue* receiver, |
| 6729 Handle<String> name) { | 6774 SmallMapList* types, |
| 6775 Handle<String> name) { | |
| 6730 // TODO(ager): We should recognize when the prototype chains for different | 6776 // TODO(ager): We should recognize when the prototype chains for different |
| 6731 // maps are identical. In that case we can avoid repeatedly generating the | 6777 // maps are identical. In that case we can avoid repeatedly generating the |
| 6732 // same prototype map checks. | 6778 // same prototype map checks. |
| 6733 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6779 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 6734 HBasicBlock* join = NULL; | 6780 HBasicBlock* join = NULL; |
| 6735 FunctionSorter order[kMaxCallPolymorphism]; | 6781 FunctionSorter order[kMaxCallPolymorphism]; |
| 6736 int ordered_functions = 0; | 6782 int ordered_functions = 0; |
| 6737 for (int i = 0; | 6783 for (int i = 0; |
| 6738 i < types->length() && ordered_functions < kMaxCallPolymorphism; | 6784 i < types->length() && ordered_functions < kMaxCallPolymorphism; |
| 6739 ++i) { | 6785 ++i) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6821 if (join->HasPredecessor()) { | 6867 if (join->HasPredecessor()) { |
| 6822 set_current_block(join); | 6868 set_current_block(join); |
| 6823 join->SetJoinId(expr->id()); | 6869 join->SetJoinId(expr->id()); |
| 6824 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 6870 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
| 6825 } else { | 6871 } else { |
| 6826 set_current_block(NULL); | 6872 set_current_block(NULL); |
| 6827 } | 6873 } |
| 6828 } | 6874 } |
| 6829 | 6875 |
| 6830 | 6876 |
| 6831 void HGraphBuilder::TraceInline(Handle<JSFunction> target, | 6877 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target, |
| 6832 Handle<JSFunction> caller, | 6878 Handle<JSFunction> caller, |
| 6833 const char* reason) { | 6879 const char* reason) { |
| 6834 if (FLAG_trace_inlining) { | 6880 if (FLAG_trace_inlining) { |
| 6835 SmartArrayPointer<char> target_name = | 6881 SmartArrayPointer<char> target_name = |
| 6836 target->shared()->DebugName()->ToCString(); | 6882 target->shared()->DebugName()->ToCString(); |
| 6837 SmartArrayPointer<char> caller_name = | 6883 SmartArrayPointer<char> caller_name = |
| 6838 caller->shared()->DebugName()->ToCString(); | 6884 caller->shared()->DebugName()->ToCString(); |
| 6839 if (reason == NULL) { | 6885 if (reason == NULL) { |
| 6840 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); | 6886 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); |
| 6841 } else { | 6887 } else { |
| 6842 PrintF("Did not inline %s called from %s (%s).\n", | 6888 PrintF("Did not inline %s called from %s (%s).\n", |
| 6843 *target_name, *caller_name, reason); | 6889 *target_name, *caller_name, reason); |
| 6844 } | 6890 } |
| 6845 } | 6891 } |
| 6846 } | 6892 } |
| 6847 | 6893 |
| 6848 | 6894 |
| 6849 static const int kNotInlinable = 1000000000; | 6895 static const int kNotInlinable = 1000000000; |
| 6850 | 6896 |
| 6851 | 6897 |
| 6852 int HGraphBuilder::InliningAstSize(Handle<JSFunction> target) { | 6898 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) { |
| 6853 if (!FLAG_use_inlining) return kNotInlinable; | 6899 if (!FLAG_use_inlining) return kNotInlinable; |
| 6854 | 6900 |
| 6855 // Precondition: call is monomorphic and we have found a target with the | 6901 // Precondition: call is monomorphic and we have found a target with the |
| 6856 // appropriate arity. | 6902 // appropriate arity. |
| 6857 Handle<JSFunction> caller = info()->closure(); | 6903 Handle<JSFunction> caller = info()->closure(); |
| 6858 Handle<SharedFunctionInfo> target_shared(target->shared()); | 6904 Handle<SharedFunctionInfo> target_shared(target->shared()); |
| 6859 | 6905 |
| 6860 // Do a quick check on source code length to avoid parsing large | 6906 // Do a quick check on source code length to avoid parsing large |
| 6861 // inlining candidates. | 6907 // inlining candidates. |
| 6862 if (target_shared->SourceSize() > | 6908 if (target_shared->SourceSize() > |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 6873 if (target_shared->dont_inline() || target_shared->dont_optimize()) { | 6919 if (target_shared->dont_inline() || target_shared->dont_optimize()) { |
| 6874 TraceInline(target, caller, "target contains unsupported syntax [early]"); | 6920 TraceInline(target, caller, "target contains unsupported syntax [early]"); |
| 6875 return kNotInlinable; | 6921 return kNotInlinable; |
| 6876 } | 6922 } |
| 6877 | 6923 |
| 6878 int nodes_added = target_shared->ast_node_count(); | 6924 int nodes_added = target_shared->ast_node_count(); |
| 6879 return nodes_added; | 6925 return nodes_added; |
| 6880 } | 6926 } |
| 6881 | 6927 |
| 6882 | 6928 |
| 6883 bool HGraphBuilder::TryInline(CallKind call_kind, | 6929 bool HOptimizedGraphBuilder::TryInline(CallKind call_kind, |
| 6884 Handle<JSFunction> target, | 6930 Handle<JSFunction> target, |
| 6885 int arguments_count, | 6931 int arguments_count, |
| 6886 HValue* implicit_return_value, | 6932 HValue* implicit_return_value, |
| 6887 BailoutId ast_id, | 6933 BailoutId ast_id, |
| 6888 BailoutId return_id, | 6934 BailoutId return_id, |
| 6889 InliningKind inlining_kind) { | 6935 InliningKind inlining_kind) { |
| 6890 int nodes_added = InliningAstSize(target); | 6936 int nodes_added = InliningAstSize(target); |
| 6891 if (nodes_added == kNotInlinable) return false; | 6937 if (nodes_added == kNotInlinable) return false; |
| 6892 | 6938 |
| 6893 Handle<JSFunction> caller = info()->closure(); | 6939 Handle<JSFunction> caller = info()->closure(); |
| 6894 | 6940 |
| 6895 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { | 6941 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { |
| 6896 TraceInline(target, caller, "target AST is too large [early]"); | 6942 TraceInline(target, caller, "target AST is too large [early]"); |
| 6897 return false; | 6943 return false; |
| 6898 } | 6944 } |
| 6899 | 6945 |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7188 function_return()->SetJoinId(ast_id); | 7234 function_return()->SetJoinId(ast_id); |
| 7189 set_current_block(function_return()); | 7235 set_current_block(function_return()); |
| 7190 } else { | 7236 } else { |
| 7191 set_current_block(NULL); | 7237 set_current_block(NULL); |
| 7192 } | 7238 } |
| 7193 delete target_state; | 7239 delete target_state; |
| 7194 return true; | 7240 return true; |
| 7195 } | 7241 } |
| 7196 | 7242 |
| 7197 | 7243 |
| 7198 bool HGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) { | 7244 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) { |
| 7199 // The function call we are inlining is a method call if the call | 7245 // The function call we are inlining is a method call if the call |
| 7200 // is a property call. | 7246 // is a property call. |
| 7201 CallKind call_kind = (expr->expression()->AsProperty() == NULL) | 7247 CallKind call_kind = (expr->expression()->AsProperty() == NULL) |
| 7202 ? CALL_AS_FUNCTION | 7248 ? CALL_AS_FUNCTION |
| 7203 : CALL_AS_METHOD; | 7249 : CALL_AS_METHOD; |
| 7204 | 7250 |
| 7205 return TryInline(call_kind, | 7251 return TryInline(call_kind, |
| 7206 expr->target(), | 7252 expr->target(), |
| 7207 expr->arguments()->length(), | 7253 expr->arguments()->length(), |
| 7208 NULL, | 7254 NULL, |
| 7209 expr->id(), | 7255 expr->id(), |
| 7210 expr->ReturnId(), | 7256 expr->ReturnId(), |
| 7211 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); | 7257 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); |
| 7212 } | 7258 } |
| 7213 | 7259 |
| 7214 | 7260 |
| 7215 bool HGraphBuilder::TryInlineConstruct(CallNew* expr, | 7261 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, |
| 7216 HValue* implicit_return_value) { | 7262 HValue* implicit_return_value) { |
| 7217 return TryInline(CALL_AS_FUNCTION, | 7263 return TryInline(CALL_AS_FUNCTION, |
| 7218 expr->target(), | 7264 expr->target(), |
| 7219 expr->arguments()->length(), | 7265 expr->arguments()->length(), |
| 7220 implicit_return_value, | 7266 implicit_return_value, |
| 7221 expr->id(), | 7267 expr->id(), |
| 7222 expr->ReturnId(), | 7268 expr->ReturnId(), |
| 7223 CONSTRUCT_CALL_RETURN); | 7269 CONSTRUCT_CALL_RETURN); |
| 7224 } | 7270 } |
| 7225 | 7271 |
| 7226 | 7272 |
| 7227 bool HGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, | 7273 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, |
| 7228 Property* prop) { | 7274 Property* prop) { |
| 7229 return TryInline(CALL_AS_METHOD, | 7275 return TryInline(CALL_AS_METHOD, |
| 7230 getter, | 7276 getter, |
| 7231 0, | 7277 0, |
| 7232 NULL, | 7278 NULL, |
| 7233 prop->id(), | 7279 prop->id(), |
| 7234 prop->LoadId(), | 7280 prop->LoadId(), |
| 7235 GETTER_CALL_RETURN); | 7281 GETTER_CALL_RETURN); |
| 7236 } | 7282 } |
| 7237 | 7283 |
| 7238 | 7284 |
| 7239 bool HGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, | 7285 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, |
| 7240 Assignment* assignment, | 7286 Assignment* assignment, |
| 7241 HValue* implicit_return_value) { | 7287 HValue* implicit_return_value) { |
| 7242 return TryInline(CALL_AS_METHOD, | 7288 return TryInline(CALL_AS_METHOD, |
| 7243 setter, | 7289 setter, |
| 7244 1, | 7290 1, |
| 7245 implicit_return_value, | 7291 implicit_return_value, |
| 7246 assignment->id(), | 7292 assignment->id(), |
| 7247 assignment->AssignmentId(), | 7293 assignment->AssignmentId(), |
| 7248 SETTER_CALL_RETURN); | 7294 SETTER_CALL_RETURN); |
| 7249 } | 7295 } |
| 7250 | 7296 |
| 7251 | 7297 |
| 7252 bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) { | 7298 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, |
| 7299 bool drop_extra) { | |
| 7253 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 7300 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
| 7254 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 7301 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
| 7255 switch (id) { | 7302 switch (id) { |
| 7256 case kMathExp: | 7303 case kMathExp: |
| 7257 if (!FLAG_fast_math) break; | 7304 if (!FLAG_fast_math) break; |
| 7258 // Fall through if FLAG_fast_math. | 7305 // Fall through if FLAG_fast_math. |
| 7259 case kMathRound: | 7306 case kMathRound: |
| 7260 case kMathAbs: | 7307 case kMathAbs: |
| 7261 case kMathSqrt: | 7308 case kMathSqrt: |
| 7262 case kMathLog: | 7309 case kMathLog: |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 7276 } | 7323 } |
| 7277 break; | 7324 break; |
| 7278 default: | 7325 default: |
| 7279 // Not supported for inlining yet. | 7326 // Not supported for inlining yet. |
| 7280 break; | 7327 break; |
| 7281 } | 7328 } |
| 7282 return false; | 7329 return false; |
| 7283 } | 7330 } |
| 7284 | 7331 |
| 7285 | 7332 |
| 7286 bool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr, | 7333 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
| 7287 HValue* receiver, | 7334 Call* expr, |
| 7288 Handle<Map> receiver_map, | 7335 HValue* receiver, |
| 7289 CheckType check_type) { | 7336 Handle<Map> receiver_map, |
| 7337 CheckType check_type) { | |
| 7290 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); | 7338 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); |
| 7291 // Try to inline calls like Math.* as operations in the calling function. | 7339 // Try to inline calls like Math.* as operations in the calling function. |
| 7292 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 7340 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
| 7293 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 7341 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
| 7294 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 7342 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 7295 switch (id) { | 7343 switch (id) { |
| 7296 case kStringCharCodeAt: | 7344 case kStringCharCodeAt: |
| 7297 case kStringCharAt: | 7345 case kStringCharAt: |
| 7298 if (argument_count == 2 && check_type == STRING_CHECK) { | 7346 if (argument_count == 2 && check_type == STRING_CHECK) { |
| 7299 HValue* index = Pop(); | 7347 HValue* index = Pop(); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7409 } | 7457 } |
| 7410 break; | 7458 break; |
| 7411 default: | 7459 default: |
| 7412 // Not yet supported for inlining. | 7460 // Not yet supported for inlining. |
| 7413 break; | 7461 break; |
| 7414 } | 7462 } |
| 7415 return false; | 7463 return false; |
| 7416 } | 7464 } |
| 7417 | 7465 |
| 7418 | 7466 |
| 7419 bool HGraphBuilder::TryCallApply(Call* expr) { | 7467 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { |
| 7420 Expression* callee = expr->expression(); | 7468 Expression* callee = expr->expression(); |
| 7421 Property* prop = callee->AsProperty(); | 7469 Property* prop = callee->AsProperty(); |
| 7422 ASSERT(prop != NULL); | 7470 ASSERT(prop != NULL); |
| 7423 | 7471 |
| 7424 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { | 7472 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { |
| 7425 return false; | 7473 return false; |
| 7426 } | 7474 } |
| 7427 Handle<Map> function_map = expr->GetReceiverTypes()->first(); | 7475 Handle<Map> function_map = expr->GetReceiverTypes()->first(); |
| 7428 if (function_map->instance_type() != JS_FUNCTION_TYPE || | 7476 if (function_map->instance_type() != JS_FUNCTION_TYPE || |
| 7429 !expr->target()->shared()->HasBuiltinFunctionId() || | 7477 !expr->target()->shared()->HasBuiltinFunctionId() || |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7537 return NULL; | 7585 return NULL; |
| 7538 } | 7586 } |
| 7539 current = next; | 7587 current = next; |
| 7540 } | 7588 } |
| 7541 } | 7589 } |
| 7542 | 7590 |
| 7543 return kinds[first_index]; | 7591 return kinds[first_index]; |
| 7544 } | 7592 } |
| 7545 | 7593 |
| 7546 | 7594 |
| 7547 void HGraphBuilder::VisitCall(Call* expr) { | 7595 void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
| 7548 ASSERT(!HasStackOverflow()); | 7596 ASSERT(!HasStackOverflow()); |
| 7549 ASSERT(current_block() != NULL); | 7597 ASSERT(current_block() != NULL); |
| 7550 ASSERT(current_block()->HasPredecessor()); | 7598 ASSERT(current_block()->HasPredecessor()); |
| 7551 Expression* callee = expr->expression(); | 7599 Expression* callee = expr->expression(); |
| 7552 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 7600 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 7553 HInstruction* call = NULL; | 7601 HInstruction* call = NULL; |
| 7554 | 7602 |
| 7555 Property* prop = callee->AsProperty(); | 7603 Property* prop = callee->AsProperty(); |
| 7556 if (prop != NULL) { | 7604 if (prop != NULL) { |
| 7557 if (!prop->key()->IsPropertyName()) { | 7605 if (!prop->key()->IsPropertyName()) { |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7767 | 7815 |
| 7768 | 7816 |
| 7769 // Checks whether allocation using the given constructor can be inlined. | 7817 // Checks whether allocation using the given constructor can be inlined. |
| 7770 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 7818 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { |
| 7771 return constructor->has_initial_map() && | 7819 return constructor->has_initial_map() && |
| 7772 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 7820 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
| 7773 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; | 7821 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; |
| 7774 } | 7822 } |
| 7775 | 7823 |
| 7776 | 7824 |
| 7777 void HGraphBuilder::VisitCallNew(CallNew* expr) { | 7825 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
| 7778 ASSERT(!HasStackOverflow()); | 7826 ASSERT(!HasStackOverflow()); |
| 7779 ASSERT(current_block() != NULL); | 7827 ASSERT(current_block() != NULL); |
| 7780 ASSERT(current_block()->HasPredecessor()); | 7828 ASSERT(current_block()->HasPredecessor()); |
| 7781 expr->RecordTypeFeedback(oracle()); | 7829 expr->RecordTypeFeedback(oracle()); |
| 7782 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 7830 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
| 7783 HValue* context = environment()->LookupContext(); | 7831 HValue* context = environment()->LookupContext(); |
| 7784 | 7832 |
| 7785 if (FLAG_inline_construct && | 7833 if (FLAG_inline_construct && |
| 7786 expr->IsMonomorphic() && | 7834 expr->IsMonomorphic() && |
| 7787 IsAllocationInlineable(expr->target())) { | 7835 IsAllocationInlineable(expr->target())) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7831 new(zone()) HCallNew(context, constructor, argument_count); | 7879 new(zone()) HCallNew(context, constructor, argument_count); |
| 7832 Drop(argument_count); | 7880 Drop(argument_count); |
| 7833 call->set_position(expr->position()); | 7881 call->set_position(expr->position()); |
| 7834 return ast_context()->ReturnInstruction(call, expr->id()); | 7882 return ast_context()->ReturnInstruction(call, expr->id()); |
| 7835 } | 7883 } |
| 7836 } | 7884 } |
| 7837 | 7885 |
| 7838 | 7886 |
| 7839 // Support for generating inlined runtime functions. | 7887 // Support for generating inlined runtime functions. |
| 7840 | 7888 |
| 7841 // Lookup table for generators for runtime calls that are generated inline. | 7889 // Lookup table for generators for runtime calls that are generated inline. |
| 7842 // Elements of the table are member pointers to functions of HGraphBuilder. | 7890 // Elements of the table are member pointers to functions of |
| 7891 // HOptimizedGraphBuilder. | |
| 7843 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ | 7892 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ |
| 7844 &HGraphBuilder::Generate##Name, | 7893 &HOptimizedGraphBuilder::Generate##Name, |
| 7845 | 7894 |
| 7846 const HGraphBuilder::InlineFunctionGenerator | 7895 const HOptimizedGraphBuilder::InlineFunctionGenerator |
| 7847 HGraphBuilder::kInlineFunctionGenerators[] = { | 7896 HOptimizedGraphBuilder::kInlineFunctionGenerators[] = { |
| 7848 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 7897 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
| 7849 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 7898 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
| 7850 }; | 7899 }; |
| 7851 #undef INLINE_FUNCTION_GENERATOR_ADDRESS | 7900 #undef INLINE_FUNCTION_GENERATOR_ADDRESS |
| 7852 | 7901 |
| 7853 | 7902 |
| 7854 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 7903 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| 7855 ASSERT(!HasStackOverflow()); | 7904 ASSERT(!HasStackOverflow()); |
| 7856 ASSERT(current_block() != NULL); | 7905 ASSERT(current_block() != NULL); |
| 7857 ASSERT(current_block()->HasPredecessor()); | 7906 ASSERT(current_block()->HasPredecessor()); |
| 7858 if (expr->is_jsruntime()) { | 7907 if (expr->is_jsruntime()) { |
| 7859 return Bailout("call to a JavaScript runtime function"); | 7908 return Bailout("call to a JavaScript runtime function"); |
| 7860 } | 7909 } |
| 7861 | 7910 |
| 7862 const Runtime::Function* function = expr->function(); | 7911 const Runtime::Function* function = expr->function(); |
| 7863 ASSERT(function != NULL); | 7912 ASSERT(function != NULL); |
| 7864 if (function->intrinsic_type == Runtime::INLINE) { | 7913 if (function->intrinsic_type == Runtime::INLINE) { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 7882 Handle<String> name = expr->name(); | 7931 Handle<String> name = expr->name(); |
| 7883 int argument_count = expr->arguments()->length(); | 7932 int argument_count = expr->arguments()->length(); |
| 7884 HCallRuntime* call = | 7933 HCallRuntime* call = |
| 7885 new(zone()) HCallRuntime(context, name, function, argument_count); | 7934 new(zone()) HCallRuntime(context, name, function, argument_count); |
| 7886 Drop(argument_count); | 7935 Drop(argument_count); |
| 7887 return ast_context()->ReturnInstruction(call, expr->id()); | 7936 return ast_context()->ReturnInstruction(call, expr->id()); |
| 7888 } | 7937 } |
| 7889 } | 7938 } |
| 7890 | 7939 |
| 7891 | 7940 |
| 7892 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 7941 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
| 7893 ASSERT(!HasStackOverflow()); | 7942 ASSERT(!HasStackOverflow()); |
| 7894 ASSERT(current_block() != NULL); | 7943 ASSERT(current_block() != NULL); |
| 7895 ASSERT(current_block()->HasPredecessor()); | 7944 ASSERT(current_block()->HasPredecessor()); |
| 7896 switch (expr->op()) { | 7945 switch (expr->op()) { |
| 7897 case Token::DELETE: return VisitDelete(expr); | 7946 case Token::DELETE: return VisitDelete(expr); |
| 7898 case Token::VOID: return VisitVoid(expr); | 7947 case Token::VOID: return VisitVoid(expr); |
| 7899 case Token::TYPEOF: return VisitTypeof(expr); | 7948 case Token::TYPEOF: return VisitTypeof(expr); |
| 7900 case Token::ADD: return VisitAdd(expr); | 7949 case Token::ADD: return VisitAdd(expr); |
| 7901 case Token::SUB: return VisitSub(expr); | 7950 case Token::SUB: return VisitSub(expr); |
| 7902 case Token::BIT_NOT: return VisitBitNot(expr); | 7951 case Token::BIT_NOT: return VisitBitNot(expr); |
| 7903 case Token::NOT: return VisitNot(expr); | 7952 case Token::NOT: return VisitNot(expr); |
| 7904 default: UNREACHABLE(); | 7953 default: UNREACHABLE(); |
| 7905 } | 7954 } |
| 7906 } | 7955 } |
| 7907 | 7956 |
| 7908 void HGraphBuilder::VisitDelete(UnaryOperation* expr) { | 7957 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { |
| 7909 Property* prop = expr->expression()->AsProperty(); | 7958 Property* prop = expr->expression()->AsProperty(); |
| 7910 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 7959 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 7911 if (prop != NULL) { | 7960 if (prop != NULL) { |
| 7912 CHECK_ALIVE(VisitForValue(prop->obj())); | 7961 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7913 CHECK_ALIVE(VisitForValue(prop->key())); | 7962 CHECK_ALIVE(VisitForValue(prop->key())); |
| 7914 HValue* key = Pop(); | 7963 HValue* key = Pop(); |
| 7915 HValue* obj = Pop(); | 7964 HValue* obj = Pop(); |
| 7916 HValue* context = environment()->LookupContext(); | 7965 HValue* context = environment()->LookupContext(); |
| 7917 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key); | 7966 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key); |
| 7918 return ast_context()->ReturnInstruction(instr, expr->id()); | 7967 return ast_context()->ReturnInstruction(instr, expr->id()); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 7933 } | 7982 } |
| 7934 } else { | 7983 } else { |
| 7935 // Result of deleting non-property, non-variable reference is true. | 7984 // Result of deleting non-property, non-variable reference is true. |
| 7936 // Evaluate the subexpression for side effects. | 7985 // Evaluate the subexpression for side effects. |
| 7937 CHECK_ALIVE(VisitForEffect(expr->expression())); | 7986 CHECK_ALIVE(VisitForEffect(expr->expression())); |
| 7938 return ast_context()->ReturnValue(graph()->GetConstantTrue()); | 7987 return ast_context()->ReturnValue(graph()->GetConstantTrue()); |
| 7939 } | 7988 } |
| 7940 } | 7989 } |
| 7941 | 7990 |
| 7942 | 7991 |
| 7943 void HGraphBuilder::VisitVoid(UnaryOperation* expr) { | 7992 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) { |
| 7944 CHECK_ALIVE(VisitForEffect(expr->expression())); | 7993 CHECK_ALIVE(VisitForEffect(expr->expression())); |
| 7945 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 7994 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
| 7946 } | 7995 } |
| 7947 | 7996 |
| 7948 | 7997 |
| 7949 void HGraphBuilder::VisitTypeof(UnaryOperation* expr) { | 7998 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
| 7950 CHECK_ALIVE(VisitForTypeOf(expr->expression())); | 7999 CHECK_ALIVE(VisitForTypeOf(expr->expression())); |
| 7951 HValue* value = Pop(); | 8000 HValue* value = Pop(); |
| 7952 HValue* context = environment()->LookupContext(); | 8001 HValue* context = environment()->LookupContext(); |
| 7953 HInstruction* instr = new(zone()) HTypeof(context, value); | 8002 HInstruction* instr = new(zone()) HTypeof(context, value); |
| 7954 return ast_context()->ReturnInstruction(instr, expr->id()); | 8003 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7955 } | 8004 } |
| 7956 | 8005 |
| 7957 | 8006 |
| 7958 void HGraphBuilder::VisitAdd(UnaryOperation* expr) { | 8007 void HOptimizedGraphBuilder::VisitAdd(UnaryOperation* expr) { |
| 7959 CHECK_ALIVE(VisitForValue(expr->expression())); | 8008 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 7960 HValue* value = Pop(); | 8009 HValue* value = Pop(); |
| 7961 HValue* context = environment()->LookupContext(); | 8010 HValue* context = environment()->LookupContext(); |
| 7962 HInstruction* instr = | 8011 HInstruction* instr = |
| 7963 new(zone()) HMul(context, value, graph_->GetConstant1()); | 8012 new(zone()) HMul(context, value, graph()->GetConstant1()); |
| 7964 return ast_context()->ReturnInstruction(instr, expr->id()); | 8013 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7965 } | 8014 } |
| 7966 | 8015 |
| 7967 | 8016 |
| 7968 void HGraphBuilder::VisitSub(UnaryOperation* expr) { | 8017 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { |
| 7969 CHECK_ALIVE(VisitForValue(expr->expression())); | 8018 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 7970 HValue* value = Pop(); | 8019 HValue* value = Pop(); |
| 7971 HValue* context = environment()->LookupContext(); | 8020 HValue* context = environment()->LookupContext(); |
| 7972 HInstruction* instr = | 8021 HInstruction* instr = |
| 7973 new(zone()) HMul(context, value, graph_->GetConstantMinus1()); | 8022 new(zone()) HMul(context, value, graph()->GetConstantMinus1()); |
| 7974 TypeInfo info = oracle()->UnaryType(expr); | 8023 TypeInfo info = oracle()->UnaryType(expr); |
| 7975 Representation rep = ToRepresentation(info); | 8024 Representation rep = ToRepresentation(info); |
| 7976 if (info.IsUninitialized()) { | 8025 if (info.IsUninitialized()) { |
| 7977 AddInstruction(new(zone()) HSoftDeoptimize); | 8026 AddInstruction(new(zone()) HSoftDeoptimize); |
| 7978 current_block()->MarkAsDeoptimizing(); | 8027 current_block()->MarkAsDeoptimizing(); |
| 7979 info = TypeInfo::Unknown(); | 8028 info = TypeInfo::Unknown(); |
| 7980 } | 8029 } |
| 7981 HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep); | 8030 HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep); |
| 7982 return ast_context()->ReturnInstruction(instr, expr->id()); | 8031 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7983 } | 8032 } |
| 7984 | 8033 |
| 7985 | 8034 |
| 7986 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 8035 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
| 7987 CHECK_ALIVE(VisitForValue(expr->expression())); | 8036 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 7988 HValue* value = Pop(); | 8037 HValue* value = Pop(); |
| 7989 TypeInfo info = oracle()->UnaryType(expr); | 8038 TypeInfo info = oracle()->UnaryType(expr); |
| 7990 if (info.IsUninitialized()) { | 8039 if (info.IsUninitialized()) { |
| 7991 AddInstruction(new(zone()) HSoftDeoptimize); | 8040 AddInstruction(new(zone()) HSoftDeoptimize); |
| 7992 current_block()->MarkAsDeoptimizing(); | 8041 current_block()->MarkAsDeoptimizing(); |
| 7993 } | 8042 } |
| 7994 HInstruction* instr = new(zone()) HBitNot(value); | 8043 HInstruction* instr = new(zone()) HBitNot(value); |
| 7995 return ast_context()->ReturnInstruction(instr, expr->id()); | 8044 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7996 } | 8045 } |
| 7997 | 8046 |
| 7998 | 8047 |
| 7999 void HGraphBuilder::VisitNot(UnaryOperation* expr) { | 8048 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { |
| 8000 if (ast_context()->IsTest()) { | 8049 if (ast_context()->IsTest()) { |
| 8001 TestContext* context = TestContext::cast(ast_context()); | 8050 TestContext* context = TestContext::cast(ast_context()); |
| 8002 VisitForControl(expr->expression(), | 8051 VisitForControl(expr->expression(), |
| 8003 context->if_false(), | 8052 context->if_false(), |
| 8004 context->if_true()); | 8053 context->if_true()); |
| 8005 return; | 8054 return; |
| 8006 } | 8055 } |
| 8007 | 8056 |
| 8008 if (ast_context()->IsEffect()) { | 8057 if (ast_context()->IsEffect()) { |
| 8009 VisitForEffect(expr->expression()); | 8058 VisitForEffect(expr->expression()); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 8033 materialize_true = NULL; | 8082 materialize_true = NULL; |
| 8034 } | 8083 } |
| 8035 | 8084 |
| 8036 HBasicBlock* join = | 8085 HBasicBlock* join = |
| 8037 CreateJoin(materialize_false, materialize_true, expr->id()); | 8086 CreateJoin(materialize_false, materialize_true, expr->id()); |
| 8038 set_current_block(join); | 8087 set_current_block(join); |
| 8039 if (join != NULL) return ast_context()->ReturnValue(Pop()); | 8088 if (join != NULL) return ast_context()->ReturnValue(Pop()); |
| 8040 } | 8089 } |
| 8041 | 8090 |
| 8042 | 8091 |
| 8043 HInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input, | 8092 HInstruction* HOptimizedGraphBuilder::BuildIncrement( |
| 8044 CountOperation* expr) { | 8093 bool returns_original_input, |
| 8094 CountOperation* expr) { | |
| 8045 // The input to the count operation is on top of the expression stack. | 8095 // The input to the count operation is on top of the expression stack. |
| 8046 TypeInfo info = oracle()->IncrementType(expr); | 8096 TypeInfo info = oracle()->IncrementType(expr); |
| 8047 Representation rep = ToRepresentation(info); | 8097 Representation rep = ToRepresentation(info); |
| 8048 if (rep.IsTagged()) { | 8098 if (rep.IsTagged()) { |
| 8049 rep = Representation::Integer32(); | 8099 rep = Representation::Integer32(); |
| 8050 } | 8100 } |
| 8051 | 8101 |
| 8052 if (returns_original_input) { | 8102 if (returns_original_input) { |
| 8053 // We need an explicit HValue representing ToNumber(input). The | 8103 // We need an explicit HValue representing ToNumber(input). The |
| 8054 // actual HChange instruction we need is (sometimes) added in a later | 8104 // actual HChange instruction we need is (sometimes) added in a later |
| 8055 // phase, so it is not available now to be used as an input to HAdd and | 8105 // phase, so it is not available now to be used as an input to HAdd and |
| 8056 // as the return value. | 8106 // as the return value. |
| 8057 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); | 8107 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); |
| 8058 AddInstruction(number_input); | 8108 AddInstruction(number_input); |
| 8059 Push(number_input); | 8109 Push(number_input); |
| 8060 } | 8110 } |
| 8061 | 8111 |
| 8062 // The addition has no side effects, so we do not need | 8112 // The addition has no side effects, so we do not need |
| 8063 // to simulate the expression stack after this instruction. | 8113 // to simulate the expression stack after this instruction. |
| 8064 // Any later failures deopt to the load of the input or earlier. | 8114 // Any later failures deopt to the load of the input or earlier. |
| 8065 HConstant* delta = (expr->op() == Token::INC) | 8115 HConstant* delta = (expr->op() == Token::INC) |
| 8066 ? graph_->GetConstant1() | 8116 ? graph()->GetConstant1() |
| 8067 : graph_->GetConstantMinus1(); | 8117 : graph()->GetConstantMinus1(); |
| 8068 HValue* context = environment()->LookupContext(); | 8118 HValue* context = environment()->LookupContext(); |
| 8069 HInstruction* instr = new(zone()) HAdd(context, Top(), delta); | 8119 HInstruction* instr = new(zone()) HAdd(context, Top(), delta); |
| 8070 // We can't insert a simulate here, because it would break deoptimization, | 8120 // We can't insert a simulate here, because it would break deoptimization, |
| 8071 // so the HAdd must not have side effects, so we must freeze its | 8121 // so the HAdd must not have side effects, so we must freeze its |
| 8072 // representation. | 8122 // representation. |
| 8073 instr->AssumeRepresentation(rep); | 8123 instr->AssumeRepresentation(rep); |
| 8074 instr->ClearAllSideEffects(); | 8124 instr->ClearAllSideEffects(); |
| 8075 AddInstruction(instr); | 8125 AddInstruction(instr); |
| 8076 return instr; | 8126 return instr; |
| 8077 } | 8127 } |
| 8078 | 8128 |
| 8079 | 8129 |
| 8080 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { | 8130 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| 8081 ASSERT(!HasStackOverflow()); | 8131 ASSERT(!HasStackOverflow()); |
| 8082 ASSERT(current_block() != NULL); | 8132 ASSERT(current_block() != NULL); |
| 8083 ASSERT(current_block()->HasPredecessor()); | 8133 ASSERT(current_block()->HasPredecessor()); |
| 8084 Expression* target = expr->expression(); | 8134 Expression* target = expr->expression(); |
| 8085 VariableProxy* proxy = target->AsVariableProxy(); | 8135 VariableProxy* proxy = target->AsVariableProxy(); |
| 8086 Property* prop = target->AsProperty(); | 8136 Property* prop = target->AsProperty(); |
| 8087 if (proxy == NULL && prop == NULL) { | 8137 if (proxy == NULL && prop == NULL) { |
| 8088 return Bailout("invalid lhs in count operation"); | 8138 return Bailout("invalid lhs in count operation"); |
| 8089 } | 8139 } |
| 8090 | 8140 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8154 return Bailout("lookup variable in count operation"); | 8204 return Bailout("lookup variable in count operation"); |
| 8155 } | 8205 } |
| 8156 | 8206 |
| 8157 } else { | 8207 } else { |
| 8158 // Argument of the count operation is a property. | 8208 // Argument of the count operation is a property. |
| 8159 ASSERT(prop != NULL); | 8209 ASSERT(prop != NULL); |
| 8160 prop->RecordTypeFeedback(oracle(), zone()); | 8210 prop->RecordTypeFeedback(oracle(), zone()); |
| 8161 | 8211 |
| 8162 if (prop->key()->IsPropertyName()) { | 8212 if (prop->key()->IsPropertyName()) { |
| 8163 // Named property. | 8213 // Named property. |
| 8164 if (returns_original_input) Push(graph_->GetConstantUndefined()); | 8214 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
| 8165 | 8215 |
| 8166 CHECK_ALIVE(VisitForValue(prop->obj())); | 8216 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 8167 HValue* object = Top(); | 8217 HValue* object = Top(); |
| 8168 | 8218 |
| 8169 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 8219 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 8170 Handle<Map> map; | 8220 Handle<Map> map; |
| 8171 HInstruction* load; | 8221 HInstruction* load; |
| 8172 bool monomorphic = prop->IsMonomorphic(); | 8222 bool monomorphic = prop->IsMonomorphic(); |
| 8173 if (monomorphic) { | 8223 if (monomorphic) { |
| 8174 map = prop->GetReceiverTypes()->first(); | 8224 map = prop->GetReceiverTypes()->first(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8215 // of the operation, and the placeholder with the original value if | 8265 // of the operation, and the placeholder with the original value if |
| 8216 // necessary. | 8266 // necessary. |
| 8217 environment()->SetExpressionStackAt(0, after); | 8267 environment()->SetExpressionStackAt(0, after); |
| 8218 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 8268 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
| 8219 if (store->HasObservableSideEffects()) { | 8269 if (store->HasObservableSideEffects()) { |
| 8220 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 8270 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 8221 } | 8271 } |
| 8222 | 8272 |
| 8223 } else { | 8273 } else { |
| 8224 // Keyed property. | 8274 // Keyed property. |
| 8225 if (returns_original_input) Push(graph_->GetConstantUndefined()); | 8275 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
| 8226 | 8276 |
| 8227 CHECK_ALIVE(VisitForValue(prop->obj())); | 8277 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 8228 CHECK_ALIVE(VisitForValue(prop->key())); | 8278 CHECK_ALIVE(VisitForValue(prop->key())); |
| 8229 HValue* obj = environment()->ExpressionStackAt(1); | 8279 HValue* obj = environment()->ExpressionStackAt(1); |
| 8230 HValue* key = environment()->ExpressionStackAt(0); | 8280 HValue* key = environment()->ExpressionStackAt(0); |
| 8231 | 8281 |
| 8232 bool has_side_effects = false; | 8282 bool has_side_effects = false; |
| 8233 HValue* load = HandleKeyedElementAccess( | 8283 HValue* load = HandleKeyedElementAccess( |
| 8234 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 8284 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
| 8235 false, // is_store | 8285 false, // is_store |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 8255 ASSERT(has_side_effects); // Stores always have side effects. | 8305 ASSERT(has_side_effects); // Stores always have side effects. |
| 8256 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 8306 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 8257 } | 8307 } |
| 8258 } | 8308 } |
| 8259 | 8309 |
| 8260 Drop(returns_original_input ? 2 : 1); | 8310 Drop(returns_original_input ? 2 : 1); |
| 8261 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 8311 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
| 8262 } | 8312 } |
| 8263 | 8313 |
| 8264 | 8314 |
| 8265 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context, | 8315 HStringCharCodeAt* HOptimizedGraphBuilder::BuildStringCharCodeAt( |
| 8266 HValue* string, | 8316 HValue* context, |
| 8267 HValue* index) { | 8317 HValue* string, |
| 8318 HValue* index) { | |
| 8268 AddInstruction(new(zone()) HCheckNonSmi(string)); | 8319 AddInstruction(new(zone()) HCheckNonSmi(string)); |
| 8269 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 8320 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
| 8270 HStringLength* length = new(zone()) HStringLength(string); | 8321 HStringLength* length = new(zone()) HStringLength(string); |
| 8271 AddInstruction(length); | 8322 AddInstruction(length); |
| 8272 HInstruction* checked_index = | 8323 HInstruction* checked_index = |
| 8273 AddInstruction(new(zone()) HBoundsCheck(index, length)); | 8324 AddInstruction(new(zone()) HBoundsCheck(index, length)); |
| 8274 return new(zone()) HStringCharCodeAt(context, string, checked_index); | 8325 return new(zone()) HStringCharCodeAt(context, string, checked_index); |
| 8275 } | 8326 } |
| 8276 | 8327 |
| 8277 // Checks if the given shift amounts have form: (sa) and (32 - sa). | 8328 // Checks if the given shift amounts have form: (sa) and (32 - sa). |
| 8278 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, | 8329 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, |
| 8279 HValue* const32_minus_sa) { | 8330 HValue* const32_minus_sa) { |
| 8280 if (!const32_minus_sa->IsSub()) return false; | 8331 if (!const32_minus_sa->IsSub()) return false; |
| 8281 HSub* sub = HSub::cast(const32_minus_sa); | 8332 HSub* sub = HSub::cast(const32_minus_sa); |
| 8282 HValue* const32 = sub->left(); | 8333 HValue* const32 = sub->left(); |
| 8283 if (!const32->IsConstant() || | 8334 if (!const32->IsConstant() || |
| 8284 HConstant::cast(const32)->Integer32Value() != 32) { | 8335 HConstant::cast(const32)->Integer32Value() != 32) { |
| 8285 return false; | 8336 return false; |
| 8286 } | 8337 } |
| 8287 return (sub->right() == sa); | 8338 return (sub->right() == sa); |
| 8288 } | 8339 } |
| 8289 | 8340 |
| 8290 | 8341 |
| 8291 // Checks if the left and the right are shift instructions with the oposite | 8342 // Checks if the left and the right are shift instructions with the oposite |
| 8292 // directions that can be replaced by one rotate right instruction or not. | 8343 // directions that can be replaced by one rotate right instruction or not. |
| 8293 // Returns the operand and the shift amount for the rotate instruction in the | 8344 // Returns the operand and the shift amount for the rotate instruction in the |
| 8294 // former case. | 8345 // former case. |
| 8295 bool HGraphBuilder::MatchRotateRight(HValue* left, | 8346 bool HOptimizedGraphBuilder::MatchRotateRight(HValue* left, |
| 8296 HValue* right, | 8347 HValue* right, |
| 8297 HValue** operand, | 8348 HValue** operand, |
| 8298 HValue** shift_amount) { | 8349 HValue** shift_amount) { |
| 8299 HShl* shl; | 8350 HShl* shl; |
| 8300 HShr* shr; | 8351 HShr* shr; |
| 8301 if (left->IsShl() && right->IsShr()) { | 8352 if (left->IsShl() && right->IsShr()) { |
| 8302 shl = HShl::cast(left); | 8353 shl = HShl::cast(left); |
| 8303 shr = HShr::cast(right); | 8354 shr = HShr::cast(right); |
| 8304 } else if (left->IsShr() && right->IsShl()) { | 8355 } else if (left->IsShr() && right->IsShl()) { |
| 8305 shl = HShl::cast(right); | 8356 shl = HShl::cast(right); |
| 8306 shr = HShr::cast(left); | 8357 shr = HShr::cast(left); |
| 8307 } else { | 8358 } else { |
| 8308 return false; | 8359 return false; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 8323 HConstant* right_const = HConstant::cast(right); | 8374 HConstant* right_const = HConstant::cast(right); |
| 8324 if (right_const->HasInteger32Value() && | 8375 if (right_const->HasInteger32Value() && |
| 8325 (right_const->Integer32Value() & 0x1f) != 0) { | 8376 (right_const->Integer32Value() & 0x1f) != 0) { |
| 8326 return false; | 8377 return false; |
| 8327 } | 8378 } |
| 8328 } | 8379 } |
| 8329 return true; | 8380 return true; |
| 8330 } | 8381 } |
| 8331 | 8382 |
| 8332 | 8383 |
| 8333 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, | 8384 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
| 8334 HValue* left, | 8385 BinaryOperation* expr, |
| 8335 HValue* right) { | 8386 HValue* left, |
| 8387 HValue* right) { | |
| 8336 HValue* context = environment()->LookupContext(); | 8388 HValue* context = environment()->LookupContext(); |
| 8337 TypeInfo left_info, right_info, result_info, combined_info; | 8389 TypeInfo left_info, right_info, result_info, combined_info; |
| 8338 oracle()->BinaryType(expr, &left_info, &right_info, &result_info); | 8390 oracle()->BinaryType(expr, &left_info, &right_info, &result_info); |
| 8339 Representation left_rep = ToRepresentation(left_info); | 8391 Representation left_rep = ToRepresentation(left_info); |
| 8340 Representation right_rep = ToRepresentation(right_info); | 8392 Representation right_rep = ToRepresentation(right_info); |
| 8341 Representation result_rep = ToRepresentation(result_info); | 8393 Representation result_rep = ToRepresentation(result_info); |
| 8342 if (left_info.IsUninitialized()) { | 8394 if (left_info.IsUninitialized()) { |
| 8343 // Can't have initialized one but not the other. | 8395 // Can't have initialized one but not the other. |
| 8344 ASSERT(right_info.IsUninitialized()); | 8396 ASSERT(right_info.IsUninitialized()); |
| 8345 AddInstruction(new(zone()) HSoftDeoptimize); | 8397 AddInstruction(new(zone()) HSoftDeoptimize); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8418 if (call == NULL) return false; | 8470 if (call == NULL) return false; |
| 8419 Literal* literal = expr->right()->AsLiteral(); | 8471 Literal* literal = expr->right()->AsLiteral(); |
| 8420 if (literal == NULL) return false; | 8472 if (literal == NULL) return false; |
| 8421 if (!literal->handle()->IsString()) return false; | 8473 if (!literal->handle()->IsString()) return false; |
| 8422 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; | 8474 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; |
| 8423 ASSERT(call->arguments()->length() == 1); | 8475 ASSERT(call->arguments()->length() == 1); |
| 8424 return true; | 8476 return true; |
| 8425 } | 8477 } |
| 8426 | 8478 |
| 8427 | 8479 |
| 8428 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 8480 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
| 8429 ASSERT(!HasStackOverflow()); | 8481 ASSERT(!HasStackOverflow()); |
| 8430 ASSERT(current_block() != NULL); | 8482 ASSERT(current_block() != NULL); |
| 8431 ASSERT(current_block()->HasPredecessor()); | 8483 ASSERT(current_block()->HasPredecessor()); |
| 8432 switch (expr->op()) { | 8484 switch (expr->op()) { |
| 8433 case Token::COMMA: | 8485 case Token::COMMA: |
| 8434 return VisitComma(expr); | 8486 return VisitComma(expr); |
| 8435 case Token::OR: | 8487 case Token::OR: |
| 8436 case Token::AND: | 8488 case Token::AND: |
| 8437 return VisitLogicalExpression(expr); | 8489 return VisitLogicalExpression(expr); |
| 8438 default: | 8490 default: |
| 8439 return VisitArithmeticExpression(expr); | 8491 return VisitArithmeticExpression(expr); |
| 8440 } | 8492 } |
| 8441 } | 8493 } |
| 8442 | 8494 |
| 8443 | 8495 |
| 8444 void HGraphBuilder::VisitComma(BinaryOperation* expr) { | 8496 void HOptimizedGraphBuilder::VisitComma(BinaryOperation* expr) { |
| 8445 CHECK_ALIVE(VisitForEffect(expr->left())); | 8497 CHECK_ALIVE(VisitForEffect(expr->left())); |
| 8446 // Visit the right subexpression in the same AST context as the entire | 8498 // Visit the right subexpression in the same AST context as the entire |
| 8447 // expression. | 8499 // expression. |
| 8448 Visit(expr->right()); | 8500 Visit(expr->right()); |
| 8449 } | 8501 } |
| 8450 | 8502 |
| 8451 | 8503 |
| 8452 void HGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { | 8504 void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { |
| 8453 bool is_logical_and = expr->op() == Token::AND; | 8505 bool is_logical_and = expr->op() == Token::AND; |
| 8454 if (ast_context()->IsTest()) { | 8506 if (ast_context()->IsTest()) { |
| 8455 TestContext* context = TestContext::cast(ast_context()); | 8507 TestContext* context = TestContext::cast(ast_context()); |
| 8456 // Translate left subexpression. | 8508 // Translate left subexpression. |
| 8457 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 8509 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
| 8458 if (is_logical_and) { | 8510 if (is_logical_and) { |
| 8459 CHECK_BAILOUT(VisitForControl(expr->left(), | 8511 CHECK_BAILOUT(VisitForControl(expr->left(), |
| 8460 eval_right, | 8512 eval_right, |
| 8461 context->if_false())); | 8513 context->if_false())); |
| 8462 } else { | 8514 } else { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8532 | 8584 |
| 8533 HBasicBlock* join_block = | 8585 HBasicBlock* join_block = |
| 8534 CreateJoin(empty_block, right_block, expr->id()); | 8586 CreateJoin(empty_block, right_block, expr->id()); |
| 8535 set_current_block(join_block); | 8587 set_current_block(join_block); |
| 8536 // We did not materialize any value in the predecessor environments, | 8588 // We did not materialize any value in the predecessor environments, |
| 8537 // so there is no need to handle it here. | 8589 // so there is no need to handle it here. |
| 8538 } | 8590 } |
| 8539 } | 8591 } |
| 8540 | 8592 |
| 8541 | 8593 |
| 8542 void HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { | 8594 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { |
| 8543 CHECK_ALIVE(VisitForValue(expr->left())); | 8595 CHECK_ALIVE(VisitForValue(expr->left())); |
| 8544 CHECK_ALIVE(VisitForValue(expr->right())); | 8596 CHECK_ALIVE(VisitForValue(expr->right())); |
| 8545 HValue* right = Pop(); | 8597 HValue* right = Pop(); |
| 8546 HValue* left = Pop(); | 8598 HValue* left = Pop(); |
| 8547 HInstruction* instr = BuildBinaryOperation(expr, left, right); | 8599 HInstruction* instr = BuildBinaryOperation(expr, left, right); |
| 8548 instr->set_position(expr->position()); | 8600 instr->set_position(expr->position()); |
| 8549 return ast_context()->ReturnInstruction(instr, expr->id()); | 8601 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 8550 } | 8602 } |
| 8551 | 8603 |
| 8552 | 8604 |
| 8553 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { | 8605 Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) { |
| 8554 if (info.IsUninitialized()) return Representation::None(); | 8606 if (info.IsUninitialized()) return Representation::None(); |
| 8555 if (info.IsSmi()) return Representation::Integer32(); | 8607 if (info.IsSmi()) return Representation::Integer32(); |
| 8556 if (info.IsInteger32()) return Representation::Integer32(); | 8608 if (info.IsInteger32()) return Representation::Integer32(); |
| 8557 if (info.IsDouble()) return Representation::Double(); | 8609 if (info.IsDouble()) return Representation::Double(); |
| 8558 if (info.IsNumber()) return Representation::Double(); | 8610 if (info.IsNumber()) return Representation::Double(); |
| 8559 return Representation::Tagged(); | 8611 return Representation::Tagged(); |
| 8560 } | 8612 } |
| 8561 | 8613 |
| 8562 | 8614 |
| 8563 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, | 8615 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, |
| 8564 HTypeof* typeof_expr, | 8616 HTypeof* typeof_expr, |
| 8565 Handle<String> check) { | 8617 Handle<String> check) { |
| 8566 // Note: The HTypeof itself is removed during canonicalization, if possible. | 8618 // Note: The HTypeof itself is removed during canonicalization, if possible. |
| 8567 HValue* value = typeof_expr->value(); | 8619 HValue* value = typeof_expr->value(); |
| 8568 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); | 8620 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); |
| 8569 instr->set_position(expr->position()); | 8621 instr->set_position(expr->position()); |
| 8570 return ast_context()->ReturnControl(instr, expr->id()); | 8622 return ast_context()->ReturnControl(instr, expr->id()); |
| 8571 } | 8623 } |
| 8572 | 8624 |
| 8573 | 8625 |
| 8574 static bool MatchLiteralCompareNil(HValue* left, | 8626 static bool MatchLiteralCompareNil(HValue* left, |
| 8575 Token::Value op, | 8627 Token::Value op, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8625 | 8677 |
| 8626 static bool IsLiteralCompareBool(HValue* left, | 8678 static bool IsLiteralCompareBool(HValue* left, |
| 8627 Token::Value op, | 8679 Token::Value op, |
| 8628 HValue* right) { | 8680 HValue* right) { |
| 8629 return op == Token::EQ_STRICT && | 8681 return op == Token::EQ_STRICT && |
| 8630 ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || | 8682 ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || |
| 8631 (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); | 8683 (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); |
| 8632 } | 8684 } |
| 8633 | 8685 |
| 8634 | 8686 |
| 8635 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 8687 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| 8636 ASSERT(!HasStackOverflow()); | 8688 ASSERT(!HasStackOverflow()); |
| 8637 ASSERT(current_block() != NULL); | 8689 ASSERT(current_block() != NULL); |
| 8638 ASSERT(current_block()->HasPredecessor()); | 8690 ASSERT(current_block()->HasPredecessor()); |
| 8639 if (IsClassOfTest(expr)) { | 8691 if (IsClassOfTest(expr)) { |
| 8640 CallRuntime* call = expr->left()->AsCallRuntime(); | 8692 CallRuntime* call = expr->left()->AsCallRuntime(); |
| 8641 ASSERT(call->arguments()->length() == 1); | 8693 ASSERT(call->arguments()->length() == 1); |
| 8642 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8694 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 8643 HValue* value = Pop(); | 8695 HValue* value = Pop(); |
| 8644 Literal* literal = expr->right()->AsLiteral(); | 8696 Literal* literal = expr->right()->AsLiteral(); |
| 8645 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 8697 Handle<String> rhs = Handle<String>::cast(literal->handle()); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8778 HCompareIDAndBranch* result = | 8830 HCompareIDAndBranch* result = |
| 8779 new(zone()) HCompareIDAndBranch(left, right, op); | 8831 new(zone()) HCompareIDAndBranch(left, right, op); |
| 8780 result->set_observed_input_representation(left_rep, right_rep); | 8832 result->set_observed_input_representation(left_rep, right_rep); |
| 8781 result->set_position(expr->position()); | 8833 result->set_position(expr->position()); |
| 8782 return ast_context()->ReturnControl(result, expr->id()); | 8834 return ast_context()->ReturnControl(result, expr->id()); |
| 8783 } | 8835 } |
| 8784 } | 8836 } |
| 8785 } | 8837 } |
| 8786 | 8838 |
| 8787 | 8839 |
| 8788 void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 8840 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
| 8789 HValue* value, | 8841 HValue* value, |
| 8790 NilValue nil) { | 8842 NilValue nil) { |
| 8791 ASSERT(!HasStackOverflow()); | 8843 ASSERT(!HasStackOverflow()); |
| 8792 ASSERT(current_block() != NULL); | 8844 ASSERT(current_block() != NULL); |
| 8793 ASSERT(current_block()->HasPredecessor()); | 8845 ASSERT(current_block()->HasPredecessor()); |
| 8794 EqualityKind kind = | 8846 EqualityKind kind = |
| 8795 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; | 8847 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; |
| 8796 HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil); | 8848 HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil); |
| 8797 instr->set_position(expr->position()); | 8849 instr->set_position(expr->position()); |
| 8798 return ast_context()->ReturnControl(instr, expr->id()); | 8850 return ast_context()->ReturnControl(instr, expr->id()); |
| 8799 } | 8851 } |
| 8800 | 8852 |
| 8801 | 8853 |
| 8802 HInstruction* HGraphBuilder::BuildThisFunction() { | 8854 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
| 8803 // If we share optimized code between different closures, the | 8855 // If we share optimized code between different closures, the |
| 8804 // this-function is not a constant, except inside an inlined body. | 8856 // this-function is not a constant, except inside an inlined body. |
| 8805 if (function_state()->outer() != NULL) { | 8857 if (function_state()->outer() != NULL) { |
| 8806 return new(zone()) HConstant( | 8858 return new(zone()) HConstant( |
| 8807 function_state()->compilation_info()->closure(), | 8859 function_state()->compilation_info()->closure(), |
| 8808 Representation::Tagged()); | 8860 Representation::Tagged()); |
| 8809 } else { | 8861 } else { |
| 8810 return new(zone()) HThisFunction; | 8862 return new(zone()) HThisFunction; |
| 8811 } | 8863 } |
| 8812 } | 8864 } |
| 8813 | 8865 |
| 8814 | 8866 |
| 8815 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 8867 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| 8816 ASSERT(!HasStackOverflow()); | 8868 ASSERT(!HasStackOverflow()); |
| 8817 ASSERT(current_block() != NULL); | 8869 ASSERT(current_block() != NULL); |
| 8818 ASSERT(current_block()->HasPredecessor()); | 8870 ASSERT(current_block()->HasPredecessor()); |
| 8819 HInstruction* instr = BuildThisFunction(); | 8871 HInstruction* instr = BuildThisFunction(); |
| 8820 return ast_context()->ReturnInstruction(instr, expr->id()); | 8872 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 8821 } | 8873 } |
| 8822 | 8874 |
| 8823 | 8875 |
| 8824 void HGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) { | 8876 void HOptimizedGraphBuilder::VisitDeclarations( |
| 8877 ZoneList<Declaration*>* declarations) { | |
| 8825 ASSERT(globals_.is_empty()); | 8878 ASSERT(globals_.is_empty()); |
| 8826 AstVisitor::VisitDeclarations(declarations); | 8879 AstVisitor::VisitDeclarations(declarations); |
| 8827 if (!globals_.is_empty()) { | 8880 if (!globals_.is_empty()) { |
| 8828 Handle<FixedArray> array = | 8881 Handle<FixedArray> array = |
| 8829 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); | 8882 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); |
| 8830 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); | 8883 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); |
| 8831 int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | | 8884 int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | |
| 8832 DeclareGlobalsNativeFlag::encode(info()->is_native()) | | 8885 DeclareGlobalsNativeFlag::encode(info()->is_native()) | |
| 8833 DeclareGlobalsLanguageMode::encode(info()->language_mode()); | 8886 DeclareGlobalsLanguageMode::encode(info()->language_mode()); |
| 8834 HInstruction* result = new(zone()) HDeclareGlobals( | 8887 HInstruction* result = new(zone()) HDeclareGlobals( |
| 8835 environment()->LookupContext(), array, flags); | 8888 environment()->LookupContext(), array, flags); |
| 8836 AddInstruction(result); | 8889 AddInstruction(result); |
| 8837 globals_.Clear(); | 8890 globals_.Clear(); |
| 8838 } | 8891 } |
| 8839 } | 8892 } |
| 8840 | 8893 |
| 8841 | 8894 |
| 8842 void HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* declaration) { | 8895 void HOptimizedGraphBuilder::VisitVariableDeclaration( |
| 8896 VariableDeclaration* declaration) { | |
| 8843 VariableProxy* proxy = declaration->proxy(); | 8897 VariableProxy* proxy = declaration->proxy(); |
| 8844 VariableMode mode = declaration->mode(); | 8898 VariableMode mode = declaration->mode(); |
| 8845 Variable* variable = proxy->var(); | 8899 Variable* variable = proxy->var(); |
| 8846 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; | 8900 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; |
| 8847 switch (variable->location()) { | 8901 switch (variable->location()) { |
| 8848 case Variable::UNALLOCATED: | 8902 case Variable::UNALLOCATED: |
| 8849 globals_.Add(variable->name(), zone()); | 8903 globals_.Add(variable->name(), zone()); |
| 8850 globals_.Add(variable->binding_needs_init() | 8904 globals_.Add(variable->binding_needs_init() |
| 8851 ? isolate()->factory()->the_hole_value() | 8905 ? isolate()->factory()->the_hole_value() |
| 8852 : isolate()->factory()->undefined_value(), zone()); | 8906 : isolate()->factory()->undefined_value(), zone()); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 8869 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8923 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); |
| 8870 } | 8924 } |
| 8871 } | 8925 } |
| 8872 break; | 8926 break; |
| 8873 case Variable::LOOKUP: | 8927 case Variable::LOOKUP: |
| 8874 return Bailout("unsupported lookup slot in declaration"); | 8928 return Bailout("unsupported lookup slot in declaration"); |
| 8875 } | 8929 } |
| 8876 } | 8930 } |
| 8877 | 8931 |
| 8878 | 8932 |
| 8879 void HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* declaration) { | 8933 void HOptimizedGraphBuilder::VisitFunctionDeclaration( |
| 8934 FunctionDeclaration* declaration) { | |
| 8880 VariableProxy* proxy = declaration->proxy(); | 8935 VariableProxy* proxy = declaration->proxy(); |
| 8881 Variable* variable = proxy->var(); | 8936 Variable* variable = proxy->var(); |
| 8882 switch (variable->location()) { | 8937 switch (variable->location()) { |
| 8883 case Variable::UNALLOCATED: { | 8938 case Variable::UNALLOCATED: { |
| 8884 globals_.Add(variable->name(), zone()); | 8939 globals_.Add(variable->name(), zone()); |
| 8885 Handle<SharedFunctionInfo> function = | 8940 Handle<SharedFunctionInfo> function = |
| 8886 Compiler::BuildFunctionInfo(declaration->fun(), info()->script()); | 8941 Compiler::BuildFunctionInfo(declaration->fun(), info()->script()); |
| 8887 // Check for stack-overflow exception. | 8942 // Check for stack-overflow exception. |
| 8888 if (function.is_null()) return SetStackOverflow(); | 8943 if (function.is_null()) return SetStackOverflow(); |
| 8889 globals_.Add(function, zone()); | 8944 globals_.Add(function, zone()); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 8907 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8962 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); |
| 8908 } | 8963 } |
| 8909 break; | 8964 break; |
| 8910 } | 8965 } |
| 8911 case Variable::LOOKUP: | 8966 case Variable::LOOKUP: |
| 8912 return Bailout("unsupported lookup slot in declaration"); | 8967 return Bailout("unsupported lookup slot in declaration"); |
| 8913 } | 8968 } |
| 8914 } | 8969 } |
| 8915 | 8970 |
| 8916 | 8971 |
| 8917 void HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 8972 void HOptimizedGraphBuilder::VisitModuleDeclaration( |
| 8973 ModuleDeclaration* declaration) { | |
| 8918 UNREACHABLE(); | 8974 UNREACHABLE(); |
| 8919 } | 8975 } |
| 8920 | 8976 |
| 8921 | 8977 |
| 8922 void HGraphBuilder::VisitImportDeclaration(ImportDeclaration* declaration) { | 8978 void HOptimizedGraphBuilder::VisitImportDeclaration( |
| 8979 ImportDeclaration* declaration) { | |
| 8923 UNREACHABLE(); | 8980 UNREACHABLE(); |
| 8924 } | 8981 } |
| 8925 | 8982 |
| 8926 | 8983 |
| 8927 void HGraphBuilder::VisitExportDeclaration(ExportDeclaration* declaration) { | 8984 void HOptimizedGraphBuilder::VisitExportDeclaration( |
| 8985 ExportDeclaration* declaration) { | |
| 8928 UNREACHABLE(); | 8986 UNREACHABLE(); |
| 8929 } | 8987 } |
| 8930 | 8988 |
| 8931 | 8989 |
| 8932 void HGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) { | 8990 void HOptimizedGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) { |
| 8933 UNREACHABLE(); | 8991 UNREACHABLE(); |
| 8934 } | 8992 } |
| 8935 | 8993 |
| 8936 | 8994 |
| 8937 void HGraphBuilder::VisitModuleVariable(ModuleVariable* module) { | 8995 void HOptimizedGraphBuilder::VisitModuleVariable(ModuleVariable* module) { |
| 8938 UNREACHABLE(); | 8996 UNREACHABLE(); |
| 8939 } | 8997 } |
| 8940 | 8998 |
| 8941 | 8999 |
| 8942 void HGraphBuilder::VisitModulePath(ModulePath* module) { | 9000 void HOptimizedGraphBuilder::VisitModulePath(ModulePath* module) { |
| 8943 UNREACHABLE(); | 9001 UNREACHABLE(); |
| 8944 } | 9002 } |
| 8945 | 9003 |
| 8946 | 9004 |
| 8947 void HGraphBuilder::VisitModuleUrl(ModuleUrl* module) { | 9005 void HOptimizedGraphBuilder::VisitModuleUrl(ModuleUrl* module) { |
| 8948 UNREACHABLE(); | 9006 UNREACHABLE(); |
| 8949 } | 9007 } |
| 8950 | 9008 |
| 8951 | 9009 |
| 8952 void HGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { | 9010 void HOptimizedGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { |
| 8953 UNREACHABLE(); | 9011 UNREACHABLE(); |
| 8954 } | 9012 } |
| 8955 | 9013 |
| 8956 | 9014 |
| 8957 // Generators for inline runtime functions. | 9015 // Generators for inline runtime functions. |
| 8958 // Support for types. | 9016 // Support for types. |
| 8959 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { | 9017 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) { |
| 8960 ASSERT(call->arguments()->length() == 1); | 9018 ASSERT(call->arguments()->length() == 1); |
| 8961 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9019 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 8962 HValue* value = Pop(); | 9020 HValue* value = Pop(); |
| 8963 HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value); | 9021 HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value); |
| 8964 return ast_context()->ReturnControl(result, call->id()); | 9022 return ast_context()->ReturnControl(result, call->id()); |
| 8965 } | 9023 } |
| 8966 | 9024 |
| 8967 | 9025 |
| 8968 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { | 9026 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { |
| 8969 ASSERT(call->arguments()->length() == 1); | 9027 ASSERT(call->arguments()->length() == 1); |
| 8970 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9028 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 8971 HValue* value = Pop(); | 9029 HValue* value = Pop(); |
| 8972 HHasInstanceTypeAndBranch* result = | 9030 HHasInstanceTypeAndBranch* result = |
| 8973 new(zone()) HHasInstanceTypeAndBranch(value, | 9031 new(zone()) HHasInstanceTypeAndBranch(value, |
| 8974 FIRST_SPEC_OBJECT_TYPE, | 9032 FIRST_SPEC_OBJECT_TYPE, |
| 8975 LAST_SPEC_OBJECT_TYPE); | 9033 LAST_SPEC_OBJECT_TYPE); |
| 8976 return ast_context()->ReturnControl(result, call->id()); | 9034 return ast_context()->ReturnControl(result, call->id()); |
| 8977 } | 9035 } |
| 8978 | 9036 |
| 8979 | 9037 |
| 8980 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { | 9038 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) { |
| 8981 ASSERT(call->arguments()->length() == 1); | 9039 ASSERT(call->arguments()->length() == 1); |
| 8982 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9040 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 8983 HValue* value = Pop(); | 9041 HValue* value = Pop(); |
| 8984 HHasInstanceTypeAndBranch* result = | 9042 HHasInstanceTypeAndBranch* result = |
| 8985 new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE); | 9043 new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE); |
| 8986 return ast_context()->ReturnControl(result, call->id()); | 9044 return ast_context()->ReturnControl(result, call->id()); |
| 8987 } | 9045 } |
| 8988 | 9046 |
| 8989 | 9047 |
| 8990 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { | 9048 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { |
| 8991 ASSERT(call->arguments()->length() == 1); | 9049 ASSERT(call->arguments()->length() == 1); |
| 8992 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9050 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 8993 HValue* value = Pop(); | 9051 HValue* value = Pop(); |
| 8994 HHasCachedArrayIndexAndBranch* result = | 9052 HHasCachedArrayIndexAndBranch* result = |
| 8995 new(zone()) HHasCachedArrayIndexAndBranch(value); | 9053 new(zone()) HHasCachedArrayIndexAndBranch(value); |
| 8996 return ast_context()->ReturnControl(result, call->id()); | 9054 return ast_context()->ReturnControl(result, call->id()); |
| 8997 } | 9055 } |
| 8998 | 9056 |
| 8999 | 9057 |
| 9000 void HGraphBuilder::GenerateIsArray(CallRuntime* call) { | 9058 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) { |
| 9001 ASSERT(call->arguments()->length() == 1); | 9059 ASSERT(call->arguments()->length() == 1); |
| 9002 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9060 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9003 HValue* value = Pop(); | 9061 HValue* value = Pop(); |
| 9004 HHasInstanceTypeAndBranch* result = | 9062 HHasInstanceTypeAndBranch* result = |
| 9005 new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE); | 9063 new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE); |
| 9006 return ast_context()->ReturnControl(result, call->id()); | 9064 return ast_context()->ReturnControl(result, call->id()); |
| 9007 } | 9065 } |
| 9008 | 9066 |
| 9009 | 9067 |
| 9010 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { | 9068 void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) { |
| 9011 ASSERT(call->arguments()->length() == 1); | 9069 ASSERT(call->arguments()->length() == 1); |
| 9012 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9070 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9013 HValue* value = Pop(); | 9071 HValue* value = Pop(); |
| 9014 HHasInstanceTypeAndBranch* result = | 9072 HHasInstanceTypeAndBranch* result = |
| 9015 new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE); | 9073 new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE); |
| 9016 return ast_context()->ReturnControl(result, call->id()); | 9074 return ast_context()->ReturnControl(result, call->id()); |
| 9017 } | 9075 } |
| 9018 | 9076 |
| 9019 | 9077 |
| 9020 void HGraphBuilder::GenerateIsObject(CallRuntime* call) { | 9078 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) { |
| 9021 ASSERT(call->arguments()->length() == 1); | 9079 ASSERT(call->arguments()->length() == 1); |
| 9022 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9080 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9023 HValue* value = Pop(); | 9081 HValue* value = Pop(); |
| 9024 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); | 9082 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); |
| 9025 return ast_context()->ReturnControl(result, call->id()); | 9083 return ast_context()->ReturnControl(result, call->id()); |
| 9026 } | 9084 } |
| 9027 | 9085 |
| 9028 | 9086 |
| 9029 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { | 9087 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { |
| 9030 return Bailout("inlined runtime function: IsNonNegativeSmi"); | 9088 return Bailout("inlined runtime function: IsNonNegativeSmi"); |
| 9031 } | 9089 } |
| 9032 | 9090 |
| 9033 | 9091 |
| 9034 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { | 9092 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { |
| 9035 ASSERT(call->arguments()->length() == 1); | 9093 ASSERT(call->arguments()->length() == 1); |
| 9036 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9094 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9037 HValue* value = Pop(); | 9095 HValue* value = Pop(); |
| 9038 HIsUndetectableAndBranch* result = | 9096 HIsUndetectableAndBranch* result = |
| 9039 new(zone()) HIsUndetectableAndBranch(value); | 9097 new(zone()) HIsUndetectableAndBranch(value); |
| 9040 return ast_context()->ReturnControl(result, call->id()); | 9098 return ast_context()->ReturnControl(result, call->id()); |
| 9041 } | 9099 } |
| 9042 | 9100 |
| 9043 | 9101 |
| 9044 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( | 9102 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( |
| 9045 CallRuntime* call) { | 9103 CallRuntime* call) { |
| 9046 return Bailout( | 9104 return Bailout( |
| 9047 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); | 9105 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); |
| 9048 } | 9106 } |
| 9049 | 9107 |
| 9050 | 9108 |
| 9051 // Support for construct call checks. | 9109 // Support for construct call checks. |
| 9052 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { | 9110 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { |
| 9053 ASSERT(call->arguments()->length() == 0); | 9111 ASSERT(call->arguments()->length() == 0); |
| 9054 if (function_state()->outer() != NULL) { | 9112 if (function_state()->outer() != NULL) { |
| 9055 // We are generating graph for inlined function. | 9113 // We are generating graph for inlined function. |
| 9056 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN | 9114 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN |
| 9057 ? graph()->GetConstantTrue() | 9115 ? graph()->GetConstantTrue() |
| 9058 : graph()->GetConstantFalse(); | 9116 : graph()->GetConstantFalse(); |
| 9059 return ast_context()->ReturnValue(value); | 9117 return ast_context()->ReturnValue(value); |
| 9060 } else { | 9118 } else { |
| 9061 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, | 9119 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, |
| 9062 call->id()); | 9120 call->id()); |
| 9063 } | 9121 } |
| 9064 } | 9122 } |
| 9065 | 9123 |
| 9066 | 9124 |
| 9067 // Support for arguments.length and arguments[?]. | 9125 // Support for arguments.length and arguments[?]. |
| 9068 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { | 9126 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { |
| 9069 // Our implementation of arguments (based on this stack frame or an | 9127 // Our implementation of arguments (based on this stack frame or an |
| 9070 // adapter below it) does not work for inlined functions. This runtime | 9128 // adapter below it) does not work for inlined functions. This runtime |
| 9071 // function is blacklisted by AstNode::IsInlineable. | 9129 // function is blacklisted by AstNode::IsInlineable. |
| 9072 ASSERT(function_state()->outer() == NULL); | 9130 ASSERT(function_state()->outer() == NULL); |
| 9073 ASSERT(call->arguments()->length() == 0); | 9131 ASSERT(call->arguments()->length() == 0); |
| 9074 HInstruction* elements = AddInstruction( | 9132 HInstruction* elements = AddInstruction( |
| 9075 new(zone()) HArgumentsElements(false)); | 9133 new(zone()) HArgumentsElements(false)); |
| 9076 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); | 9134 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); |
| 9077 return ast_context()->ReturnInstruction(result, call->id()); | 9135 return ast_context()->ReturnInstruction(result, call->id()); |
| 9078 } | 9136 } |
| 9079 | 9137 |
| 9080 | 9138 |
| 9081 void HGraphBuilder::GenerateArguments(CallRuntime* call) { | 9139 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { |
| 9082 // Our implementation of arguments (based on this stack frame or an | 9140 // Our implementation of arguments (based on this stack frame or an |
| 9083 // adapter below it) does not work for inlined functions. This runtime | 9141 // adapter below it) does not work for inlined functions. This runtime |
| 9084 // function is blacklisted by AstNode::IsInlineable. | 9142 // function is blacklisted by AstNode::IsInlineable. |
| 9085 ASSERT(function_state()->outer() == NULL); | 9143 ASSERT(function_state()->outer() == NULL); |
| 9086 ASSERT(call->arguments()->length() == 1); | 9144 ASSERT(call->arguments()->length() == 1); |
| 9087 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9145 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9088 HValue* index = Pop(); | 9146 HValue* index = Pop(); |
| 9089 HInstruction* elements = AddInstruction( | 9147 HInstruction* elements = AddInstruction( |
| 9090 new(zone()) HArgumentsElements(false)); | 9148 new(zone()) HArgumentsElements(false)); |
| 9091 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); | 9149 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
| 9092 HInstruction* checked_index = | 9150 HInstruction* checked_index = |
| 9093 AddInstruction(new(zone()) HBoundsCheck(index, length)); | 9151 AddInstruction(new(zone()) HBoundsCheck(index, length)); |
| 9094 HAccessArgumentsAt* result = | 9152 HAccessArgumentsAt* result = |
| 9095 new(zone()) HAccessArgumentsAt(elements, length, checked_index); | 9153 new(zone()) HAccessArgumentsAt(elements, length, checked_index); |
| 9096 return ast_context()->ReturnInstruction(result, call->id()); | 9154 return ast_context()->ReturnInstruction(result, call->id()); |
| 9097 } | 9155 } |
| 9098 | 9156 |
| 9099 | 9157 |
| 9100 // Support for accessing the class and value fields of an object. | 9158 // Support for accessing the class and value fields of an object. |
| 9101 void HGraphBuilder::GenerateClassOf(CallRuntime* call) { | 9159 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { |
| 9102 // The special form detected by IsClassOfTest is detected before we get here | 9160 // The special form detected by IsClassOfTest is detected before we get here |
| 9103 // and does not cause a bailout. | 9161 // and does not cause a bailout. |
| 9104 return Bailout("inlined runtime function: ClassOf"); | 9162 return Bailout("inlined runtime function: ClassOf"); |
| 9105 } | 9163 } |
| 9106 | 9164 |
| 9107 | 9165 |
| 9108 void HGraphBuilder::GenerateValueOf(CallRuntime* call) { | 9166 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) { |
| 9109 ASSERT(call->arguments()->length() == 1); | 9167 ASSERT(call->arguments()->length() == 1); |
| 9110 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9168 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9111 HValue* value = Pop(); | 9169 HValue* value = Pop(); |
| 9112 HValueOf* result = new(zone()) HValueOf(value); | 9170 HValueOf* result = new(zone()) HValueOf(value); |
| 9113 return ast_context()->ReturnInstruction(result, call->id()); | 9171 return ast_context()->ReturnInstruction(result, call->id()); |
| 9114 } | 9172 } |
| 9115 | 9173 |
| 9116 | 9174 |
| 9117 void HGraphBuilder::GenerateDateField(CallRuntime* call) { | 9175 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) { |
| 9118 ASSERT(call->arguments()->length() == 2); | 9176 ASSERT(call->arguments()->length() == 2); |
| 9119 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); | 9177 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); |
| 9120 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle())); | 9178 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle())); |
| 9121 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9179 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9122 HValue* date = Pop(); | 9180 HValue* date = Pop(); |
| 9123 HDateField* result = new(zone()) HDateField(date, index); | 9181 HDateField* result = new(zone()) HDateField(date, index); |
| 9124 return ast_context()->ReturnInstruction(result, call->id()); | 9182 return ast_context()->ReturnInstruction(result, call->id()); |
| 9125 } | 9183 } |
| 9126 | 9184 |
| 9127 | 9185 |
| 9128 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { | 9186 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { |
| 9129 ASSERT(call->arguments()->length() == 2); | 9187 ASSERT(call->arguments()->length() == 2); |
| 9130 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9188 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9131 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9189 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9132 HValue* value = Pop(); | 9190 HValue* value = Pop(); |
| 9133 HValue* object = Pop(); | 9191 HValue* object = Pop(); |
| 9134 // Check if object is a not a smi. | 9192 // Check if object is a not a smi. |
| 9135 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(object); | 9193 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(object); |
| 9136 HBasicBlock* if_smi = graph()->CreateBasicBlock(); | 9194 HBasicBlock* if_smi = graph()->CreateBasicBlock(); |
| 9137 HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); | 9195 HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); |
| 9138 HBasicBlock* join = graph()->CreateBasicBlock(); | 9196 HBasicBlock* join = graph()->CreateBasicBlock(); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 9161 true, // in-object store. | 9219 true, // in-object store. |
| 9162 JSValue::kValueOffset)); | 9220 JSValue::kValueOffset)); |
| 9163 if_js_value->Goto(join); | 9221 if_js_value->Goto(join); |
| 9164 join->SetJoinId(call->id()); | 9222 join->SetJoinId(call->id()); |
| 9165 set_current_block(join); | 9223 set_current_block(join); |
| 9166 return ast_context()->ReturnValue(value); | 9224 return ast_context()->ReturnValue(value); |
| 9167 } | 9225 } |
| 9168 | 9226 |
| 9169 | 9227 |
| 9170 // Fast support for charCodeAt(n). | 9228 // Fast support for charCodeAt(n). |
| 9171 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 9229 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
| 9172 ASSERT(call->arguments()->length() == 2); | 9230 ASSERT(call->arguments()->length() == 2); |
| 9173 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9231 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9174 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9232 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9175 HValue* index = Pop(); | 9233 HValue* index = Pop(); |
| 9176 HValue* string = Pop(); | 9234 HValue* string = Pop(); |
| 9177 HValue* context = environment()->LookupContext(); | 9235 HValue* context = environment()->LookupContext(); |
| 9178 HStringCharCodeAt* result = BuildStringCharCodeAt(context, string, index); | 9236 HStringCharCodeAt* result = BuildStringCharCodeAt(context, string, index); |
| 9179 return ast_context()->ReturnInstruction(result, call->id()); | 9237 return ast_context()->ReturnInstruction(result, call->id()); |
| 9180 } | 9238 } |
| 9181 | 9239 |
| 9182 | 9240 |
| 9183 // Fast support for string.charAt(n) and string[n]. | 9241 // Fast support for string.charAt(n) and string[n]. |
| 9184 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { | 9242 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { |
| 9185 ASSERT(call->arguments()->length() == 1); | 9243 ASSERT(call->arguments()->length() == 1); |
| 9186 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9244 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9187 HValue* char_code = Pop(); | 9245 HValue* char_code = Pop(); |
| 9188 HValue* context = environment()->LookupContext(); | 9246 HValue* context = environment()->LookupContext(); |
| 9189 HStringCharFromCode* result = | 9247 HStringCharFromCode* result = |
| 9190 new(zone()) HStringCharFromCode(context, char_code); | 9248 new(zone()) HStringCharFromCode(context, char_code); |
| 9191 return ast_context()->ReturnInstruction(result, call->id()); | 9249 return ast_context()->ReturnInstruction(result, call->id()); |
| 9192 } | 9250 } |
| 9193 | 9251 |
| 9194 | 9252 |
| 9195 // Fast support for string.charAt(n) and string[n]. | 9253 // Fast support for string.charAt(n) and string[n]. |
| 9196 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { | 9254 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) { |
| 9197 ASSERT(call->arguments()->length() == 2); | 9255 ASSERT(call->arguments()->length() == 2); |
| 9198 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9256 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9199 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9257 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9200 HValue* index = Pop(); | 9258 HValue* index = Pop(); |
| 9201 HValue* string = Pop(); | 9259 HValue* string = Pop(); |
| 9202 HValue* context = environment()->LookupContext(); | 9260 HValue* context = environment()->LookupContext(); |
| 9203 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index); | 9261 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index); |
| 9204 AddInstruction(char_code); | 9262 AddInstruction(char_code); |
| 9205 HStringCharFromCode* result = | 9263 HStringCharFromCode* result = |
| 9206 new(zone()) HStringCharFromCode(context, char_code); | 9264 new(zone()) HStringCharFromCode(context, char_code); |
| 9207 return ast_context()->ReturnInstruction(result, call->id()); | 9265 return ast_context()->ReturnInstruction(result, call->id()); |
| 9208 } | 9266 } |
| 9209 | 9267 |
| 9210 | 9268 |
| 9211 // Fast support for object equality testing. | 9269 // Fast support for object equality testing. |
| 9212 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { | 9270 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) { |
| 9213 ASSERT(call->arguments()->length() == 2); | 9271 ASSERT(call->arguments()->length() == 2); |
| 9214 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9272 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9215 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9273 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9216 HValue* right = Pop(); | 9274 HValue* right = Pop(); |
| 9217 HValue* left = Pop(); | 9275 HValue* left = Pop(); |
| 9218 HCompareObjectEqAndBranch* result = | 9276 HCompareObjectEqAndBranch* result = |
| 9219 new(zone()) HCompareObjectEqAndBranch(left, right); | 9277 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 9220 return ast_context()->ReturnControl(result, call->id()); | 9278 return ast_context()->ReturnControl(result, call->id()); |
| 9221 } | 9279 } |
| 9222 | 9280 |
| 9223 | 9281 |
| 9224 void HGraphBuilder::GenerateLog(CallRuntime* call) { | 9282 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { |
| 9225 // %_Log is ignored in optimized code. | 9283 // %_Log is ignored in optimized code. |
| 9226 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 9284 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
| 9227 } | 9285 } |
| 9228 | 9286 |
| 9229 | 9287 |
| 9230 // Fast support for Math.random(). | 9288 // Fast support for Math.random(). |
| 9231 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { | 9289 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { |
| 9232 HValue* context = environment()->LookupContext(); | 9290 HValue* context = environment()->LookupContext(); |
| 9233 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 9291 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 9234 AddInstruction(global_object); | 9292 AddInstruction(global_object); |
| 9235 HRandom* result = new(zone()) HRandom(global_object); | 9293 HRandom* result = new(zone()) HRandom(global_object); |
| 9236 return ast_context()->ReturnInstruction(result, call->id()); | 9294 return ast_context()->ReturnInstruction(result, call->id()); |
| 9237 } | 9295 } |
| 9238 | 9296 |
| 9239 | 9297 |
| 9240 // Fast support for StringAdd. | 9298 // Fast support for StringAdd. |
| 9241 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 9299 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
| 9242 ASSERT_EQ(2, call->arguments()->length()); | 9300 ASSERT_EQ(2, call->arguments()->length()); |
| 9243 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9301 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9244 HValue* context = environment()->LookupContext(); | 9302 HValue* context = environment()->LookupContext(); |
| 9245 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); | 9303 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); |
| 9246 Drop(2); | 9304 Drop(2); |
| 9247 return ast_context()->ReturnInstruction(result, call->id()); | 9305 return ast_context()->ReturnInstruction(result, call->id()); |
| 9248 } | 9306 } |
| 9249 | 9307 |
| 9250 | 9308 |
| 9251 // Fast support for SubString. | 9309 // Fast support for SubString. |
| 9252 void HGraphBuilder::GenerateSubString(CallRuntime* call) { | 9310 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { |
| 9253 ASSERT_EQ(3, call->arguments()->length()); | 9311 ASSERT_EQ(3, call->arguments()->length()); |
| 9254 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9312 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9255 HValue* context = environment()->LookupContext(); | 9313 HValue* context = environment()->LookupContext(); |
| 9256 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); | 9314 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); |
| 9257 Drop(3); | 9315 Drop(3); |
| 9258 return ast_context()->ReturnInstruction(result, call->id()); | 9316 return ast_context()->ReturnInstruction(result, call->id()); |
| 9259 } | 9317 } |
| 9260 | 9318 |
| 9261 | 9319 |
| 9262 // Fast support for StringCompare. | 9320 // Fast support for StringCompare. |
| 9263 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { | 9321 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
| 9264 ASSERT_EQ(2, call->arguments()->length()); | 9322 ASSERT_EQ(2, call->arguments()->length()); |
| 9265 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9323 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9266 HValue* context = environment()->LookupContext(); | 9324 HValue* context = environment()->LookupContext(); |
| 9267 HCallStub* result = | 9325 HCallStub* result = |
| 9268 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); | 9326 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); |
| 9269 Drop(2); | 9327 Drop(2); |
| 9270 return ast_context()->ReturnInstruction(result, call->id()); | 9328 return ast_context()->ReturnInstruction(result, call->id()); |
| 9271 } | 9329 } |
| 9272 | 9330 |
| 9273 | 9331 |
| 9274 // Support for direct calls from JavaScript to native RegExp code. | 9332 // Support for direct calls from JavaScript to native RegExp code. |
| 9275 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { | 9333 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
| 9276 ASSERT_EQ(4, call->arguments()->length()); | 9334 ASSERT_EQ(4, call->arguments()->length()); |
| 9277 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9335 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9278 HValue* context = environment()->LookupContext(); | 9336 HValue* context = environment()->LookupContext(); |
| 9279 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); | 9337 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); |
| 9280 Drop(4); | 9338 Drop(4); |
| 9281 return ast_context()->ReturnInstruction(result, call->id()); | 9339 return ast_context()->ReturnInstruction(result, call->id()); |
| 9282 } | 9340 } |
| 9283 | 9341 |
| 9284 | 9342 |
| 9285 // Construct a RegExp exec result with two in-object properties. | 9343 // Construct a RegExp exec result with two in-object properties. |
| 9286 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { | 9344 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
| 9287 ASSERT_EQ(3, call->arguments()->length()); | 9345 ASSERT_EQ(3, call->arguments()->length()); |
| 9288 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9346 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9289 HValue* context = environment()->LookupContext(); | 9347 HValue* context = environment()->LookupContext(); |
| 9290 HCallStub* result = | 9348 HCallStub* result = |
| 9291 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); | 9349 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); |
| 9292 Drop(3); | 9350 Drop(3); |
| 9293 return ast_context()->ReturnInstruction(result, call->id()); | 9351 return ast_context()->ReturnInstruction(result, call->id()); |
| 9294 } | 9352 } |
| 9295 | 9353 |
| 9296 | 9354 |
| 9297 // Support for fast native caches. | 9355 // Support for fast native caches. |
| 9298 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 9356 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
| 9299 return Bailout("inlined runtime function: GetFromCache"); | 9357 return Bailout("inlined runtime function: GetFromCache"); |
| 9300 } | 9358 } |
| 9301 | 9359 |
| 9302 | 9360 |
| 9303 // Fast support for number to string. | 9361 // Fast support for number to string. |
| 9304 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 9362 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
| 9305 ASSERT_EQ(1, call->arguments()->length()); | 9363 ASSERT_EQ(1, call->arguments()->length()); |
| 9306 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9364 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9307 HValue* context = environment()->LookupContext(); | 9365 HValue* context = environment()->LookupContext(); |
| 9308 HCallStub* result = | 9366 HCallStub* result = |
| 9309 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); | 9367 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); |
| 9310 Drop(1); | 9368 Drop(1); |
| 9311 return ast_context()->ReturnInstruction(result, call->id()); | 9369 return ast_context()->ReturnInstruction(result, call->id()); |
| 9312 } | 9370 } |
| 9313 | 9371 |
| 9314 | 9372 |
| 9315 // Fast call for custom callbacks. | 9373 // Fast call for custom callbacks. |
| 9316 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 9374 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
| 9317 // 1 ~ The function to call is not itself an argument to the call. | 9375 // 1 ~ The function to call is not itself an argument to the call. |
| 9318 int arg_count = call->arguments()->length() - 1; | 9376 int arg_count = call->arguments()->length() - 1; |
| 9319 ASSERT(arg_count >= 1); // There's always at least a receiver. | 9377 ASSERT(arg_count >= 1); // There's always at least a receiver. |
| 9320 | 9378 |
| 9321 for (int i = 0; i < arg_count; ++i) { | 9379 for (int i = 0; i < arg_count; ++i) { |
| 9322 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); | 9380 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); |
| 9323 } | 9381 } |
| 9324 CHECK_ALIVE(VisitForValue(call->arguments()->last())); | 9382 CHECK_ALIVE(VisitForValue(call->arguments()->last())); |
| 9325 | 9383 |
| 9326 HValue* function = Pop(); | 9384 HValue* function = Pop(); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 9350 Push(call_result); | 9408 Push(call_result); |
| 9351 if_nonfunction->Goto(join); | 9409 if_nonfunction->Goto(join); |
| 9352 | 9410 |
| 9353 set_current_block(join); | 9411 set_current_block(join); |
| 9354 join->SetJoinId(call->id()); | 9412 join->SetJoinId(call->id()); |
| 9355 return ast_context()->ReturnValue(Pop()); | 9413 return ast_context()->ReturnValue(Pop()); |
| 9356 } | 9414 } |
| 9357 | 9415 |
| 9358 | 9416 |
| 9359 // Fast call to math functions. | 9417 // Fast call to math functions. |
| 9360 void HGraphBuilder::GenerateMathPow(CallRuntime* call) { | 9418 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { |
| 9361 ASSERT_EQ(2, call->arguments()->length()); | 9419 ASSERT_EQ(2, call->arguments()->length()); |
| 9362 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9420 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9363 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9421 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9364 HValue* right = Pop(); | 9422 HValue* right = Pop(); |
| 9365 HValue* left = Pop(); | 9423 HValue* left = Pop(); |
| 9366 HPower* result = new(zone()) HPower(left, right); | 9424 HPower* result = new(zone()) HPower(left, right); |
| 9367 return ast_context()->ReturnInstruction(result, call->id()); | 9425 return ast_context()->ReturnInstruction(result, call->id()); |
| 9368 } | 9426 } |
| 9369 | 9427 |
| 9370 | 9428 |
| 9371 void HGraphBuilder::GenerateMathSin(CallRuntime* call) { | 9429 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) { |
| 9372 ASSERT_EQ(1, call->arguments()->length()); | 9430 ASSERT_EQ(1, call->arguments()->length()); |
| 9373 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9431 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9374 HValue* context = environment()->LookupContext(); | 9432 HValue* context = environment()->LookupContext(); |
| 9375 HCallStub* result = | 9433 HCallStub* result = |
| 9376 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9434 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| 9377 result->set_transcendental_type(TranscendentalCache::SIN); | 9435 result->set_transcendental_type(TranscendentalCache::SIN); |
| 9378 Drop(1); | 9436 Drop(1); |
| 9379 return ast_context()->ReturnInstruction(result, call->id()); | 9437 return ast_context()->ReturnInstruction(result, call->id()); |
| 9380 } | 9438 } |
| 9381 | 9439 |
| 9382 | 9440 |
| 9383 void HGraphBuilder::GenerateMathCos(CallRuntime* call) { | 9441 void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) { |
| 9384 ASSERT_EQ(1, call->arguments()->length()); | 9442 ASSERT_EQ(1, call->arguments()->length()); |
| 9385 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9443 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9386 HValue* context = environment()->LookupContext(); | 9444 HValue* context = environment()->LookupContext(); |
| 9387 HCallStub* result = | 9445 HCallStub* result = |
| 9388 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9446 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| 9389 result->set_transcendental_type(TranscendentalCache::COS); | 9447 result->set_transcendental_type(TranscendentalCache::COS); |
| 9390 Drop(1); | 9448 Drop(1); |
| 9391 return ast_context()->ReturnInstruction(result, call->id()); | 9449 return ast_context()->ReturnInstruction(result, call->id()); |
| 9392 } | 9450 } |
| 9393 | 9451 |
| 9394 | 9452 |
| 9395 void HGraphBuilder::GenerateMathTan(CallRuntime* call) { | 9453 void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) { |
| 9396 ASSERT_EQ(1, call->arguments()->length()); | 9454 ASSERT_EQ(1, call->arguments()->length()); |
| 9397 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9455 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9398 HValue* context = environment()->LookupContext(); | 9456 HValue* context = environment()->LookupContext(); |
| 9399 HCallStub* result = | 9457 HCallStub* result = |
| 9400 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9458 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| 9401 result->set_transcendental_type(TranscendentalCache::TAN); | 9459 result->set_transcendental_type(TranscendentalCache::TAN); |
| 9402 Drop(1); | 9460 Drop(1); |
| 9403 return ast_context()->ReturnInstruction(result, call->id()); | 9461 return ast_context()->ReturnInstruction(result, call->id()); |
| 9404 } | 9462 } |
| 9405 | 9463 |
| 9406 | 9464 |
| 9407 void HGraphBuilder::GenerateMathLog(CallRuntime* call) { | 9465 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) { |
| 9408 ASSERT_EQ(1, call->arguments()->length()); | 9466 ASSERT_EQ(1, call->arguments()->length()); |
| 9409 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9467 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9410 HValue* context = environment()->LookupContext(); | 9468 HValue* context = environment()->LookupContext(); |
| 9411 HCallStub* result = | 9469 HCallStub* result = |
| 9412 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9470 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| 9413 result->set_transcendental_type(TranscendentalCache::LOG); | 9471 result->set_transcendental_type(TranscendentalCache::LOG); |
| 9414 Drop(1); | 9472 Drop(1); |
| 9415 return ast_context()->ReturnInstruction(result, call->id()); | 9473 return ast_context()->ReturnInstruction(result, call->id()); |
| 9416 } | 9474 } |
| 9417 | 9475 |
| 9418 | 9476 |
| 9419 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { | 9477 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
| 9420 return Bailout("inlined runtime function: MathSqrt"); | 9478 return Bailout("inlined runtime function: MathSqrt"); |
| 9421 } | 9479 } |
| 9422 | 9480 |
| 9423 | 9481 |
| 9424 // Check whether two RegExps are equivalent | 9482 // Check whether two RegExps are equivalent |
| 9425 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { | 9483 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
| 9426 return Bailout("inlined runtime function: IsRegExpEquivalent"); | 9484 return Bailout("inlined runtime function: IsRegExpEquivalent"); |
| 9427 } | 9485 } |
| 9428 | 9486 |
| 9429 | 9487 |
| 9430 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { | 9488 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { |
| 9431 ASSERT(call->arguments()->length() == 1); | 9489 ASSERT(call->arguments()->length() == 1); |
| 9432 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9490 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9433 HValue* value = Pop(); | 9491 HValue* value = Pop(); |
| 9434 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); | 9492 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); |
| 9435 return ast_context()->ReturnInstruction(result, call->id()); | 9493 return ast_context()->ReturnInstruction(result, call->id()); |
| 9436 } | 9494 } |
| 9437 | 9495 |
| 9438 | 9496 |
| 9439 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { | 9497 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { |
| 9440 return Bailout("inlined runtime function: FastAsciiArrayJoin"); | 9498 return Bailout("inlined runtime function: FastAsciiArrayJoin"); |
| 9441 } | 9499 } |
| 9442 | 9500 |
| 9443 | 9501 |
| 9444 #undef CHECK_BAILOUT | 9502 #undef CHECK_BAILOUT |
| 9445 #undef CHECK_ALIVE | 9503 #undef CHECK_ALIVE |
| 9446 | 9504 |
| 9447 | 9505 |
| 9448 HEnvironment::HEnvironment(HEnvironment* outer, | 9506 HEnvironment::HEnvironment(HEnvironment* outer, |
| 9449 Scope* scope, | 9507 Scope* scope, |
| 9450 Handle<JSFunction> closure, | 9508 Handle<JSFunction> closure, |
| 9451 Zone* zone) | 9509 Zone* zone) |
| 9452 : closure_(closure), | 9510 : closure_(closure), |
| 9453 values_(0, zone), | 9511 values_(0, zone), |
| 9454 assigned_variables_(4, zone), | 9512 assigned_variables_(4, zone), |
| 9455 frame_type_(JS_FUNCTION), | 9513 frame_type_(JS_FUNCTION), |
| 9456 parameter_count_(0), | 9514 parameter_count_(0), |
| 9457 specials_count_(1), | 9515 specials_count_(1), |
| 9458 local_count_(0), | 9516 local_count_(0), |
| 9459 outer_(outer), | 9517 outer_(outer), |
| 9460 entry_(NULL), | 9518 entry_(NULL), |
| 9461 pop_count_(0), | 9519 pop_count_(0), |
| 9462 push_count_(0), | 9520 push_count_(0), |
| 9463 ast_id_(BailoutId::None()), | 9521 ast_id_(BailoutId::None()), |
| 9464 zone_(zone) { | 9522 zone_(zone) { |
| 9465 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); | 9523 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); |
| 9466 } | 9524 } |
| 9467 | 9525 |
| 9468 | 9526 |
| 9527 HEnvironment::HEnvironment(Zone* zone) | |
| 9528 : values_(0, zone), | |
| 9529 assigned_variables_(0, zone), | |
| 9530 frame_type_(STUB), | |
| 9531 parameter_count_(0), | |
| 9532 specials_count_(0), | |
| 9533 local_count_(0), | |
| 9534 outer_(NULL), | |
| 9535 entry_(NULL), | |
| 9536 pop_count_(0), | |
| 9537 push_count_(0), | |
| 9538 ast_id_(BailoutId::None()), | |
| 9539 zone_(zone) { | |
| 9540 Initialize(0, 0, 0); | |
| 9541 } | |
| 9542 | |
| 9543 | |
| 9469 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone) | 9544 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone) |
| 9470 : values_(0, zone), | 9545 : values_(0, zone), |
| 9471 assigned_variables_(0, zone), | 9546 assigned_variables_(0, zone), |
| 9472 frame_type_(JS_FUNCTION), | 9547 frame_type_(JS_FUNCTION), |
| 9473 parameter_count_(0), | 9548 parameter_count_(0), |
| 9474 specials_count_(1), | 9549 specials_count_(1), |
| 9475 local_count_(0), | 9550 local_count_(0), |
| 9476 outer_(NULL), | 9551 outer_(NULL), |
| 9477 entry_(NULL), | 9552 entry_(NULL), |
| 9478 pop_count_(0), | 9553 pop_count_(0), |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9726 | 9801 |
| 9727 | 9802 |
| 9728 void HEnvironment::PrintToStd() { | 9803 void HEnvironment::PrintToStd() { |
| 9729 HeapStringAllocator string_allocator; | 9804 HeapStringAllocator string_allocator; |
| 9730 StringStream trace(&string_allocator); | 9805 StringStream trace(&string_allocator); |
| 9731 PrintTo(&trace); | 9806 PrintTo(&trace); |
| 9732 PrintF("%s", *trace.ToCString()); | 9807 PrintF("%s", *trace.ToCString()); |
| 9733 } | 9808 } |
| 9734 | 9809 |
| 9735 | 9810 |
| 9736 void HTracer::TraceCompilation(FunctionLiteral* function) { | 9811 void HTracer::TraceCompilation(CompilationInfo* info) { |
| 9737 Tag tag(this, "compilation"); | 9812 Tag tag(this, "compilation"); |
| 9738 Handle<String> name = function->debug_name(); | 9813 if (info->IsOptimizing()) { |
| 9739 PrintStringProperty("name", *name->ToCString()); | 9814 Handle<String> name = info->function()->debug_name(); |
| 9740 PrintStringProperty("method", *name->ToCString()); | 9815 PrintStringProperty("name", *name->ToCString()); |
| 9816 PrintStringProperty("method", *name->ToCString()); | |
| 9817 } else { | |
| 9818 PrintStringProperty("name", "stub"); | |
|
Jakob Kummerow
2012/11/28 16:28:22
Can we print info->stub()->major_key() or somethin
danno
2012/11/30 16:23:24
Done.
| |
| 9819 PrintStringProperty("method", "stub"); | |
| 9820 } | |
| 9741 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); | 9821 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); |
| 9742 } | 9822 } |
| 9743 | 9823 |
| 9744 | 9824 |
| 9745 void HTracer::TraceLithium(const char* name, LChunk* chunk) { | 9825 void HTracer::TraceLithium(const char* name, LChunk* chunk) { |
| 9746 Trace(name, chunk->graph(), chunk); | 9826 Trace(name, chunk->graph(), chunk); |
| 9747 } | 9827 } |
| 9748 | 9828 |
| 9749 | 9829 |
| 9750 void HTracer::TraceHydrogen(const char* name, HGraph* graph) { | 9830 void HTracer::TraceHydrogen(const char* name, HGraph* graph) { |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10059 } | 10139 } |
| 10060 } | 10140 } |
| 10061 | 10141 |
| 10062 #ifdef DEBUG | 10142 #ifdef DEBUG |
| 10063 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 10143 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 10064 if (allocator_ != NULL) allocator_->Verify(); | 10144 if (allocator_ != NULL) allocator_->Verify(); |
| 10065 #endif | 10145 #endif |
| 10066 } | 10146 } |
| 10067 | 10147 |
| 10068 } } // namespace v8::internal | 10148 } } // namespace v8::internal |
| OLD | NEW |