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