| 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 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3928 } | 3755 } |
| 3929 instr->DeleteAndReplaceWith(NULL); | 3756 instr->DeleteAndReplaceWith(NULL); |
| 3930 for (int i = 0; i < instr->OperandCount(); ++i) { | 3757 for (int i = 0; i < instr->OperandCount(); ++i) { |
| 3931 HValue* operand = instr->OperandAt(i); | 3758 HValue* operand = instr->OperandAt(i); |
| 3932 if (operand->IsDead()) worklist.Add(HInstruction::cast(operand), zone()); | 3759 if (operand->IsDead()) worklist.Add(HInstruction::cast(operand), zone()); |
| 3933 } | 3760 } |
| 3934 } | 3761 } |
| 3935 } | 3762 } |
| 3936 | 3763 |
| 3937 | 3764 |
| 3938 void HOptimizedGraphBuilder::AddPhi(HPhi* instr) { | 3765 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
| 3766 ASSERT(current_block() != NULL); |
| 3767 current_block()->AddInstruction(instr); |
| 3768 return instr; |
| 3769 } |
| 3770 |
| 3771 |
| 3772 void HGraphBuilder::AddSimulate(BailoutId ast_id, RemovableSimulate removable) { |
| 3773 ASSERT(current_block() != NULL); |
| 3774 current_block()->AddSimulate(ast_id, removable); |
| 3775 } |
| 3776 |
| 3777 |
| 3778 void HGraphBuilder::AddPhi(HPhi* instr) { |
| 3939 ASSERT(current_block() != NULL); | 3779 ASSERT(current_block() != NULL); |
| 3940 current_block()->AddPhi(instr); | 3780 current_block()->AddPhi(instr); |
| 3941 } | 3781 } |
| 3942 | 3782 |
| 3943 | 3783 |
| 3944 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { | 3784 void HGraphBuilder::PushAndAdd(HInstruction* instr) { |
| 3945 Push(instr); | 3785 Push(instr); |
| 3946 AddInstruction(instr); | 3786 AddInstruction(instr); |
| 3947 } | 3787 } |
| 3948 | 3788 |
| 3949 | 3789 |
| 3950 template <class Instruction> | 3790 template <class Instruction> |
| 3951 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { | 3791 HInstruction* HGraphBuilder::PreProcessCall(Instruction* call) { |
| 3952 int count = call->argument_count(); | 3792 int count = call->argument_count(); |
| 3953 ZoneList<HValue*> arguments(count, zone()); | 3793 ZoneList<HValue*> arguments(count, zone()); |
| 3954 for (int i = 0; i < count; ++i) { | 3794 for (int i = 0; i < count; ++i) { |
| 3955 arguments.Add(Pop(), zone()); | 3795 arguments.Add(Pop(), zone()); |
| 3956 } | 3796 } |
| 3957 | 3797 |
| 3958 while (!arguments.is_empty()) { | 3798 while (!arguments.is_empty()) { |
| 3959 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); | 3799 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); |
| 3960 } | 3800 } |
| 3961 return call; | 3801 return call; |
| 3962 } | 3802 } |
| 3963 | 3803 |
| 3964 | 3804 |
| 3965 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { | 3805 void HGraphBuilder::SetUpScope(Scope* scope) { |
| 3966 HConstant* undefined_constant = new(zone()) HConstant( | 3806 HConstant* undefined_constant = new(zone()) HConstant( |
| 3967 isolate()->factory()->undefined_value(), Representation::Tagged()); | 3807 isolate()->factory()->undefined_value(), Representation::Tagged()); |
| 3968 AddInstruction(undefined_constant); | 3808 AddInstruction(undefined_constant); |
| 3969 graph()->set_undefined_constant(undefined_constant); | 3809 graph_->set_undefined_constant(undefined_constant); |
| 3970 | 3810 |
| 3971 HArgumentsObject* object = new(zone()) HArgumentsObject; | 3811 HArgumentsObject* object = new(zone()) HArgumentsObject; |
| 3972 AddInstruction(object); | 3812 AddInstruction(object); |
| 3973 graph()->SetArgumentsObject(object); | 3813 graph()->SetArgumentsObject(object); |
| 3974 | 3814 |
| 3975 // Set the initial values of parameters including "this". "This" has | 3815 // Set the initial values of parameters including "this". "This" has |
| 3976 // parameter index 0. | 3816 // parameter index 0. |
| 3977 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); | 3817 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); |
| 3978 | 3818 |
| 3979 for (int i = 0; i < environment()->parameter_count(); ++i) { | 3819 for (int i = 0; i < environment()->parameter_count(); ++i) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3998 if (!scope->arguments()->IsStackAllocated()) { | 3838 if (!scope->arguments()->IsStackAllocated()) { |
| 3999 return Bailout("context-allocated arguments"); | 3839 return Bailout("context-allocated arguments"); |
| 4000 } | 3840 } |
| 4001 | 3841 |
| 4002 environment()->Bind(scope->arguments(), | 3842 environment()->Bind(scope->arguments(), |
| 4003 graph()->GetArgumentsObject()); | 3843 graph()->GetArgumentsObject()); |
| 4004 } | 3844 } |
| 4005 } | 3845 } |
| 4006 | 3846 |
| 4007 | 3847 |
| 4008 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { | 3848 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { |
| 4009 for (int i = 0; i < statements->length(); i++) { | 3849 for (int i = 0; i < statements->length(); i++) { |
| 4010 CHECK_ALIVE(Visit(statements->at(i))); | 3850 CHECK_ALIVE(Visit(statements->at(i))); |
| 4011 } | 3851 } |
| 4012 } | 3852 } |
| 4013 | 3853 |
| 4014 | 3854 |
| 4015 HBasicBlock* HOptimizedGraphBuilder::CreateBasicBlock(HEnvironment* env) { | 3855 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
| 4016 HBasicBlock* b = graph()->CreateBasicBlock(); | 3856 HBasicBlock* b = graph()->CreateBasicBlock(); |
| 4017 b->SetInitialEnvironment(env); | 3857 b->SetInitialEnvironment(env); |
| 4018 return b; | 3858 return b; |
| 4019 } | 3859 } |
| 4020 | 3860 |
| 4021 | 3861 |
| 4022 HBasicBlock* HOptimizedGraphBuilder::CreateLoopHeaderBlock() { | 3862 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
| 4023 HBasicBlock* header = graph()->CreateBasicBlock(); | 3863 HBasicBlock* header = graph()->CreateBasicBlock(); |
| 4024 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 3864 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
| 4025 header->SetInitialEnvironment(entry_env); | 3865 header->SetInitialEnvironment(entry_env); |
| 4026 header->AttachLoopInformation(); | 3866 header->AttachLoopInformation(); |
| 4027 return header; | 3867 return header; |
| 4028 } | 3868 } |
| 4029 | 3869 |
| 4030 | 3870 |
| 4031 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) { | 3871 void HGraphBuilder::VisitBlock(Block* stmt) { |
| 4032 ASSERT(!HasStackOverflow()); | 3872 ASSERT(!HasStackOverflow()); |
| 4033 ASSERT(current_block() != NULL); | 3873 ASSERT(current_block() != NULL); |
| 4034 ASSERT(current_block()->HasPredecessor()); | 3874 ASSERT(current_block()->HasPredecessor()); |
| 4035 if (stmt->scope() != NULL) { | 3875 if (stmt->scope() != NULL) { |
| 4036 return Bailout("ScopedBlock"); | 3876 return Bailout("ScopedBlock"); |
| 4037 } | 3877 } |
| 4038 BreakAndContinueInfo break_info(stmt); | 3878 BreakAndContinueInfo break_info(stmt); |
| 4039 { BreakAndContinueScope push(&break_info, this); | 3879 { BreakAndContinueScope push(&break_info, this); |
| 4040 CHECK_BAILOUT(VisitStatements(stmt->statements())); | 3880 CHECK_BAILOUT(VisitStatements(stmt->statements())); |
| 4041 } | 3881 } |
| 4042 HBasicBlock* break_block = break_info.break_block(); | 3882 HBasicBlock* break_block = break_info.break_block(); |
| 4043 if (break_block != NULL) { | 3883 if (break_block != NULL) { |
| 4044 if (current_block() != NULL) current_block()->Goto(break_block); | 3884 if (current_block() != NULL) current_block()->Goto(break_block); |
| 4045 break_block->SetJoinId(stmt->ExitId()); | 3885 break_block->SetJoinId(stmt->ExitId()); |
| 4046 set_current_block(break_block); | 3886 set_current_block(break_block); |
| 4047 } | 3887 } |
| 4048 } | 3888 } |
| 4049 | 3889 |
| 4050 | 3890 |
| 4051 void HOptimizedGraphBuilder::VisitExpressionStatement( | 3891 void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { |
| 4052 ExpressionStatement* stmt) { | |
| 4053 ASSERT(!HasStackOverflow()); | 3892 ASSERT(!HasStackOverflow()); |
| 4054 ASSERT(current_block() != NULL); | 3893 ASSERT(current_block() != NULL); |
| 4055 ASSERT(current_block()->HasPredecessor()); | 3894 ASSERT(current_block()->HasPredecessor()); |
| 4056 VisitForEffect(stmt->expression()); | 3895 VisitForEffect(stmt->expression()); |
| 4057 } | 3896 } |
| 4058 | 3897 |
| 4059 | 3898 |
| 4060 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { | 3899 void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { |
| 4061 ASSERT(!HasStackOverflow()); | 3900 ASSERT(!HasStackOverflow()); |
| 4062 ASSERT(current_block() != NULL); | 3901 ASSERT(current_block() != NULL); |
| 4063 ASSERT(current_block()->HasPredecessor()); | 3902 ASSERT(current_block()->HasPredecessor()); |
| 4064 } | 3903 } |
| 4065 | 3904 |
| 4066 | 3905 |
| 4067 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) { | 3906 void HGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
| 4068 ASSERT(!HasStackOverflow()); | 3907 ASSERT(!HasStackOverflow()); |
| 4069 ASSERT(current_block() != NULL); | 3908 ASSERT(current_block() != NULL); |
| 4070 ASSERT(current_block()->HasPredecessor()); | 3909 ASSERT(current_block()->HasPredecessor()); |
| 4071 if (stmt->condition()->ToBooleanIsTrue()) { | 3910 if (stmt->condition()->ToBooleanIsTrue()) { |
| 4072 AddSimulate(stmt->ThenId()); | 3911 AddSimulate(stmt->ThenId()); |
| 4073 Visit(stmt->then_statement()); | 3912 Visit(stmt->then_statement()); |
| 4074 } else if (stmt->condition()->ToBooleanIsFalse()) { | 3913 } else if (stmt->condition()->ToBooleanIsFalse()) { |
| 4075 AddSimulate(stmt->ElseId()); | 3914 AddSimulate(stmt->ElseId()); |
| 4076 Visit(stmt->else_statement()); | 3915 Visit(stmt->else_statement()); |
| 4077 } else { | 3916 } else { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4096 } else { | 3935 } else { |
| 4097 cond_false = NULL; | 3936 cond_false = NULL; |
| 4098 } | 3937 } |
| 4099 | 3938 |
| 4100 HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId()); | 3939 HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId()); |
| 4101 set_current_block(join); | 3940 set_current_block(join); |
| 4102 } | 3941 } |
| 4103 } | 3942 } |
| 4104 | 3943 |
| 4105 | 3944 |
| 4106 HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get( | 3945 HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get( |
| 4107 BreakableStatement* stmt, | 3946 BreakableStatement* stmt, |
| 4108 BreakType type, | 3947 BreakType type, |
| 4109 int* drop_extra) { | 3948 int* drop_extra) { |
| 4110 *drop_extra = 0; | 3949 *drop_extra = 0; |
| 4111 BreakAndContinueScope* current = this; | 3950 BreakAndContinueScope* current = this; |
| 4112 while (current != NULL && current->info()->target() != stmt) { | 3951 while (current != NULL && current->info()->target() != stmt) { |
| 4113 *drop_extra += current->info()->drop_extra(); | 3952 *drop_extra += current->info()->drop_extra(); |
| 4114 current = current->next(); | 3953 current = current->next(); |
| 4115 } | 3954 } |
| 4116 ASSERT(current != NULL); // Always found (unless stack is malformed). | 3955 ASSERT(current != NULL); // Always found (unless stack is malformed). |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4135 block = current->owner()->graph()->CreateBasicBlock(); | 3974 block = current->owner()->graph()->CreateBasicBlock(); |
| 4136 current->info()->set_continue_block(block); | 3975 current->info()->set_continue_block(block); |
| 4137 } | 3976 } |
| 4138 break; | 3977 break; |
| 4139 } | 3978 } |
| 4140 | 3979 |
| 4141 return block; | 3980 return block; |
| 4142 } | 3981 } |
| 4143 | 3982 |
| 4144 | 3983 |
| 4145 void HOptimizedGraphBuilder::VisitContinueStatement( | 3984 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
| 4146 ContinueStatement* stmt) { | |
| 4147 ASSERT(!HasStackOverflow()); | 3985 ASSERT(!HasStackOverflow()); |
| 4148 ASSERT(current_block() != NULL); | 3986 ASSERT(current_block() != NULL); |
| 4149 ASSERT(current_block()->HasPredecessor()); | 3987 ASSERT(current_block()->HasPredecessor()); |
| 4150 int drop_extra = 0; | 3988 int drop_extra = 0; |
| 4151 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), | 3989 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), |
| 4152 CONTINUE, | 3990 CONTINUE, |
| 4153 &drop_extra); | 3991 &drop_extra); |
| 4154 Drop(drop_extra); | 3992 Drop(drop_extra); |
| 4155 current_block()->Goto(continue_block); | 3993 current_block()->Goto(continue_block); |
| 4156 set_current_block(NULL); | 3994 set_current_block(NULL); |
| 4157 } | 3995 } |
| 4158 | 3996 |
| 4159 | 3997 |
| 4160 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 3998 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
| 4161 ASSERT(!HasStackOverflow()); | 3999 ASSERT(!HasStackOverflow()); |
| 4162 ASSERT(current_block() != NULL); | 4000 ASSERT(current_block() != NULL); |
| 4163 ASSERT(current_block()->HasPredecessor()); | 4001 ASSERT(current_block()->HasPredecessor()); |
| 4164 int drop_extra = 0; | 4002 int drop_extra = 0; |
| 4165 HBasicBlock* break_block = break_scope()->Get(stmt->target(), | 4003 HBasicBlock* break_block = break_scope()->Get(stmt->target(), |
| 4166 BREAK, | 4004 BREAK, |
| 4167 &drop_extra); | 4005 &drop_extra); |
| 4168 Drop(drop_extra); | 4006 Drop(drop_extra); |
| 4169 current_block()->Goto(break_block); | 4007 current_block()->Goto(break_block); |
| 4170 set_current_block(NULL); | 4008 set_current_block(NULL); |
| 4171 } | 4009 } |
| 4172 | 4010 |
| 4173 | 4011 |
| 4174 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 4012 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
| 4175 ASSERT(!HasStackOverflow()); | 4013 ASSERT(!HasStackOverflow()); |
| 4176 ASSERT(current_block() != NULL); | 4014 ASSERT(current_block() != NULL); |
| 4177 ASSERT(current_block()->HasPredecessor()); | 4015 ASSERT(current_block()->HasPredecessor()); |
| 4178 FunctionState* state = function_state(); | 4016 FunctionState* state = function_state(); |
| 4179 AstContext* context = call_context(); | 4017 AstContext* context = call_context(); |
| 4180 if (context == NULL) { | 4018 if (context == NULL) { |
| 4181 // Not an inlined return, so an actual one. | 4019 // Not an inlined return, so an actual one. |
| 4182 CHECK_ALIVE(VisitForValue(stmt->expression())); | 4020 CHECK_ALIVE(VisitForValue(stmt->expression())); |
| 4183 HValue* result = environment()->Pop(); | 4021 HValue* result = environment()->Pop(); |
| 4184 current_block()->FinishExit(new(zone()) HReturn(result)); | 4022 current_block()->FinishExit(new(zone()) HReturn(result)); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4236 } else { | 4074 } else { |
| 4237 ASSERT(context->IsValue()); | 4075 ASSERT(context->IsValue()); |
| 4238 CHECK_ALIVE(VisitForValue(stmt->expression())); | 4076 CHECK_ALIVE(VisitForValue(stmt->expression())); |
| 4239 current_block()->AddLeaveInlined(Pop(), state); | 4077 current_block()->AddLeaveInlined(Pop(), state); |
| 4240 } | 4078 } |
| 4241 } | 4079 } |
| 4242 set_current_block(NULL); | 4080 set_current_block(NULL); |
| 4243 } | 4081 } |
| 4244 | 4082 |
| 4245 | 4083 |
| 4246 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { | 4084 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { |
| 4247 ASSERT(!HasStackOverflow()); | 4085 ASSERT(!HasStackOverflow()); |
| 4248 ASSERT(current_block() != NULL); | 4086 ASSERT(current_block() != NULL); |
| 4249 ASSERT(current_block()->HasPredecessor()); | 4087 ASSERT(current_block()->HasPredecessor()); |
| 4250 return Bailout("WithStatement"); | 4088 return Bailout("WithStatement"); |
| 4251 } | 4089 } |
| 4252 | 4090 |
| 4253 | 4091 |
| 4254 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 4092 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
| 4255 ASSERT(!HasStackOverflow()); | 4093 ASSERT(!HasStackOverflow()); |
| 4256 ASSERT(current_block() != NULL); | 4094 ASSERT(current_block() != NULL); |
| 4257 ASSERT(current_block()->HasPredecessor()); | 4095 ASSERT(current_block()->HasPredecessor()); |
| 4258 // We only optimize switch statements with smi-literal smi comparisons, | 4096 // We only optimize switch statements with smi-literal smi comparisons, |
| 4259 // with a bounded number of clauses. | 4097 // with a bounded number of clauses. |
| 4260 const int kCaseClauseLimit = 128; | 4098 const int kCaseClauseLimit = 128; |
| 4261 ZoneList<CaseClause*>* clauses = stmt->cases(); | 4099 ZoneList<CaseClause*>* clauses = stmt->cases(); |
| 4262 int clause_count = clauses->length(); | 4100 int clause_count = clauses->length(); |
| 4263 if (clause_count > kCaseClauseLimit) { | 4101 if (clause_count > kCaseClauseLimit) { |
| 4264 return Bailout("SwitchStatement: too many clauses"); | 4102 return Bailout("SwitchStatement: too many clauses"); |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4430 stmt->ExitId())); | 4268 stmt->ExitId())); |
| 4431 } else { | 4269 } else { |
| 4432 if (fall_through_block != NULL) fall_through_block->Goto(break_block); | 4270 if (fall_through_block != NULL) fall_through_block->Goto(break_block); |
| 4433 if (last_block != NULL) last_block->Goto(break_block); | 4271 if (last_block != NULL) last_block->Goto(break_block); |
| 4434 break_block->SetJoinId(stmt->ExitId()); | 4272 break_block->SetJoinId(stmt->ExitId()); |
| 4435 set_current_block(break_block); | 4273 set_current_block(break_block); |
| 4436 } | 4274 } |
| 4437 } | 4275 } |
| 4438 | 4276 |
| 4439 | 4277 |
| 4440 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { | 4278 bool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { |
| 4441 return statement->OsrEntryId() == info()->osr_ast_id(); | 4279 return statement->OsrEntryId() == info()->osr_ast_id(); |
| 4442 } | 4280 } |
| 4443 | 4281 |
| 4444 | 4282 |
| 4445 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { | 4283 bool HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { |
| 4446 if (!HasOsrEntryAt(statement)) return false; | 4284 if (!HasOsrEntryAt(statement)) return false; |
| 4447 | 4285 |
| 4448 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); | 4286 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); |
| 4449 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); | 4287 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); |
| 4450 HValue* true_value = graph()->GetConstantTrue(); | 4288 HValue* true_value = graph()->GetConstantTrue(); |
| 4451 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); | 4289 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); |
| 4452 current_block()->Finish(test); | 4290 current_block()->Finish(test); |
| 4453 | 4291 |
| 4454 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); | 4292 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); |
| 4455 non_osr_entry->Goto(loop_predecessor); | 4293 non_osr_entry->Goto(loop_predecessor); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 4485 HContext* context = new(zone()) HContext; | 4323 HContext* context = new(zone()) HContext; |
| 4486 AddInstruction(context); | 4324 AddInstruction(context); |
| 4487 environment()->BindContext(context); | 4325 environment()->BindContext(context); |
| 4488 current_block()->Goto(loop_predecessor); | 4326 current_block()->Goto(loop_predecessor); |
| 4489 loop_predecessor->SetJoinId(statement->EntryId()); | 4327 loop_predecessor->SetJoinId(statement->EntryId()); |
| 4490 set_current_block(loop_predecessor); | 4328 set_current_block(loop_predecessor); |
| 4491 return true; | 4329 return true; |
| 4492 } | 4330 } |
| 4493 | 4331 |
| 4494 | 4332 |
| 4495 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 4333 void HGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
| 4496 HBasicBlock* loop_entry, | 4334 HBasicBlock* loop_entry, |
| 4497 BreakAndContinueInfo* break_info) { | 4335 BreakAndContinueInfo* break_info) { |
| 4498 BreakAndContinueScope push(break_info, this); | 4336 BreakAndContinueScope push(break_info, this); |
| 4499 AddSimulate(stmt->StackCheckId()); | 4337 AddSimulate(stmt->StackCheckId()); |
| 4500 HValue* context = environment()->LookupContext(); | 4338 HValue* context = environment()->LookupContext(); |
| 4501 HStackCheck* stack_check = | 4339 HStackCheck* stack_check = |
| 4502 new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch); | 4340 new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch); |
| 4503 AddInstruction(stack_check); | 4341 AddInstruction(stack_check); |
| 4504 ASSERT(loop_entry->IsLoopHeader()); | 4342 ASSERT(loop_entry->IsLoopHeader()); |
| 4505 loop_entry->loop_information()->set_stack_check(stack_check); | 4343 loop_entry->loop_information()->set_stack_check(stack_check); |
| 4506 CHECK_BAILOUT(Visit(stmt->body())); | 4344 CHECK_BAILOUT(Visit(stmt->body())); |
| 4507 } | 4345 } |
| 4508 | 4346 |
| 4509 | 4347 |
| 4510 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 4348 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 4511 ASSERT(!HasStackOverflow()); | 4349 ASSERT(!HasStackOverflow()); |
| 4512 ASSERT(current_block() != NULL); | 4350 ASSERT(current_block() != NULL); |
| 4513 ASSERT(current_block()->HasPredecessor()); | 4351 ASSERT(current_block()->HasPredecessor()); |
| 4514 ASSERT(current_block() != NULL); | 4352 ASSERT(current_block() != NULL); |
| 4515 bool osr_entry = PreProcessOsrEntry(stmt); | 4353 bool osr_entry = PreProcessOsrEntry(stmt); |
| 4516 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 4354 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
| 4517 current_block()->Goto(loop_entry); | 4355 current_block()->Goto(loop_entry); |
| 4518 set_current_block(loop_entry); | 4356 set_current_block(loop_entry); |
| 4519 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | 4357 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); |
| 4520 | 4358 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 4543 } | 4381 } |
| 4544 HBasicBlock* loop_exit = CreateLoop(stmt, | 4382 HBasicBlock* loop_exit = CreateLoop(stmt, |
| 4545 loop_entry, | 4383 loop_entry, |
| 4546 body_exit, | 4384 body_exit, |
| 4547 loop_successor, | 4385 loop_successor, |
| 4548 break_info.break_block()); | 4386 break_info.break_block()); |
| 4549 set_current_block(loop_exit); | 4387 set_current_block(loop_exit); |
| 4550 } | 4388 } |
| 4551 | 4389 |
| 4552 | 4390 |
| 4553 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 4391 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
| 4554 ASSERT(!HasStackOverflow()); | 4392 ASSERT(!HasStackOverflow()); |
| 4555 ASSERT(current_block() != NULL); | 4393 ASSERT(current_block() != NULL); |
| 4556 ASSERT(current_block()->HasPredecessor()); | 4394 ASSERT(current_block()->HasPredecessor()); |
| 4557 ASSERT(current_block() != NULL); | 4395 ASSERT(current_block() != NULL); |
| 4558 bool osr_entry = PreProcessOsrEntry(stmt); | 4396 bool osr_entry = PreProcessOsrEntry(stmt); |
| 4559 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 4397 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
| 4560 current_block()->Goto(loop_entry); | 4398 current_block()->Goto(loop_entry); |
| 4561 set_current_block(loop_entry); | 4399 set_current_block(loop_entry); |
| 4562 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | 4400 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); |
| 4563 | 4401 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 4587 JoinContinue(stmt, current_block(), break_info.continue_block()); | 4425 JoinContinue(stmt, current_block(), break_info.continue_block()); |
| 4588 HBasicBlock* loop_exit = CreateLoop(stmt, | 4426 HBasicBlock* loop_exit = CreateLoop(stmt, |
| 4589 loop_entry, | 4427 loop_entry, |
| 4590 body_exit, | 4428 body_exit, |
| 4591 loop_successor, | 4429 loop_successor, |
| 4592 break_info.break_block()); | 4430 break_info.break_block()); |
| 4593 set_current_block(loop_exit); | 4431 set_current_block(loop_exit); |
| 4594 } | 4432 } |
| 4595 | 4433 |
| 4596 | 4434 |
| 4597 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) { | 4435 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { |
| 4598 ASSERT(!HasStackOverflow()); | 4436 ASSERT(!HasStackOverflow()); |
| 4599 ASSERT(current_block() != NULL); | 4437 ASSERT(current_block() != NULL); |
| 4600 ASSERT(current_block()->HasPredecessor()); | 4438 ASSERT(current_block()->HasPredecessor()); |
| 4601 if (stmt->init() != NULL) { | 4439 if (stmt->init() != NULL) { |
| 4602 CHECK_ALIVE(Visit(stmt->init())); | 4440 CHECK_ALIVE(Visit(stmt->init())); |
| 4603 } | 4441 } |
| 4604 ASSERT(current_block() != NULL); | 4442 ASSERT(current_block() != NULL); |
| 4605 bool osr_entry = PreProcessOsrEntry(stmt); | 4443 bool osr_entry = PreProcessOsrEntry(stmt); |
| 4606 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 4444 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
| 4607 current_block()->Goto(loop_entry); | 4445 current_block()->Goto(loop_entry); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4639 | 4477 |
| 4640 HBasicBlock* loop_exit = CreateLoop(stmt, | 4478 HBasicBlock* loop_exit = CreateLoop(stmt, |
| 4641 loop_entry, | 4479 loop_entry, |
| 4642 body_exit, | 4480 body_exit, |
| 4643 loop_successor, | 4481 loop_successor, |
| 4644 break_info.break_block()); | 4482 break_info.break_block()); |
| 4645 set_current_block(loop_exit); | 4483 set_current_block(loop_exit); |
| 4646 } | 4484 } |
| 4647 | 4485 |
| 4648 | 4486 |
| 4649 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 4487 void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
| 4650 ASSERT(!HasStackOverflow()); | 4488 ASSERT(!HasStackOverflow()); |
| 4651 ASSERT(current_block() != NULL); | 4489 ASSERT(current_block() != NULL); |
| 4652 ASSERT(current_block()->HasPredecessor()); | 4490 ASSERT(current_block()->HasPredecessor()); |
| 4653 | 4491 |
| 4654 if (!FLAG_optimize_for_in) { | 4492 if (!FLAG_optimize_for_in) { |
| 4655 return Bailout("ForInStatement optimization is disabled"); | 4493 return Bailout("ForInStatement optimization is disabled"); |
| 4656 } | 4494 } |
| 4657 | 4495 |
| 4658 if (!oracle()->IsForInFastCase(stmt)) { | 4496 if (!oracle()->IsForInFastCase(stmt)) { |
| 4659 return Bailout("ForInStatement is not fast case"); | 4497 return Bailout("ForInStatement is not fast case"); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4760 HBasicBlock* loop_exit = CreateLoop(stmt, | 4598 HBasicBlock* loop_exit = CreateLoop(stmt, |
| 4761 loop_entry, | 4599 loop_entry, |
| 4762 body_exit, | 4600 body_exit, |
| 4763 loop_successor, | 4601 loop_successor, |
| 4764 break_info.break_block()); | 4602 break_info.break_block()); |
| 4765 | 4603 |
| 4766 set_current_block(loop_exit); | 4604 set_current_block(loop_exit); |
| 4767 } | 4605 } |
| 4768 | 4606 |
| 4769 | 4607 |
| 4770 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 4608 void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 4771 ASSERT(!HasStackOverflow()); | 4609 ASSERT(!HasStackOverflow()); |
| 4772 ASSERT(current_block() != NULL); | 4610 ASSERT(current_block() != NULL); |
| 4773 ASSERT(current_block()->HasPredecessor()); | 4611 ASSERT(current_block()->HasPredecessor()); |
| 4774 return Bailout("TryCatchStatement"); | 4612 return Bailout("TryCatchStatement"); |
| 4775 } | 4613 } |
| 4776 | 4614 |
| 4777 | 4615 |
| 4778 void HOptimizedGraphBuilder::VisitTryFinallyStatement( | 4616 void HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| 4779 TryFinallyStatement* stmt) { | |
| 4780 ASSERT(!HasStackOverflow()); | 4617 ASSERT(!HasStackOverflow()); |
| 4781 ASSERT(current_block() != NULL); | 4618 ASSERT(current_block() != NULL); |
| 4782 ASSERT(current_block()->HasPredecessor()); | 4619 ASSERT(current_block()->HasPredecessor()); |
| 4783 return Bailout("TryFinallyStatement"); | 4620 return Bailout("TryFinallyStatement"); |
| 4784 } | 4621 } |
| 4785 | 4622 |
| 4786 | 4623 |
| 4787 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 4624 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 4788 ASSERT(!HasStackOverflow()); | 4625 ASSERT(!HasStackOverflow()); |
| 4789 ASSERT(current_block() != NULL); | 4626 ASSERT(current_block() != NULL); |
| 4790 ASSERT(current_block()->HasPredecessor()); | 4627 ASSERT(current_block()->HasPredecessor()); |
| 4791 return Bailout("DebuggerStatement"); | 4628 return Bailout("DebuggerStatement"); |
| 4792 } | 4629 } |
| 4793 | 4630 |
| 4794 | 4631 |
| 4795 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( | 4632 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( |
| 4796 Code* unoptimized_code, FunctionLiteral* expr) { | 4633 Code* unoptimized_code, FunctionLiteral* expr) { |
| 4797 int start_position = expr->start_position(); | 4634 int start_position = expr->start_position(); |
| 4798 RelocIterator it(unoptimized_code); | 4635 RelocIterator it(unoptimized_code); |
| 4799 for (;!it.done(); it.next()) { | 4636 for (;!it.done(); it.next()) { |
| 4800 RelocInfo* rinfo = it.rinfo(); | 4637 RelocInfo* rinfo = it.rinfo(); |
| 4801 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; | 4638 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; |
| 4802 Object* obj = rinfo->target_object(); | 4639 Object* obj = rinfo->target_object(); |
| 4803 if (obj->IsSharedFunctionInfo()) { | 4640 if (obj->IsSharedFunctionInfo()) { |
| 4804 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 4641 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
| 4805 if (shared->start_position() == start_position) { | 4642 if (shared->start_position() == start_position) { |
| 4806 return Handle<SharedFunctionInfo>(shared); | 4643 return Handle<SharedFunctionInfo>(shared); |
| 4807 } | 4644 } |
| 4808 } | 4645 } |
| 4809 } | 4646 } |
| 4810 | 4647 |
| 4811 return Handle<SharedFunctionInfo>(); | 4648 return Handle<SharedFunctionInfo>(); |
| 4812 } | 4649 } |
| 4813 | 4650 |
| 4814 | 4651 |
| 4815 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 4652 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 4816 ASSERT(!HasStackOverflow()); | 4653 ASSERT(!HasStackOverflow()); |
| 4817 ASSERT(current_block() != NULL); | 4654 ASSERT(current_block() != NULL); |
| 4818 ASSERT(current_block()->HasPredecessor()); | 4655 ASSERT(current_block()->HasPredecessor()); |
| 4819 Handle<SharedFunctionInfo> shared_info = | 4656 Handle<SharedFunctionInfo> shared_info = |
| 4820 SearchSharedFunctionInfo(info()->shared_info()->code(), | 4657 SearchSharedFunctionInfo(info()->shared_info()->code(), |
| 4821 expr); | 4658 expr); |
| 4822 if (shared_info.is_null()) { | 4659 if (shared_info.is_null()) { |
| 4823 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); | 4660 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); |
| 4824 } | 4661 } |
| 4825 // We also have a stack overflow if the recursive compilation did. | 4662 // We also have a stack overflow if the recursive compilation did. |
| 4826 if (HasStackOverflow()) return; | 4663 if (HasStackOverflow()) return; |
| 4827 HValue* context = environment()->LookupContext(); | 4664 HValue* context = environment()->LookupContext(); |
| 4828 HFunctionLiteral* instr = | 4665 HFunctionLiteral* instr = |
| 4829 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); | 4666 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); |
| 4830 return ast_context()->ReturnInstruction(instr, expr->id()); | 4667 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4831 } | 4668 } |
| 4832 | 4669 |
| 4833 | 4670 |
| 4834 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( | 4671 void HGraphBuilder::VisitSharedFunctionInfoLiteral( |
| 4835 SharedFunctionInfoLiteral* expr) { | 4672 SharedFunctionInfoLiteral* expr) { |
| 4836 ASSERT(!HasStackOverflow()); | 4673 ASSERT(!HasStackOverflow()); |
| 4837 ASSERT(current_block() != NULL); | 4674 ASSERT(current_block() != NULL); |
| 4838 ASSERT(current_block()->HasPredecessor()); | 4675 ASSERT(current_block()->HasPredecessor()); |
| 4839 return Bailout("SharedFunctionInfoLiteral"); | 4676 return Bailout("SharedFunctionInfoLiteral"); |
| 4840 } | 4677 } |
| 4841 | 4678 |
| 4842 | 4679 |
| 4843 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) { | 4680 void HGraphBuilder::VisitConditional(Conditional* expr) { |
| 4844 ASSERT(!HasStackOverflow()); | 4681 ASSERT(!HasStackOverflow()); |
| 4845 ASSERT(current_block() != NULL); | 4682 ASSERT(current_block() != NULL); |
| 4846 ASSERT(current_block()->HasPredecessor()); | 4683 ASSERT(current_block()->HasPredecessor()); |
| 4847 HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 4684 HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
| 4848 HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 4685 HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
| 4849 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); | 4686 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); |
| 4850 | 4687 |
| 4851 // Visit the true and false subexpressions in the same AST context as the | 4688 // Visit the true and false subexpressions in the same AST context as the |
| 4852 // whole expression. | 4689 // whole expression. |
| 4853 if (cond_true->HasPredecessor()) { | 4690 if (cond_true->HasPredecessor()) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4871 if (!ast_context()->IsTest()) { | 4708 if (!ast_context()->IsTest()) { |
| 4872 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); | 4709 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); |
| 4873 set_current_block(join); | 4710 set_current_block(join); |
| 4874 if (join != NULL && !ast_context()->IsEffect()) { | 4711 if (join != NULL && !ast_context()->IsEffect()) { |
| 4875 return ast_context()->ReturnValue(Pop()); | 4712 return ast_context()->ReturnValue(Pop()); |
| 4876 } | 4713 } |
| 4877 } | 4714 } |
| 4878 } | 4715 } |
| 4879 | 4716 |
| 4880 | 4717 |
| 4881 HOptimizedGraphBuilder::GlobalPropertyAccess | 4718 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( |
| 4882 HOptimizedGraphBuilder::LookupGlobalProperty( | 4719 Variable* var, LookupResult* lookup, bool is_store) { |
| 4883 Variable* var, LookupResult* lookup, bool is_store) { | |
| 4884 if (var->is_this() || !info()->has_global_object()) { | 4720 if (var->is_this() || !info()->has_global_object()) { |
| 4885 return kUseGeneric; | 4721 return kUseGeneric; |
| 4886 } | 4722 } |
| 4887 Handle<GlobalObject> global(info()->global_object()); | 4723 Handle<GlobalObject> global(info()->global_object()); |
| 4888 global->Lookup(*var->name(), lookup); | 4724 global->Lookup(*var->name(), lookup); |
| 4889 if (!lookup->IsNormal() || | 4725 if (!lookup->IsNormal() || |
| 4890 (is_store && lookup->IsReadOnly()) || | 4726 (is_store && lookup->IsReadOnly()) || |
| 4891 lookup->holder() != *global) { | 4727 lookup->holder() != *global) { |
| 4892 return kUseGeneric; | 4728 return kUseGeneric; |
| 4893 } | 4729 } |
| 4894 | 4730 |
| 4895 return kUseCell; | 4731 return kUseCell; |
| 4896 } | 4732 } |
| 4897 | 4733 |
| 4898 | 4734 |
| 4899 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 4735 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { |
| 4900 ASSERT(var->IsContextSlot()); | 4736 ASSERT(var->IsContextSlot()); |
| 4901 HValue* context = environment()->LookupContext(); | 4737 HValue* context = environment()->LookupContext(); |
| 4902 int length = info()->scope()->ContextChainLength(var->scope()); | 4738 int length = info()->scope()->ContextChainLength(var->scope()); |
| 4903 while (length-- > 0) { | 4739 while (length-- > 0) { |
| 4904 HInstruction* context_instruction = new(zone()) HOuterContext(context); | 4740 HInstruction* context_instruction = new(zone()) HOuterContext(context); |
| 4905 AddInstruction(context_instruction); | 4741 AddInstruction(context_instruction); |
| 4906 context = context_instruction; | 4742 context = context_instruction; |
| 4907 } | 4743 } |
| 4908 return context; | 4744 return context; |
| 4909 } | 4745 } |
| 4910 | 4746 |
| 4911 | 4747 |
| 4912 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 4748 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 4913 ASSERT(!HasStackOverflow()); | 4749 ASSERT(!HasStackOverflow()); |
| 4914 ASSERT(current_block() != NULL); | 4750 ASSERT(current_block() != NULL); |
| 4915 ASSERT(current_block()->HasPredecessor()); | 4751 ASSERT(current_block()->HasPredecessor()); |
| 4916 Variable* variable = expr->var(); | 4752 Variable* variable = expr->var(); |
| 4917 switch (variable->location()) { | 4753 switch (variable->location()) { |
| 4918 case Variable::UNALLOCATED: { | 4754 case Variable::UNALLOCATED: { |
| 4919 if (IsLexicalVariableMode(variable->mode())) { | 4755 if (IsLexicalVariableMode(variable->mode())) { |
| 4920 // TODO(rossberg): should this be an ASSERT? | 4756 // TODO(rossberg): should this be an ASSERT? |
| 4921 return Bailout("reference to global lexical variable"); | 4757 return Bailout("reference to global lexical variable"); |
| 4922 } | 4758 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4975 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable); | 4811 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable); |
| 4976 return ast_context()->ReturnInstruction(instr, expr->id()); | 4812 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4977 } | 4813 } |
| 4978 | 4814 |
| 4979 case Variable::LOOKUP: | 4815 case Variable::LOOKUP: |
| 4980 return Bailout("reference to a variable which requires dynamic lookup"); | 4816 return Bailout("reference to a variable which requires dynamic lookup"); |
| 4981 } | 4817 } |
| 4982 } | 4818 } |
| 4983 | 4819 |
| 4984 | 4820 |
| 4985 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { | 4821 void HGraphBuilder::VisitLiteral(Literal* expr) { |
| 4986 ASSERT(!HasStackOverflow()); | 4822 ASSERT(!HasStackOverflow()); |
| 4987 ASSERT(current_block() != NULL); | 4823 ASSERT(current_block() != NULL); |
| 4988 ASSERT(current_block()->HasPredecessor()); | 4824 ASSERT(current_block()->HasPredecessor()); |
| 4989 HConstant* instr = | 4825 HConstant* instr = |
| 4990 new(zone()) HConstant(expr->handle(), Representation::None()); | 4826 new(zone()) HConstant(expr->handle(), Representation::None()); |
| 4991 return ast_context()->ReturnInstruction(instr, expr->id()); | 4827 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4992 } | 4828 } |
| 4993 | 4829 |
| 4994 | 4830 |
| 4995 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 4831 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* 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 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4835 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 5000 Handle<FixedArray> literals(closure->literals()); | 4836 Handle<FixedArray> literals(closure->literals()); |
| 5001 HValue* context = environment()->LookupContext(); | 4837 HValue* context = environment()->LookupContext(); |
| 5002 | 4838 |
| 5003 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, | 4839 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, |
| 5004 literals, | 4840 literals, |
| 5005 expr->pattern(), | 4841 expr->pattern(), |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5144 } | 4980 } |
| 5145 } | 4981 } |
| 5146 } | 4982 } |
| 5147 } | 4983 } |
| 5148 | 4984 |
| 5149 *total_size += boilerplate->map()->instance_size(); | 4985 *total_size += boilerplate->map()->instance_size(); |
| 5150 return true; | 4986 return true; |
| 5151 } | 4987 } |
| 5152 | 4988 |
| 5153 | 4989 |
| 5154 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 4990 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| 5155 ASSERT(!HasStackOverflow()); | 4991 ASSERT(!HasStackOverflow()); |
| 5156 ASSERT(current_block() != NULL); | 4992 ASSERT(current_block() != NULL); |
| 5157 ASSERT(current_block()->HasPredecessor()); | 4993 ASSERT(current_block()->HasPredecessor()); |
| 5158 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4994 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 5159 HValue* context = environment()->LookupContext(); | 4995 HValue* context = environment()->LookupContext(); |
| 5160 HInstruction* literal; | 4996 HInstruction* literal; |
| 5161 | 4997 |
| 5162 // Check whether to use fast or slow deep-copying for boilerplate. | 4998 // Check whether to use fast or slow deep-copying for boilerplate. |
| 5163 int total_size = 0; | 4999 int total_size = 0; |
| 5164 int max_properties = HFastLiteral::kMaxLiteralProperties; | 5000 int max_properties = HFastLiteral::kMaxLiteralProperties; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5249 // (e.g. because of code motion). | 5085 // (e.g. because of code motion). |
| 5250 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); | 5086 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); |
| 5251 AddInstruction(result); | 5087 AddInstruction(result); |
| 5252 return ast_context()->ReturnValue(result); | 5088 return ast_context()->ReturnValue(result); |
| 5253 } else { | 5089 } else { |
| 5254 return ast_context()->ReturnValue(Pop()); | 5090 return ast_context()->ReturnValue(Pop()); |
| 5255 } | 5091 } |
| 5256 } | 5092 } |
| 5257 | 5093 |
| 5258 | 5094 |
| 5259 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 5095 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| 5260 ASSERT(!HasStackOverflow()); | 5096 ASSERT(!HasStackOverflow()); |
| 5261 ASSERT(current_block() != NULL); | 5097 ASSERT(current_block() != NULL); |
| 5262 ASSERT(current_block()->HasPredecessor()); | 5098 ASSERT(current_block()->HasPredecessor()); |
| 5263 ZoneList<Expression*>* subexprs = expr->values(); | 5099 ZoneList<Expression*>* subexprs = expr->values(); |
| 5264 int length = subexprs->length(); | 5100 int length = subexprs->length(); |
| 5265 HValue* context = environment()->LookupContext(); | 5101 HValue* context = environment()->LookupContext(); |
| 5266 HInstruction* literal; | 5102 HInstruction* literal; |
| 5267 | 5103 |
| 5268 Handle<FixedArray> literals(environment()->closure()->literals()); | 5104 Handle<FixedArray> literals(environment()->closure()->literals()); |
| 5269 Handle<Object> raw_boilerplate(literals->get(expr->literal_index())); | 5105 Handle<Object> raw_boilerplate(literals->get(expr->literal_index())); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5383 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); | 5219 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); |
| 5384 if (lookup->IsField()) { | 5220 if (lookup->IsField()) { |
| 5385 return lookup->GetLocalFieldIndexFromMap(*type); | 5221 return lookup->GetLocalFieldIndexFromMap(*type); |
| 5386 } else { | 5222 } else { |
| 5387 Map* transition = lookup->GetTransitionMapFromMap(*type); | 5223 Map* transition = lookup->GetTransitionMapFromMap(*type); |
| 5388 return transition->PropertyIndexFor(*name) - type->inobject_properties(); | 5224 return transition->PropertyIndexFor(*name) - type->inobject_properties(); |
| 5389 } | 5225 } |
| 5390 } | 5226 } |
| 5391 | 5227 |
| 5392 | 5228 |
| 5393 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, | 5229 void HGraphBuilder::AddCheckMapsWithTransitions(HValue* object, |
| 5394 Handle<Map> map) { | 5230 Handle<Map> map) { |
| 5395 AddInstruction(new(zone()) HCheckNonSmi(object)); | 5231 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 5396 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); | 5232 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
| 5397 } | 5233 } |
| 5398 | 5234 |
| 5399 | 5235 |
| 5400 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( | 5236 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, |
| 5401 HValue* object, | 5237 Handle<String> name, |
| 5402 Handle<String> name, | 5238 HValue* value, |
| 5403 HValue* value, | 5239 Handle<Map> map, |
| 5404 Handle<Map> map, | 5240 LookupResult* lookup) { |
| 5405 LookupResult* lookup) { | |
| 5406 ASSERT(lookup->IsFound()); | 5241 ASSERT(lookup->IsFound()); |
| 5407 // If the property does not exist yet, we have to check that it wasn't made | 5242 // If the property does not exist yet, we have to check that it wasn't made |
| 5408 // readonly or turned into a setter by some meanwhile modifications on the | 5243 // readonly or turned into a setter by some meanwhile modifications on the |
| 5409 // prototype chain. | 5244 // prototype chain. |
| 5410 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { | 5245 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { |
| 5411 Object* proto = map->prototype(); | 5246 Object* proto = map->prototype(); |
| 5412 // First check that the prototype chain isn't affected already. | 5247 // First check that the prototype chain isn't affected already. |
| 5413 LookupResult proto_result(isolate()); | 5248 LookupResult proto_result(isolate()); |
| 5414 proto->Lookup(*name, &proto_result); | 5249 proto->Lookup(*name, &proto_result); |
| 5415 if (proto_result.IsProperty()) { | 5250 if (proto_result.IsProperty()) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5447 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 5282 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
| 5448 instr->set_transition(transition); | 5283 instr->set_transition(transition); |
| 5449 // TODO(fschneider): Record the new map type of the object in the IR to | 5284 // TODO(fschneider): Record the new map type of the object in the IR to |
| 5450 // enable elimination of redundant checks after the transition store. | 5285 // enable elimination of redundant checks after the transition store. |
| 5451 instr->SetGVNFlag(kChangesMaps); | 5286 instr->SetGVNFlag(kChangesMaps); |
| 5452 } | 5287 } |
| 5453 return instr; | 5288 return instr; |
| 5454 } | 5289 } |
| 5455 | 5290 |
| 5456 | 5291 |
| 5457 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( | 5292 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, |
| 5458 HValue* object, | 5293 Handle<String> name, |
| 5459 Handle<String> name, | 5294 HValue* value) { |
| 5460 HValue* value) { | |
| 5461 HValue* context = environment()->LookupContext(); | 5295 HValue* context = environment()->LookupContext(); |
| 5462 return new(zone()) HStoreNamedGeneric( | 5296 return new(zone()) HStoreNamedGeneric( |
| 5463 context, | 5297 context, |
| 5464 object, | 5298 object, |
| 5465 name, | 5299 name, |
| 5466 value, | 5300 value, |
| 5467 function_strict_mode_flag()); | 5301 function_strict_mode_flag()); |
| 5468 } | 5302 } |
| 5469 | 5303 |
| 5470 | 5304 |
| 5471 HInstruction* HOptimizedGraphBuilder::BuildCallSetter( | 5305 HInstruction* HGraphBuilder::BuildCallSetter(HValue* object, |
| 5472 HValue* object, | 5306 HValue* value, |
| 5473 HValue* value, | 5307 Handle<Map> map, |
| 5474 Handle<Map> map, | 5308 Handle<JSFunction> setter, |
| 5475 Handle<JSFunction> setter, | 5309 Handle<JSObject> holder) { |
| 5476 Handle<JSObject> holder) { | |
| 5477 AddCheckConstantFunction(holder, object, map); | 5310 AddCheckConstantFunction(holder, object, map); |
| 5478 AddInstruction(new(zone()) HPushArgument(object)); | 5311 AddInstruction(new(zone()) HPushArgument(object)); |
| 5479 AddInstruction(new(zone()) HPushArgument(value)); | 5312 AddInstruction(new(zone()) HPushArgument(value)); |
| 5480 return new(zone()) HCallConstantFunction(setter, 2); | 5313 return new(zone()) HCallConstantFunction(setter, 2); |
| 5481 } | 5314 } |
| 5482 | 5315 |
| 5483 | 5316 |
| 5484 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( | 5317 HInstruction* HGraphBuilder::BuildStoreNamedMonomorphic(HValue* object, |
| 5485 HValue* object, | 5318 Handle<String> name, |
| 5486 Handle<String> name, | 5319 HValue* value, |
| 5487 HValue* value, | 5320 Handle<Map> map) { |
| 5488 Handle<Map> map) { | |
| 5489 // Handle a store to a known field. | 5321 // Handle a store to a known field. |
| 5490 LookupResult lookup(isolate()); | 5322 LookupResult lookup(isolate()); |
| 5491 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 5323 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| 5492 AddCheckMapsWithTransitions(object, map); | 5324 AddCheckMapsWithTransitions(object, map); |
| 5493 return BuildStoreNamedField(object, name, value, map, &lookup); | 5325 return BuildStoreNamedField(object, name, value, map, &lookup); |
| 5494 } | 5326 } |
| 5495 | 5327 |
| 5496 // No luck, do a generic store. | 5328 // No luck, do a generic store. |
| 5497 return BuildStoreNamedGeneric(object, name, value); | 5329 return BuildStoreNamedGeneric(object, name, value); |
| 5498 } | 5330 } |
| 5499 | 5331 |
| 5500 | 5332 |
| 5501 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 5333 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
| 5502 Property* expr, | 5334 HValue* object, |
| 5503 HValue* object, | 5335 SmallMapList* types, |
| 5504 SmallMapList* types, | 5336 Handle<String> name) { |
| 5505 Handle<String> name) { | |
| 5506 int count = 0; | 5337 int count = 0; |
| 5507 int previous_field_offset = 0; | 5338 int previous_field_offset = 0; |
| 5508 bool previous_field_is_in_object = false; | 5339 bool previous_field_is_in_object = false; |
| 5509 bool is_monomorphic_field = true; | 5340 bool is_monomorphic_field = true; |
| 5510 Handle<Map> map; | 5341 Handle<Map> map; |
| 5511 LookupResult lookup(isolate()); | 5342 LookupResult lookup(isolate()); |
| 5512 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 5343 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
| 5513 map = types->at(i); | 5344 map = types->at(i); |
| 5514 if (ComputeLoadStoreField(map, name, &lookup, false)) { | 5345 if (ComputeLoadStoreField(map, name, &lookup, false)) { |
| 5515 int index = ComputeLoadStoreFieldIndex(map, name, &lookup); | 5346 int index = ComputeLoadStoreFieldIndex(map, name, &lookup); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5547 types, | 5378 types, |
| 5548 name, | 5379 name, |
| 5549 zone()); | 5380 zone()); |
| 5550 } | 5381 } |
| 5551 | 5382 |
| 5552 instr->set_position(expr->position()); | 5383 instr->set_position(expr->position()); |
| 5553 return ast_context()->ReturnInstruction(instr, expr->id()); | 5384 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5554 } | 5385 } |
| 5555 | 5386 |
| 5556 | 5387 |
| 5557 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 5388 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, |
| 5558 Assignment* expr, | 5389 HValue* object, |
| 5559 HValue* object, | 5390 HValue* value, |
| 5560 HValue* value, | 5391 SmallMapList* types, |
| 5561 SmallMapList* types, | 5392 Handle<String> name) { |
| 5562 Handle<String> name) { | |
| 5563 // TODO(ager): We should recognize when the prototype chains for different | 5393 // TODO(ager): We should recognize when the prototype chains for different |
| 5564 // maps are identical. In that case we can avoid repeatedly generating the | 5394 // maps are identical. In that case we can avoid repeatedly generating the |
| 5565 // same prototype map checks. | 5395 // same prototype map checks. |
| 5566 int count = 0; | 5396 int count = 0; |
| 5567 HBasicBlock* join = NULL; | 5397 HBasicBlock* join = NULL; |
| 5568 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 5398 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
| 5569 Handle<Map> map = types->at(i); | 5399 Handle<Map> map = types->at(i); |
| 5570 LookupResult lookup(isolate()); | 5400 LookupResult lookup(isolate()); |
| 5571 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 5401 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| 5572 if (count == 0) { | 5402 if (count == 0) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5624 } | 5454 } |
| 5625 } | 5455 } |
| 5626 | 5456 |
| 5627 ASSERT(join != NULL); | 5457 ASSERT(join != NULL); |
| 5628 join->SetJoinId(expr->id()); | 5458 join->SetJoinId(expr->id()); |
| 5629 set_current_block(join); | 5459 set_current_block(join); |
| 5630 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 5460 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
| 5631 } | 5461 } |
| 5632 | 5462 |
| 5633 | 5463 |
| 5634 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 5464 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 5635 Property* prop = expr->target()->AsProperty(); | 5465 Property* prop = expr->target()->AsProperty(); |
| 5636 ASSERT(prop != NULL); | 5466 ASSERT(prop != NULL); |
| 5637 expr->RecordTypeFeedback(oracle(), zone()); | 5467 expr->RecordTypeFeedback(oracle(), zone()); |
| 5638 CHECK_ALIVE(VisitForValue(prop->obj())); | 5468 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 5639 | 5469 |
| 5640 if (prop->key()->IsPropertyName()) { | 5470 if (prop->key()->IsPropertyName()) { |
| 5641 // Named store. | 5471 // Named store. |
| 5642 CHECK_ALIVE(VisitForValue(expr->value())); | 5472 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5643 HValue* value = environment()->ExpressionStackAt(0); | 5473 HValue* value = environment()->ExpressionStackAt(0); |
| 5644 HValue* object = environment()->ExpressionStackAt(1); | 5474 HValue* object = environment()->ExpressionStackAt(1); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5707 ASSERT(has_side_effects); // Stores always have side effects. | 5537 ASSERT(has_side_effects); // Stores always have side effects. |
| 5708 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5538 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 5709 return ast_context()->ReturnValue(Pop()); | 5539 return ast_context()->ReturnValue(Pop()); |
| 5710 } | 5540 } |
| 5711 } | 5541 } |
| 5712 | 5542 |
| 5713 | 5543 |
| 5714 // Because not every expression has a position and there is not common | 5544 // Because not every expression has a position and there is not common |
| 5715 // superclass of Assignment and CountOperation, we cannot just pass the | 5545 // superclass of Assignment and CountOperation, we cannot just pass the |
| 5716 // owning expression instead of position and ast_id separately. | 5546 // owning expression instead of position and ast_id separately. |
| 5717 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 5547 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
| 5718 Variable* var, | 5548 HValue* value, |
| 5719 HValue* value, | 5549 int position, |
| 5720 int position, | 5550 BailoutId ast_id) { |
| 5721 BailoutId ast_id) { | |
| 5722 LookupResult lookup(isolate()); | 5551 LookupResult lookup(isolate()); |
| 5723 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 5552 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| 5724 if (type == kUseCell) { | 5553 if (type == kUseCell) { |
| 5725 Handle<GlobalObject> global(info()->global_object()); | 5554 Handle<GlobalObject> global(info()->global_object()); |
| 5726 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 5555 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 5727 HInstruction* instr = | 5556 HInstruction* instr = |
| 5728 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); | 5557 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); |
| 5729 instr->set_position(position); | 5558 instr->set_position(position); |
| 5730 AddInstruction(instr); | 5559 AddInstruction(instr); |
| 5731 if (instr->HasObservableSideEffects()) { | 5560 if (instr->HasObservableSideEffects()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5742 value, | 5571 value, |
| 5743 function_strict_mode_flag()); | 5572 function_strict_mode_flag()); |
| 5744 instr->set_position(position); | 5573 instr->set_position(position); |
| 5745 AddInstruction(instr); | 5574 AddInstruction(instr); |
| 5746 ASSERT(instr->HasObservableSideEffects()); | 5575 ASSERT(instr->HasObservableSideEffects()); |
| 5747 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 5576 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 5748 } | 5577 } |
| 5749 } | 5578 } |
| 5750 | 5579 |
| 5751 | 5580 |
| 5752 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5581 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 5753 Expression* target = expr->target(); | 5582 Expression* target = expr->target(); |
| 5754 VariableProxy* proxy = target->AsVariableProxy(); | 5583 VariableProxy* proxy = target->AsVariableProxy(); |
| 5755 Property* prop = target->AsProperty(); | 5584 Property* prop = target->AsProperty(); |
| 5756 ASSERT(proxy == NULL || prop == NULL); | 5585 ASSERT(proxy == NULL || prop == NULL); |
| 5757 | 5586 |
| 5758 // We have a second position recorded in the FullCodeGenerator to have | 5587 // We have a second position recorded in the FullCodeGenerator to have |
| 5759 // type feedback for the binary operation. | 5588 // type feedback for the binary operation. |
| 5760 BinaryOperation* operation = expr->binary_operation(); | 5589 BinaryOperation* operation = expr->binary_operation(); |
| 5761 | 5590 |
| 5762 if (proxy != NULL) { | 5591 if (proxy != NULL) { |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5939 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5768 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 5940 return ast_context()->ReturnValue(Pop()); | 5769 return ast_context()->ReturnValue(Pop()); |
| 5941 } | 5770 } |
| 5942 | 5771 |
| 5943 } else { | 5772 } else { |
| 5944 return Bailout("invalid lhs in compound assignment"); | 5773 return Bailout("invalid lhs in compound assignment"); |
| 5945 } | 5774 } |
| 5946 } | 5775 } |
| 5947 | 5776 |
| 5948 | 5777 |
| 5949 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { | 5778 void HGraphBuilder::VisitAssignment(Assignment* expr) { |
| 5950 ASSERT(!HasStackOverflow()); | 5779 ASSERT(!HasStackOverflow()); |
| 5951 ASSERT(current_block() != NULL); | 5780 ASSERT(current_block() != NULL); |
| 5952 ASSERT(current_block()->HasPredecessor()); | 5781 ASSERT(current_block()->HasPredecessor()); |
| 5953 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 5782 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
| 5954 Property* prop = expr->target()->AsProperty(); | 5783 Property* prop = expr->target()->AsProperty(); |
| 5955 ASSERT(proxy == NULL || prop == NULL); | 5784 ASSERT(proxy == NULL || prop == NULL); |
| 5956 | 5785 |
| 5957 if (expr->is_compound()) { | 5786 if (expr->is_compound()) { |
| 5958 HandleCompoundAssignment(expr); | 5787 HandleCompoundAssignment(expr); |
| 5959 return; | 5788 return; |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6066 | 5895 |
| 6067 case Variable::LOOKUP: | 5896 case Variable::LOOKUP: |
| 6068 return Bailout("assignment to LOOKUP variable"); | 5897 return Bailout("assignment to LOOKUP variable"); |
| 6069 } | 5898 } |
| 6070 } else { | 5899 } else { |
| 6071 return Bailout("invalid left-hand side in assignment"); | 5900 return Bailout("invalid left-hand side in assignment"); |
| 6072 } | 5901 } |
| 6073 } | 5902 } |
| 6074 | 5903 |
| 6075 | 5904 |
| 6076 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) { | 5905 void HGraphBuilder::VisitThrow(Throw* expr) { |
| 6077 ASSERT(!HasStackOverflow()); | 5906 ASSERT(!HasStackOverflow()); |
| 6078 ASSERT(current_block() != NULL); | 5907 ASSERT(current_block() != NULL); |
| 6079 ASSERT(current_block()->HasPredecessor()); | 5908 ASSERT(current_block()->HasPredecessor()); |
| 6080 // We don't optimize functions with invalid left-hand sides in | 5909 // We don't optimize functions with invalid left-hand sides in |
| 6081 // assignments, count operations, or for-in. Consequently throw can | 5910 // assignments, count operations, or for-in. Consequently throw can |
| 6082 // currently only occur in an effect context. | 5911 // currently only occur in an effect context. |
| 6083 ASSERT(ast_context()->IsEffect()); | 5912 ASSERT(ast_context()->IsEffect()); |
| 6084 CHECK_ALIVE(VisitForValue(expr->exception())); | 5913 CHECK_ALIVE(VisitForValue(expr->exception())); |
| 6085 | 5914 |
| 6086 HValue* context = environment()->LookupContext(); | 5915 HValue* context = environment()->LookupContext(); |
| 6087 HValue* value = environment()->Pop(); | 5916 HValue* value = environment()->Pop(); |
| 6088 HThrow* instr = new(zone()) HThrow(context, value); | 5917 HThrow* instr = new(zone()) HThrow(context, value); |
| 6089 instr->set_position(expr->position()); | 5918 instr->set_position(expr->position()); |
| 6090 AddInstruction(instr); | 5919 AddInstruction(instr); |
| 6091 AddSimulate(expr->id()); | 5920 AddSimulate(expr->id()); |
| 6092 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5921 current_block()->FinishExit(new(zone()) HAbnormalExit); |
| 6093 set_current_block(NULL); | 5922 set_current_block(NULL); |
| 6094 } | 5923 } |
| 6095 | 5924 |
| 6096 | 5925 |
| 6097 HLoadNamedField* HOptimizedGraphBuilder::BuildLoadNamedField( | 5926 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
| 6098 HValue* object, | 5927 Handle<Map> map, |
| 6099 Handle<Map> map, | 5928 LookupResult* lookup) { |
| 6100 LookupResult* lookup) { | |
| 6101 int index = lookup->GetLocalFieldIndexFromMap(*map); | 5929 int index = lookup->GetLocalFieldIndexFromMap(*map); |
| 6102 if (index < 0) { | 5930 if (index < 0) { |
| 6103 // Negative property indices are in-object properties, indexed | 5931 // Negative property indices are in-object properties, indexed |
| 6104 // from the end of the fixed part of the object. | 5932 // from the end of the fixed part of the object. |
| 6105 int offset = (index * kPointerSize) + map->instance_size(); | 5933 int offset = (index * kPointerSize) + map->instance_size(); |
| 6106 return new(zone()) HLoadNamedField(object, true, offset); | 5934 return new(zone()) HLoadNamedField(object, true, offset); |
| 6107 } else { | 5935 } else { |
| 6108 // Non-negative property indices are in the properties array. | 5936 // Non-negative property indices are in the properties array. |
| 6109 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | 5937 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; |
| 6110 return new(zone()) HLoadNamedField(object, false, offset); | 5938 return new(zone()) HLoadNamedField(object, false, offset); |
| 6111 } | 5939 } |
| 6112 } | 5940 } |
| 6113 | 5941 |
| 6114 | 5942 |
| 6115 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 5943 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* object, |
| 6116 HValue* object, | 5944 Handle<String> name, |
| 6117 Handle<String> name, | 5945 Property* expr) { |
| 6118 Property* expr) { | |
| 6119 if (expr->IsUninitialized() && !FLAG_always_opt) { | 5946 if (expr->IsUninitialized() && !FLAG_always_opt) { |
| 6120 AddInstruction(new(zone()) HSoftDeoptimize); | 5947 AddInstruction(new(zone()) HSoftDeoptimize); |
| 6121 current_block()->MarkAsDeoptimizing(); | 5948 current_block()->MarkAsDeoptimizing(); |
| 6122 } | 5949 } |
| 6123 HValue* context = environment()->LookupContext(); | 5950 HValue* context = environment()->LookupContext(); |
| 6124 return new(zone()) HLoadNamedGeneric(context, object, name); | 5951 return new(zone()) HLoadNamedGeneric(context, object, name); |
| 6125 } | 5952 } |
| 6126 | 5953 |
| 6127 | 5954 |
| 6128 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | 5955 HInstruction* HGraphBuilder::BuildCallGetter(HValue* object, |
| 6129 HValue* object, | 5956 Handle<Map> map, |
| 6130 Handle<Map> map, | 5957 Handle<JSFunction> getter, |
| 6131 Handle<JSFunction> getter, | 5958 Handle<JSObject> holder) { |
| 6132 Handle<JSObject> holder) { | |
| 6133 AddCheckConstantFunction(holder, object, map); | 5959 AddCheckConstantFunction(holder, object, map); |
| 6134 AddInstruction(new(zone()) HPushArgument(object)); | 5960 AddInstruction(new(zone()) HPushArgument(object)); |
| 6135 return new(zone()) HCallConstantFunction(getter, 1); | 5961 return new(zone()) HCallConstantFunction(getter, 1); |
| 6136 } | 5962 } |
| 6137 | 5963 |
| 6138 | 5964 |
| 6139 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( | 5965 HInstruction* HGraphBuilder::BuildLoadNamedMonomorphic(HValue* object, |
| 6140 HValue* object, | 5966 Handle<String> name, |
| 6141 Handle<String> name, | 5967 Property* expr, |
| 6142 Property* expr, | 5968 Handle<Map> map) { |
| 6143 Handle<Map> map) { | |
| 6144 // Handle a load from a known field. | 5969 // Handle a load from a known field. |
| 6145 ASSERT(!map->is_dictionary_map()); | 5970 ASSERT(!map->is_dictionary_map()); |
| 6146 LookupResult lookup(isolate()); | 5971 LookupResult lookup(isolate()); |
| 6147 map->LookupDescriptor(NULL, *name, &lookup); | 5972 map->LookupDescriptor(NULL, *name, &lookup); |
| 6148 if (lookup.IsField()) { | 5973 if (lookup.IsField()) { |
| 6149 AddCheckMapsWithTransitions(object, map); | 5974 AddCheckMapsWithTransitions(object, map); |
| 6150 return BuildLoadNamedField(object, map, &lookup); | 5975 return BuildLoadNamedField(object, map, &lookup); |
| 6151 } | 5976 } |
| 6152 | 5977 |
| 6153 // Handle a load of a constant known function. | 5978 // Handle a load of a constant known function. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 6167 HInstruction* holder_value = | 5992 HInstruction* holder_value = |
| 6168 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder)); | 5993 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder)); |
| 6169 return BuildLoadNamedField(holder_value, holder_map, &lookup); | 5994 return BuildLoadNamedField(holder_value, holder_map, &lookup); |
| 6170 } | 5995 } |
| 6171 | 5996 |
| 6172 // No luck, do a generic load. | 5997 // No luck, do a generic load. |
| 6173 return BuildLoadNamedGeneric(object, name, expr); | 5998 return BuildLoadNamedGeneric(object, name, expr); |
| 6174 } | 5999 } |
| 6175 | 6000 |
| 6176 | 6001 |
| 6177 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 6002 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
| 6178 HValue* key) { | 6003 HValue* key) { |
| 6179 HValue* context = environment()->LookupContext(); | 6004 HValue* context = environment()->LookupContext(); |
| 6180 return new(zone()) HLoadKeyedGeneric(context, object, key); | 6005 return new(zone()) HLoadKeyedGeneric(context, object, key); |
| 6181 } | 6006 } |
| 6182 | 6007 |
| 6183 | 6008 |
| 6184 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( | 6009 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( |
| 6185 HValue* object, | 6010 HValue* external_elements, |
| 6186 HValue* key, | 6011 HValue* checked_key, |
| 6187 HValue* val, | 6012 HValue* val, |
| 6188 HValue* dependency, | 6013 HValue* dependency, |
| 6189 Handle<Map> map, | 6014 ElementsKind elements_kind, |
| 6190 bool is_store) { | 6015 bool is_store) { |
| 6016 if (is_store) { |
| 6017 ASSERT(val != NULL); |
| 6018 switch (elements_kind) { |
| 6019 case EXTERNAL_PIXEL_ELEMENTS: { |
| 6020 val = AddInstruction(new(zone()) HClampToUint8(val)); |
| 6021 break; |
| 6022 } |
| 6023 case EXTERNAL_BYTE_ELEMENTS: |
| 6024 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 6025 case EXTERNAL_SHORT_ELEMENTS: |
| 6026 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 6027 case EXTERNAL_INT_ELEMENTS: |
| 6028 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
| 6029 break; |
| 6030 } |
| 6031 case EXTERNAL_FLOAT_ELEMENTS: |
| 6032 case EXTERNAL_DOUBLE_ELEMENTS: |
| 6033 break; |
| 6034 case FAST_SMI_ELEMENTS: |
| 6035 case FAST_ELEMENTS: |
| 6036 case FAST_DOUBLE_ELEMENTS: |
| 6037 case FAST_HOLEY_SMI_ELEMENTS: |
| 6038 case FAST_HOLEY_ELEMENTS: |
| 6039 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 6040 case DICTIONARY_ELEMENTS: |
| 6041 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 6042 UNREACHABLE(); |
| 6043 break; |
| 6044 } |
| 6045 return new(zone()) HStoreKeyed(external_elements, |
| 6046 checked_key, |
| 6047 val, |
| 6048 elements_kind); |
| 6049 } else { |
| 6050 ASSERT(val == NULL); |
| 6051 HLoadKeyed* load = |
| 6052 new(zone()) HLoadKeyed( |
| 6053 external_elements, checked_key, dependency, elements_kind); |
| 6054 if (FLAG_opt_safe_uint32_operations && |
| 6055 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
| 6056 graph()->RecordUint32Instruction(load); |
| 6057 } |
| 6058 return load; |
| 6059 } |
| 6060 } |
| 6061 |
| 6062 |
| 6063 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, |
| 6064 HValue* checked_key, |
| 6065 HValue* val, |
| 6066 HValue* load_dependency, |
| 6067 ElementsKind elements_kind, |
| 6068 bool is_store) { |
| 6069 if (is_store) { |
| 6070 ASSERT(val != NULL); |
| 6071 switch (elements_kind) { |
| 6072 case FAST_SMI_ELEMENTS: |
| 6073 case FAST_HOLEY_SMI_ELEMENTS: |
| 6074 // Smi-only arrays need a smi check. |
| 6075 AddInstruction(new(zone()) HCheckSmi(val)); |
| 6076 // Fall through. |
| 6077 case FAST_ELEMENTS: |
| 6078 case FAST_HOLEY_ELEMENTS: |
| 6079 case FAST_DOUBLE_ELEMENTS: |
| 6080 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 6081 return new(zone()) HStoreKeyed( |
| 6082 elements, checked_key, val, elements_kind); |
| 6083 default: |
| 6084 UNREACHABLE(); |
| 6085 return NULL; |
| 6086 } |
| 6087 } |
| 6088 // It's an element load (!is_store). |
| 6089 return new(zone()) HLoadKeyed(elements, |
| 6090 checked_key, |
| 6091 load_dependency, |
| 6092 elements_kind); |
| 6093 } |
| 6094 |
| 6095 |
| 6096 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, |
| 6097 HValue* key, |
| 6098 HValue* val, |
| 6099 HValue* dependency, |
| 6100 Handle<Map> map, |
| 6101 bool is_store) { |
| 6191 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, | 6102 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, |
| 6192 zone(), dependency); | 6103 zone(), dependency); |
| 6193 AddInstruction(mapcheck); | 6104 AddInstruction(mapcheck); |
| 6194 if (dependency) { | 6105 if (dependency) { |
| 6195 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 6106 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
| 6196 } | 6107 } |
| 6197 return BuildUncheckedMonomorphicElementAccess( | 6108 return BuildUncheckedMonomorphicElementAccess(object, key, val, |
| 6198 object, key, val, | 6109 mapcheck, map, is_store); |
| 6199 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | |
| 6200 map->elements_kind(), is_store); | |
| 6201 } | 6110 } |
| 6202 | 6111 |
| 6203 | 6112 |
| 6204 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( | 6113 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
| 6205 HValue* object, | 6114 HValue* object, |
| 6206 HValue* key, | 6115 HValue* key, |
| 6207 HValue* val, | 6116 HValue* val, |
| 6117 HCheckMaps* mapcheck, |
| 6118 Handle<Map> map, |
| 6119 bool is_store) { |
| 6120 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
| 6121 // on a HElementsTransition instruction. The flag can also be removed if the |
| 6122 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
| 6123 // ElementsKind transitions. Finally, the dependency can be removed for stores |
| 6124 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
| 6125 // generated store code. |
| 6126 if ((map->elements_kind() == FAST_HOLEY_ELEMENTS) || |
| 6127 (map->elements_kind() == FAST_ELEMENTS && is_store)) { |
| 6128 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
| 6129 } |
| 6130 bool fast_smi_only_elements = map->has_fast_smi_elements(); |
| 6131 bool fast_elements = map->has_fast_object_elements(); |
| 6132 HInstruction* elements = |
| 6133 AddInstruction(new(zone()) HLoadElements(object, mapcheck)); |
| 6134 if (is_store && (fast_elements || fast_smi_only_elements)) { |
| 6135 HCheckMaps* check_cow_map = new(zone()) HCheckMaps( |
| 6136 elements, isolate()->factory()->fixed_array_map(), zone()); |
| 6137 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 6138 AddInstruction(check_cow_map); |
| 6139 } |
| 6140 HInstruction* length = NULL; |
| 6141 HInstruction* checked_key = NULL; |
| 6142 if (map->has_external_array_elements()) { |
| 6143 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
| 6144 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length, |
| 6145 ALLOW_SMI_KEY)); |
| 6146 HLoadExternalArrayPointer* external_elements = |
| 6147 new(zone()) HLoadExternalArrayPointer(elements); |
| 6148 AddInstruction(external_elements); |
| 6149 return BuildExternalArrayElementAccess( |
| 6150 external_elements, checked_key, val, mapcheck, |
| 6151 map->elements_kind(), is_store); |
| 6152 } |
| 6153 ASSERT(fast_smi_only_elements || |
| 6154 fast_elements || |
| 6155 map->has_fast_double_elements()); |
| 6156 if (map->instance_type() == JS_ARRAY_TYPE) { |
| 6157 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck, |
| 6158 HType::Smi())); |
| 6159 } else { |
| 6160 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
| 6161 } |
| 6162 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length, |
| 6163 ALLOW_SMI_KEY)); |
| 6164 return BuildFastElementAccess(elements, checked_key, val, mapcheck, |
| 6165 map->elements_kind(), is_store); |
| 6166 } |
| 6167 |
| 6168 |
| 6169 HInstruction* HGraphBuilder::TryBuildConsolidatedElementLoad( |
| 6170 HValue* object, |
| 6171 HValue* key, |
| 6172 HValue* val, |
| 6208 SmallMapList* maps) { | 6173 SmallMapList* maps) { |
| 6209 // For polymorphic loads of similar elements kinds (i.e. all tagged or all | 6174 // For polymorphic loads of similar elements kinds (i.e. all tagged or all |
| 6210 // double), always use the "worst case" code without a transition. This is | 6175 // double), always use the "worst case" code without a transition. This is |
| 6211 // much faster than transitioning the elements to the worst case, trading a | 6176 // much faster than transitioning the elements to the worst case, trading a |
| 6212 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. | 6177 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. |
| 6213 bool has_double_maps = false; | 6178 bool has_double_maps = false; |
| 6214 bool has_smi_or_object_maps = false; | 6179 bool has_smi_or_object_maps = false; |
| 6215 bool has_js_array_access = false; | 6180 bool has_js_array_access = false; |
| 6216 bool has_non_js_array_access = false; | 6181 bool has_non_js_array_access = false; |
| 6217 Handle<Map> most_general_consolidated_map; | 6182 Handle<Map> most_general_consolidated_map; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 6242 most_general_consolidated_map->elements_kind(), | 6207 most_general_consolidated_map->elements_kind(), |
| 6243 map->elements_kind())) { | 6208 map->elements_kind())) { |
| 6244 most_general_consolidated_map = map; | 6209 most_general_consolidated_map = map; |
| 6245 } | 6210 } |
| 6246 } | 6211 } |
| 6247 if (!has_double_maps && !has_smi_or_object_maps) return NULL; | 6212 if (!has_double_maps && !has_smi_or_object_maps) return NULL; |
| 6248 | 6213 |
| 6249 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); | 6214 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); |
| 6250 AddInstruction(check_maps); | 6215 AddInstruction(check_maps); |
| 6251 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( | 6216 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( |
| 6252 object, key, val, check_maps, | 6217 object, key, val, check_maps, most_general_consolidated_map, false); |
| 6253 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, | |
| 6254 most_general_consolidated_map->elements_kind(), | |
| 6255 false); | |
| 6256 return instr; | 6218 return instr; |
| 6257 } | 6219 } |
| 6258 | 6220 |
| 6259 | 6221 |
| 6260 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 6222 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, |
| 6261 HValue* object, | 6223 HValue* key, |
| 6262 HValue* key, | 6224 HValue* val, |
| 6263 HValue* val, | 6225 Expression* prop, |
| 6264 Expression* prop, | 6226 BailoutId ast_id, |
| 6265 BailoutId ast_id, | 6227 int position, |
| 6266 int position, | 6228 bool is_store, |
| 6267 bool is_store, | 6229 bool* has_side_effects) { |
| 6268 bool* has_side_effects) { | |
| 6269 *has_side_effects = false; | 6230 *has_side_effects = false; |
| 6270 AddInstruction(new(zone()) HCheckNonSmi(object)); | 6231 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 6271 SmallMapList* maps = prop->GetReceiverTypes(); | 6232 SmallMapList* maps = prop->GetReceiverTypes(); |
| 6272 bool todo_external_array = false; | 6233 bool todo_external_array = false; |
| 6273 | 6234 |
| 6274 if (!is_store) { | 6235 if (!is_store) { |
| 6275 HInstruction* consolidated_load = | 6236 HInstruction* consolidated_load = |
| 6276 TryBuildConsolidatedElementLoad(object, key, val, maps); | 6237 TryBuildConsolidatedElementLoad(object, key, val, maps); |
| 6277 if (consolidated_load != NULL) { | 6238 if (consolidated_load != NULL) { |
| 6278 AddInstruction(consolidated_load); | 6239 AddInstruction(consolidated_load); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6443 elements, checked_key, val, elements_kind_branch, | 6404 elements, checked_key, val, elements_kind_branch, |
| 6444 elements_kind, is_store)); | 6405 elements_kind, is_store)); |
| 6445 } else if (elements_kind == DICTIONARY_ELEMENTS) { | 6406 } else if (elements_kind == DICTIONARY_ELEMENTS) { |
| 6446 if (is_store) { | 6407 if (is_store) { |
| 6447 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); | 6408 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); |
| 6448 } else { | 6409 } else { |
| 6449 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); | 6410 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); |
| 6450 } | 6411 } |
| 6451 } else { // External array elements. | 6412 } else { // External array elements. |
| 6452 access = AddInstruction(BuildExternalArrayElementAccess( | 6413 access = AddInstruction(BuildExternalArrayElementAccess( |
| 6453 external_elements, checked_key, val, | 6414 external_elements, checked_key, val, elements_kind_branch, |
| 6454 elements_kind_branch, elements_kind, is_store)); | 6415 elements_kind, is_store)); |
| 6455 } | 6416 } |
| 6456 *has_side_effects |= access->HasObservableSideEffects(); | 6417 *has_side_effects |= access->HasObservableSideEffects(); |
| 6457 if (position != RelocInfo::kNoPosition) access->set_position(position); | 6418 if (position != RelocInfo::kNoPosition) access->set_position(position); |
| 6458 if (!is_store) { | 6419 if (!is_store) { |
| 6459 Push(access); | 6420 Push(access); |
| 6460 } | 6421 } |
| 6461 current_block()->Goto(join); | 6422 current_block()->Goto(join); |
| 6462 set_current_block(if_false); | 6423 set_current_block(if_false); |
| 6463 } | 6424 } |
| 6464 } | 6425 } |
| 6465 | 6426 |
| 6466 // Deopt if none of the cases matched. | 6427 // Deopt if none of the cases matched. |
| 6467 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 6428 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); |
| 6468 join->SetJoinId(ast_id); | 6429 join->SetJoinId(ast_id); |
| 6469 set_current_block(join); | 6430 set_current_block(join); |
| 6470 return is_store ? NULL : Pop(); | 6431 return is_store ? NULL : Pop(); |
| 6471 } | 6432 } |
| 6472 | 6433 |
| 6473 | 6434 |
| 6474 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 6435 HValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj, |
| 6475 HValue* obj, | 6436 HValue* key, |
| 6476 HValue* key, | 6437 HValue* val, |
| 6477 HValue* val, | 6438 Expression* expr, |
| 6478 Expression* expr, | 6439 BailoutId ast_id, |
| 6479 BailoutId ast_id, | 6440 int position, |
| 6480 int position, | 6441 bool is_store, |
| 6481 bool is_store, | 6442 bool* has_side_effects) { |
| 6482 bool* has_side_effects) { | |
| 6483 ASSERT(!expr->IsPropertyName()); | 6443 ASSERT(!expr->IsPropertyName()); |
| 6484 HInstruction* instr = NULL; | 6444 HInstruction* instr = NULL; |
| 6485 if (expr->IsMonomorphic()) { | 6445 if (expr->IsMonomorphic()) { |
| 6486 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 6446 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
| 6487 if (map->has_slow_elements_kind()) { | 6447 if (map->has_slow_elements_kind()) { |
| 6488 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) | 6448 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) |
| 6489 : BuildLoadKeyedGeneric(obj, key); | 6449 : BuildLoadKeyedGeneric(obj, key); |
| 6490 } else { | 6450 } else { |
| 6491 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 6451 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
| 6492 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); | 6452 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); |
| 6493 } | 6453 } |
| 6494 } else if (expr->GetReceiverTypes() != NULL && | 6454 } else if (expr->GetReceiverTypes() != NULL && |
| 6495 !expr->GetReceiverTypes()->is_empty()) { | 6455 !expr->GetReceiverTypes()->is_empty()) { |
| 6496 return HandlePolymorphicElementAccess( | 6456 return HandlePolymorphicElementAccess( |
| 6497 obj, key, val, expr, ast_id, position, is_store, has_side_effects); | 6457 obj, key, val, expr, ast_id, position, is_store, has_side_effects); |
| 6498 } else { | 6458 } else { |
| 6499 if (is_store) { | 6459 if (is_store) { |
| 6500 instr = BuildStoreKeyedGeneric(obj, key, val); | 6460 instr = BuildStoreKeyedGeneric(obj, key, val); |
| 6501 } else { | 6461 } else { |
| 6502 instr = BuildLoadKeyedGeneric(obj, key); | 6462 instr = BuildLoadKeyedGeneric(obj, key); |
| 6503 } | 6463 } |
| 6504 } | 6464 } |
| 6505 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 6465 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
| 6506 AddInstruction(instr); | 6466 AddInstruction(instr); |
| 6507 *has_side_effects = instr->HasObservableSideEffects(); | 6467 *has_side_effects = instr->HasObservableSideEffects(); |
| 6508 return instr; | 6468 return instr; |
| 6509 } | 6469 } |
| 6510 | 6470 |
| 6511 | 6471 |
| 6512 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( | 6472 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, |
| 6513 HValue* object, | 6473 HValue* key, |
| 6514 HValue* key, | 6474 HValue* value) { |
| 6515 HValue* value) { | |
| 6516 HValue* context = environment()->LookupContext(); | 6475 HValue* context = environment()->LookupContext(); |
| 6517 return new(zone()) HStoreKeyedGeneric( | 6476 return new(zone()) HStoreKeyedGeneric( |
| 6518 context, | 6477 context, |
| 6519 object, | 6478 object, |
| 6520 key, | 6479 key, |
| 6521 value, | 6480 value, |
| 6522 function_strict_mode_flag()); | 6481 function_strict_mode_flag()); |
| 6523 } | 6482 } |
| 6524 | 6483 |
| 6525 | 6484 |
| 6526 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { | 6485 void HGraphBuilder::EnsureArgumentsArePushedForAccess() { |
| 6527 // Outermost function already has arguments on the stack. | 6486 // Outermost function already has arguments on the stack. |
| 6528 if (function_state()->outer() == NULL) return; | 6487 if (function_state()->outer() == NULL) return; |
| 6529 | 6488 |
| 6530 if (function_state()->arguments_pushed()) return; | 6489 if (function_state()->arguments_pushed()) return; |
| 6531 | 6490 |
| 6532 // Push arguments when entering inlined function. | 6491 // Push arguments when entering inlined function. |
| 6533 HEnterInlined* entry = function_state()->entry(); | 6492 HEnterInlined* entry = function_state()->entry(); |
| 6534 entry->set_arguments_pushed(); | 6493 entry->set_arguments_pushed(); |
| 6535 | 6494 |
| 6536 ZoneList<HValue*>* arguments_values = entry->arguments_values(); | 6495 ZoneList<HValue*>* arguments_values = entry->arguments_values(); |
| 6537 | 6496 |
| 6538 HInstruction* insert_after = entry; | 6497 HInstruction* insert_after = entry; |
| 6539 for (int i = 0; i < arguments_values->length(); i++) { | 6498 for (int i = 0; i < arguments_values->length(); i++) { |
| 6540 HValue* argument = arguments_values->at(i); | 6499 HValue* argument = arguments_values->at(i); |
| 6541 HInstruction* push_argument = new(zone()) HPushArgument(argument); | 6500 HInstruction* push_argument = new(zone()) HPushArgument(argument); |
| 6542 push_argument->InsertAfter(insert_after); | 6501 push_argument->InsertAfter(insert_after); |
| 6543 insert_after = push_argument; | 6502 insert_after = push_argument; |
| 6544 } | 6503 } |
| 6545 | 6504 |
| 6546 HArgumentsElements* arguments_elements = | 6505 HArgumentsElements* arguments_elements = |
| 6547 new(zone()) HArgumentsElements(true); | 6506 new(zone()) HArgumentsElements(true); |
| 6548 arguments_elements->ClearFlag(HValue::kUseGVN); | 6507 arguments_elements->ClearFlag(HValue::kUseGVN); |
| 6549 arguments_elements->InsertAfter(insert_after); | 6508 arguments_elements->InsertAfter(insert_after); |
| 6550 function_state()->set_arguments_elements(arguments_elements); | 6509 function_state()->set_arguments_elements(arguments_elements); |
| 6551 } | 6510 } |
| 6552 | 6511 |
| 6553 | 6512 |
| 6554 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) { | 6513 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { |
| 6555 VariableProxy* proxy = expr->obj()->AsVariableProxy(); | 6514 VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
| 6556 if (proxy == NULL) return false; | 6515 if (proxy == NULL) return false; |
| 6557 if (!proxy->var()->IsStackAllocated()) return false; | 6516 if (!proxy->var()->IsStackAllocated()) return false; |
| 6558 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { | 6517 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { |
| 6559 return false; | 6518 return false; |
| 6560 } | 6519 } |
| 6561 | 6520 |
| 6562 HInstruction* result = NULL; | 6521 HInstruction* result = NULL; |
| 6563 if (expr->key()->IsPropertyName()) { | 6522 if (expr->key()->IsPropertyName()) { |
| 6564 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 6523 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6603 HInstruction* checked_key = | 6562 HInstruction* checked_key = |
| 6604 AddInstruction(new(zone()) HBoundsCheck(key, length)); | 6563 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 6605 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); | 6564 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); |
| 6606 } | 6565 } |
| 6607 } | 6566 } |
| 6608 ast_context()->ReturnInstruction(result, expr->id()); | 6567 ast_context()->ReturnInstruction(result, expr->id()); |
| 6609 return true; | 6568 return true; |
| 6610 } | 6569 } |
| 6611 | 6570 |
| 6612 | 6571 |
| 6613 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { | 6572 void HGraphBuilder::VisitProperty(Property* expr) { |
| 6614 ASSERT(!HasStackOverflow()); | 6573 ASSERT(!HasStackOverflow()); |
| 6615 ASSERT(current_block() != NULL); | 6574 ASSERT(current_block() != NULL); |
| 6616 ASSERT(current_block()->HasPredecessor()); | 6575 ASSERT(current_block()->HasPredecessor()); |
| 6617 expr->RecordTypeFeedback(oracle(), zone()); | 6576 expr->RecordTypeFeedback(oracle(), zone()); |
| 6618 | 6577 |
| 6619 if (TryArgumentsAccess(expr)) return; | 6578 if (TryArgumentsAccess(expr)) return; |
| 6620 | 6579 |
| 6621 CHECK_ALIVE(VisitForValue(expr->obj())); | 6580 CHECK_ALIVE(VisitForValue(expr->obj())); |
| 6622 | 6581 |
| 6623 HInstruction* instr = NULL; | 6582 HInstruction* instr = NULL; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6694 Drop(1); | 6653 Drop(1); |
| 6695 } | 6654 } |
| 6696 } | 6655 } |
| 6697 return ast_context()->ReturnValue(load); | 6656 return ast_context()->ReturnValue(load); |
| 6698 } | 6657 } |
| 6699 instr->set_position(expr->position()); | 6658 instr->set_position(expr->position()); |
| 6700 return ast_context()->ReturnInstruction(instr, expr->id()); | 6659 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 6701 } | 6660 } |
| 6702 | 6661 |
| 6703 | 6662 |
| 6704 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 6663 void HGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
| 6705 Handle<Map> receiver_map) { | 6664 Handle<Map> receiver_map) { |
| 6706 if (!holder.is_null()) { | 6665 if (!holder.is_null()) { |
| 6707 AddInstruction(new(zone()) HCheckPrototypeMaps( | 6666 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 6708 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), holder)); | 6667 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), holder)); |
| 6709 } | 6668 } |
| 6710 } | 6669 } |
| 6711 | 6670 |
| 6712 | 6671 |
| 6713 void HOptimizedGraphBuilder::AddCheckConstantFunction( | 6672 void HGraphBuilder::AddCheckConstantFunction(Handle<JSObject> holder, |
| 6714 Handle<JSObject> holder, | 6673 HValue* receiver, |
| 6715 HValue* receiver, | 6674 Handle<Map> receiver_map) { |
| 6716 Handle<Map> receiver_map) { | |
| 6717 // Constant functions have the nice property that the map will change if they | 6675 // Constant functions have the nice property that the map will change if they |
| 6718 // are overwritten. Therefore it is enough to check the map of the holder and | 6676 // are overwritten. Therefore it is enough to check the map of the holder and |
| 6719 // its prototypes. | 6677 // its prototypes. |
| 6720 AddCheckMapsWithTransitions(receiver, receiver_map); | 6678 AddCheckMapsWithTransitions(receiver, receiver_map); |
| 6721 AddCheckPrototypeMaps(holder, receiver_map); | 6679 AddCheckPrototypeMaps(holder, receiver_map); |
| 6722 } | 6680 } |
| 6723 | 6681 |
| 6724 | 6682 |
| 6725 class FunctionSorter { | 6683 class FunctionSorter { |
| 6726 public: | 6684 public: |
| (...skipping 21 matching lines...) Expand all Loading... |
| 6748 FunctionSorter const* function1 = reinterpret_cast<FunctionSorter const*>(a); | 6706 FunctionSorter const* function1 = reinterpret_cast<FunctionSorter const*>(a); |
| 6749 FunctionSorter const* function2 = reinterpret_cast<FunctionSorter const*>(b); | 6707 FunctionSorter const* function2 = reinterpret_cast<FunctionSorter const*>(b); |
| 6750 int diff = function1->ticks() - function2->ticks(); | 6708 int diff = function1->ticks() - function2->ticks(); |
| 6751 if (diff != 0) return -diff; | 6709 if (diff != 0) return -diff; |
| 6752 diff = function1->ast_length() - function2->ast_length(); | 6710 diff = function1->ast_length() - function2->ast_length(); |
| 6753 if (diff != 0) return diff; | 6711 if (diff != 0) return diff; |
| 6754 return function1->src_length() - function2->src_length(); | 6712 return function1->src_length() - function2->src_length(); |
| 6755 } | 6713 } |
| 6756 | 6714 |
| 6757 | 6715 |
| 6758 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( | 6716 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, |
| 6759 Call* expr, | 6717 HValue* receiver, |
| 6760 HValue* receiver, | 6718 SmallMapList* types, |
| 6761 SmallMapList* types, | 6719 Handle<String> name) { |
| 6762 Handle<String> name) { | |
| 6763 // TODO(ager): We should recognize when the prototype chains for different | 6720 // TODO(ager): We should recognize when the prototype chains for different |
| 6764 // maps are identical. In that case we can avoid repeatedly generating the | 6721 // maps are identical. In that case we can avoid repeatedly generating the |
| 6765 // same prototype map checks. | 6722 // same prototype map checks. |
| 6766 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6723 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 6767 HBasicBlock* join = NULL; | 6724 HBasicBlock* join = NULL; |
| 6768 FunctionSorter order[kMaxCallPolymorphism]; | 6725 FunctionSorter order[kMaxCallPolymorphism]; |
| 6769 int ordered_functions = 0; | 6726 int ordered_functions = 0; |
| 6770 for (int i = 0; | 6727 for (int i = 0; |
| 6771 i < types->length() && ordered_functions < kMaxCallPolymorphism; | 6728 i < types->length() && ordered_functions < kMaxCallPolymorphism; |
| 6772 ++i) { | 6729 ++i) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6854 if (join->HasPredecessor()) { | 6811 if (join->HasPredecessor()) { |
| 6855 set_current_block(join); | 6812 set_current_block(join); |
| 6856 join->SetJoinId(expr->id()); | 6813 join->SetJoinId(expr->id()); |
| 6857 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 6814 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
| 6858 } else { | 6815 } else { |
| 6859 set_current_block(NULL); | 6816 set_current_block(NULL); |
| 6860 } | 6817 } |
| 6861 } | 6818 } |
| 6862 | 6819 |
| 6863 | 6820 |
| 6864 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target, | 6821 void HGraphBuilder::TraceInline(Handle<JSFunction> target, |
| 6865 Handle<JSFunction> caller, | 6822 Handle<JSFunction> caller, |
| 6866 const char* reason) { | 6823 const char* reason) { |
| 6867 if (FLAG_trace_inlining) { | 6824 if (FLAG_trace_inlining) { |
| 6868 SmartArrayPointer<char> target_name = | 6825 SmartArrayPointer<char> target_name = |
| 6869 target->shared()->DebugName()->ToCString(); | 6826 target->shared()->DebugName()->ToCString(); |
| 6870 SmartArrayPointer<char> caller_name = | 6827 SmartArrayPointer<char> caller_name = |
| 6871 caller->shared()->DebugName()->ToCString(); | 6828 caller->shared()->DebugName()->ToCString(); |
| 6872 if (reason == NULL) { | 6829 if (reason == NULL) { |
| 6873 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); | 6830 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); |
| 6874 } else { | 6831 } else { |
| 6875 PrintF("Did not inline %s called from %s (%s).\n", | 6832 PrintF("Did not inline %s called from %s (%s).\n", |
| 6876 *target_name, *caller_name, reason); | 6833 *target_name, *caller_name, reason); |
| 6877 } | 6834 } |
| 6878 } | 6835 } |
| 6879 } | 6836 } |
| 6880 | 6837 |
| 6881 | 6838 |
| 6882 static const int kNotInlinable = 1000000000; | 6839 static const int kNotInlinable = 1000000000; |
| 6883 | 6840 |
| 6884 | 6841 |
| 6885 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) { | 6842 int HGraphBuilder::InliningAstSize(Handle<JSFunction> target) { |
| 6886 if (!FLAG_use_inlining) return kNotInlinable; | 6843 if (!FLAG_use_inlining) return kNotInlinable; |
| 6887 | 6844 |
| 6888 // Precondition: call is monomorphic and we have found a target with the | 6845 // Precondition: call is monomorphic and we have found a target with the |
| 6889 // appropriate arity. | 6846 // appropriate arity. |
| 6890 Handle<JSFunction> caller = info()->closure(); | 6847 Handle<JSFunction> caller = info()->closure(); |
| 6891 Handle<SharedFunctionInfo> target_shared(target->shared()); | 6848 Handle<SharedFunctionInfo> target_shared(target->shared()); |
| 6892 | 6849 |
| 6893 // Do a quick check on source code length to avoid parsing large | 6850 // Do a quick check on source code length to avoid parsing large |
| 6894 // inlining candidates. | 6851 // inlining candidates. |
| 6895 if (target_shared->SourceSize() > | 6852 if (target_shared->SourceSize() > |
| (...skipping 10 matching lines...) Expand all Loading... |
| 6906 if (target_shared->dont_inline() || target_shared->dont_optimize()) { | 6863 if (target_shared->dont_inline() || target_shared->dont_optimize()) { |
| 6907 TraceInline(target, caller, "target contains unsupported syntax [early]"); | 6864 TraceInline(target, caller, "target contains unsupported syntax [early]"); |
| 6908 return kNotInlinable; | 6865 return kNotInlinable; |
| 6909 } | 6866 } |
| 6910 | 6867 |
| 6911 int nodes_added = target_shared->ast_node_count(); | 6868 int nodes_added = target_shared->ast_node_count(); |
| 6912 return nodes_added; | 6869 return nodes_added; |
| 6913 } | 6870 } |
| 6914 | 6871 |
| 6915 | 6872 |
| 6916 bool HOptimizedGraphBuilder::TryInline(CallKind call_kind, | 6873 bool HGraphBuilder::TryInline(CallKind call_kind, |
| 6917 Handle<JSFunction> target, | 6874 Handle<JSFunction> target, |
| 6918 int arguments_count, | 6875 int arguments_count, |
| 6919 HValue* implicit_return_value, | 6876 HValue* implicit_return_value, |
| 6920 BailoutId ast_id, | 6877 BailoutId ast_id, |
| 6921 BailoutId return_id, | 6878 BailoutId return_id, |
| 6922 InliningKind inlining_kind) { | 6879 InliningKind inlining_kind) { |
| 6923 int nodes_added = InliningAstSize(target); | 6880 int nodes_added = InliningAstSize(target); |
| 6924 if (nodes_added == kNotInlinable) return false; | 6881 if (nodes_added == kNotInlinable) return false; |
| 6925 | 6882 |
| 6926 Handle<JSFunction> caller = info()->closure(); | 6883 Handle<JSFunction> caller = info()->closure(); |
| 6927 | 6884 |
| 6928 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { | 6885 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { |
| 6929 TraceInline(target, caller, "target AST is too large [early]"); | 6886 TraceInline(target, caller, "target AST is too large [early]"); |
| 6930 return false; | 6887 return false; |
| 6931 } | 6888 } |
| 6932 | 6889 |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7221 function_return()->SetJoinId(ast_id); | 7178 function_return()->SetJoinId(ast_id); |
| 7222 set_current_block(function_return()); | 7179 set_current_block(function_return()); |
| 7223 } else { | 7180 } else { |
| 7224 set_current_block(NULL); | 7181 set_current_block(NULL); |
| 7225 } | 7182 } |
| 7226 delete target_state; | 7183 delete target_state; |
| 7227 return true; | 7184 return true; |
| 7228 } | 7185 } |
| 7229 | 7186 |
| 7230 | 7187 |
| 7231 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) { | 7188 bool HGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) { |
| 7232 // The function call we are inlining is a method call if the call | 7189 // The function call we are inlining is a method call if the call |
| 7233 // is a property call. | 7190 // is a property call. |
| 7234 CallKind call_kind = (expr->expression()->AsProperty() == NULL) | 7191 CallKind call_kind = (expr->expression()->AsProperty() == NULL) |
| 7235 ? CALL_AS_FUNCTION | 7192 ? CALL_AS_FUNCTION |
| 7236 : CALL_AS_METHOD; | 7193 : CALL_AS_METHOD; |
| 7237 | 7194 |
| 7238 return TryInline(call_kind, | 7195 return TryInline(call_kind, |
| 7239 expr->target(), | 7196 expr->target(), |
| 7240 expr->arguments()->length(), | 7197 expr->arguments()->length(), |
| 7241 NULL, | 7198 NULL, |
| 7242 expr->id(), | 7199 expr->id(), |
| 7243 expr->ReturnId(), | 7200 expr->ReturnId(), |
| 7244 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); | 7201 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); |
| 7245 } | 7202 } |
| 7246 | 7203 |
| 7247 | 7204 |
| 7248 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, | 7205 bool HGraphBuilder::TryInlineConstruct(CallNew* expr, |
| 7249 HValue* implicit_return_value) { | 7206 HValue* implicit_return_value) { |
| 7250 return TryInline(CALL_AS_FUNCTION, | 7207 return TryInline(CALL_AS_FUNCTION, |
| 7251 expr->target(), | 7208 expr->target(), |
| 7252 expr->arguments()->length(), | 7209 expr->arguments()->length(), |
| 7253 implicit_return_value, | 7210 implicit_return_value, |
| 7254 expr->id(), | 7211 expr->id(), |
| 7255 expr->ReturnId(), | 7212 expr->ReturnId(), |
| 7256 CONSTRUCT_CALL_RETURN); | 7213 CONSTRUCT_CALL_RETURN); |
| 7257 } | 7214 } |
| 7258 | 7215 |
| 7259 | 7216 |
| 7260 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, | 7217 bool HGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, |
| 7261 Property* prop) { | 7218 Property* prop) { |
| 7262 return TryInline(CALL_AS_METHOD, | 7219 return TryInline(CALL_AS_METHOD, |
| 7263 getter, | 7220 getter, |
| 7264 0, | 7221 0, |
| 7265 NULL, | 7222 NULL, |
| 7266 prop->id(), | 7223 prop->id(), |
| 7267 prop->LoadId(), | 7224 prop->LoadId(), |
| 7268 GETTER_CALL_RETURN); | 7225 GETTER_CALL_RETURN); |
| 7269 } | 7226 } |
| 7270 | 7227 |
| 7271 | 7228 |
| 7272 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, | 7229 bool HGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, |
| 7273 Assignment* assignment, | 7230 Assignment* assignment, |
| 7274 HValue* implicit_return_value) { | 7231 HValue* implicit_return_value) { |
| 7275 return TryInline(CALL_AS_METHOD, | 7232 return TryInline(CALL_AS_METHOD, |
| 7276 setter, | 7233 setter, |
| 7277 1, | 7234 1, |
| 7278 implicit_return_value, | 7235 implicit_return_value, |
| 7279 assignment->id(), | 7236 assignment->id(), |
| 7280 assignment->AssignmentId(), | 7237 assignment->AssignmentId(), |
| 7281 SETTER_CALL_RETURN); | 7238 SETTER_CALL_RETURN); |
| 7282 } | 7239 } |
| 7283 | 7240 |
| 7284 | 7241 |
| 7285 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, | 7242 bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) { |
| 7286 bool drop_extra) { | |
| 7287 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 7243 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
| 7288 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 7244 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
| 7289 switch (id) { | 7245 switch (id) { |
| 7290 case kMathExp: | 7246 case kMathExp: |
| 7291 if (!FLAG_fast_math) break; | 7247 if (!FLAG_fast_math) break; |
| 7292 // Fall through if FLAG_fast_math. | 7248 // Fall through if FLAG_fast_math. |
| 7293 case kMathRound: | 7249 case kMathRound: |
| 7294 case kMathAbs: | 7250 case kMathAbs: |
| 7295 case kMathSqrt: | 7251 case kMathSqrt: |
| 7296 case kMathLog: | 7252 case kMathLog: |
| (...skipping 13 matching lines...) Expand all Loading... |
| 7310 } | 7266 } |
| 7311 break; | 7267 break; |
| 7312 default: | 7268 default: |
| 7313 // Not supported for inlining yet. | 7269 // Not supported for inlining yet. |
| 7314 break; | 7270 break; |
| 7315 } | 7271 } |
| 7316 return false; | 7272 return false; |
| 7317 } | 7273 } |
| 7318 | 7274 |
| 7319 | 7275 |
| 7320 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( | 7276 bool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr, |
| 7321 Call* expr, | 7277 HValue* receiver, |
| 7322 HValue* receiver, | 7278 Handle<Map> receiver_map, |
| 7323 Handle<Map> receiver_map, | 7279 CheckType check_type) { |
| 7324 CheckType check_type) { | |
| 7325 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); | 7280 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); |
| 7326 // Try to inline calls like Math.* as operations in the calling function. | 7281 // Try to inline calls like Math.* as operations in the calling function. |
| 7327 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 7282 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
| 7328 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 7283 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
| 7329 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 7284 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 7330 switch (id) { | 7285 switch (id) { |
| 7331 case kStringCharCodeAt: | 7286 case kStringCharCodeAt: |
| 7332 case kStringCharAt: | 7287 case kStringCharAt: |
| 7333 if (argument_count == 2 && check_type == STRING_CHECK) { | 7288 if (argument_count == 2 && check_type == STRING_CHECK) { |
| 7334 HValue* index = Pop(); | 7289 HValue* index = Pop(); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7444 } | 7399 } |
| 7445 break; | 7400 break; |
| 7446 default: | 7401 default: |
| 7447 // Not yet supported for inlining. | 7402 // Not yet supported for inlining. |
| 7448 break; | 7403 break; |
| 7449 } | 7404 } |
| 7450 return false; | 7405 return false; |
| 7451 } | 7406 } |
| 7452 | 7407 |
| 7453 | 7408 |
| 7454 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { | 7409 bool HGraphBuilder::TryCallApply(Call* expr) { |
| 7455 Expression* callee = expr->expression(); | 7410 Expression* callee = expr->expression(); |
| 7456 Property* prop = callee->AsProperty(); | 7411 Property* prop = callee->AsProperty(); |
| 7457 ASSERT(prop != NULL); | 7412 ASSERT(prop != NULL); |
| 7458 | 7413 |
| 7459 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { | 7414 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { |
| 7460 return false; | 7415 return false; |
| 7461 } | 7416 } |
| 7462 Handle<Map> function_map = expr->GetReceiverTypes()->first(); | 7417 Handle<Map> function_map = expr->GetReceiverTypes()->first(); |
| 7463 if (function_map->instance_type() != JS_FUNCTION_TYPE || | 7418 if (function_map->instance_type() != JS_FUNCTION_TYPE || |
| 7464 !expr->target()->shared()->HasBuiltinFunctionId() || | 7419 !expr->target()->shared()->HasBuiltinFunctionId() || |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7572 return NULL; | 7527 return NULL; |
| 7573 } | 7528 } |
| 7574 current = next; | 7529 current = next; |
| 7575 } | 7530 } |
| 7576 } | 7531 } |
| 7577 | 7532 |
| 7578 return kinds[first_index]; | 7533 return kinds[first_index]; |
| 7579 } | 7534 } |
| 7580 | 7535 |
| 7581 | 7536 |
| 7582 void HOptimizedGraphBuilder::VisitCall(Call* expr) { | 7537 void HGraphBuilder::VisitCall(Call* expr) { |
| 7583 ASSERT(!HasStackOverflow()); | 7538 ASSERT(!HasStackOverflow()); |
| 7584 ASSERT(current_block() != NULL); | 7539 ASSERT(current_block() != NULL); |
| 7585 ASSERT(current_block()->HasPredecessor()); | 7540 ASSERT(current_block()->HasPredecessor()); |
| 7586 Expression* callee = expr->expression(); | 7541 Expression* callee = expr->expression(); |
| 7587 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 7542 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 7588 HInstruction* call = NULL; | 7543 HInstruction* call = NULL; |
| 7589 | 7544 |
| 7590 Property* prop = callee->AsProperty(); | 7545 Property* prop = callee->AsProperty(); |
| 7591 if (prop != NULL) { | 7546 if (prop != NULL) { |
| 7592 if (!prop->key()->IsPropertyName()) { | 7547 if (!prop->key()->IsPropertyName()) { |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7802 | 7757 |
| 7803 | 7758 |
| 7804 // Checks whether allocation using the given constructor can be inlined. | 7759 // Checks whether allocation using the given constructor can be inlined. |
| 7805 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 7760 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { |
| 7806 return constructor->has_initial_map() && | 7761 return constructor->has_initial_map() && |
| 7807 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 7762 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
| 7808 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; | 7763 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; |
| 7809 } | 7764 } |
| 7810 | 7765 |
| 7811 | 7766 |
| 7812 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 7767 void HGraphBuilder::VisitCallNew(CallNew* expr) { |
| 7813 ASSERT(!HasStackOverflow()); | 7768 ASSERT(!HasStackOverflow()); |
| 7814 ASSERT(current_block() != NULL); | 7769 ASSERT(current_block() != NULL); |
| 7815 ASSERT(current_block()->HasPredecessor()); | 7770 ASSERT(current_block()->HasPredecessor()); |
| 7816 expr->RecordTypeFeedback(oracle()); | 7771 expr->RecordTypeFeedback(oracle()); |
| 7817 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 7772 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
| 7818 HValue* context = environment()->LookupContext(); | 7773 HValue* context = environment()->LookupContext(); |
| 7819 | 7774 |
| 7820 if (FLAG_inline_construct && | 7775 if (FLAG_inline_construct && |
| 7821 expr->IsMonomorphic() && | 7776 expr->IsMonomorphic() && |
| 7822 IsAllocationInlineable(expr->target())) { | 7777 IsAllocationInlineable(expr->target())) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7866 new(zone()) HCallNew(context, constructor, argument_count); | 7821 new(zone()) HCallNew(context, constructor, argument_count); |
| 7867 Drop(argument_count); | 7822 Drop(argument_count); |
| 7868 call->set_position(expr->position()); | 7823 call->set_position(expr->position()); |
| 7869 return ast_context()->ReturnInstruction(call, expr->id()); | 7824 return ast_context()->ReturnInstruction(call, expr->id()); |
| 7870 } | 7825 } |
| 7871 } | 7826 } |
| 7872 | 7827 |
| 7873 | 7828 |
| 7874 // Support for generating inlined runtime functions. | 7829 // Support for generating inlined runtime functions. |
| 7875 | 7830 |
| 7876 // Lookup table for generators for runtime calls that are generated inline. | 7831 // Lookup table for generators for runtime calls that are generated inline. |
| 7877 // Elements of the table are member pointers to functions of | 7832 // Elements of the table are member pointers to functions of HGraphBuilder. |
| 7878 // HOptimizedGraphBuilder. | |
| 7879 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ | 7833 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ |
| 7880 &HOptimizedGraphBuilder::Generate##Name, | 7834 &HGraphBuilder::Generate##Name, |
| 7881 | 7835 |
| 7882 const HOptimizedGraphBuilder::InlineFunctionGenerator | 7836 const HGraphBuilder::InlineFunctionGenerator |
| 7883 HOptimizedGraphBuilder::kInlineFunctionGenerators[] = { | 7837 HGraphBuilder::kInlineFunctionGenerators[] = { |
| 7884 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 7838 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
| 7885 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 7839 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
| 7886 }; | 7840 }; |
| 7887 #undef INLINE_FUNCTION_GENERATOR_ADDRESS | 7841 #undef INLINE_FUNCTION_GENERATOR_ADDRESS |
| 7888 | 7842 |
| 7889 | 7843 |
| 7890 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 7844 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| 7891 ASSERT(!HasStackOverflow()); | 7845 ASSERT(!HasStackOverflow()); |
| 7892 ASSERT(current_block() != NULL); | 7846 ASSERT(current_block() != NULL); |
| 7893 ASSERT(current_block()->HasPredecessor()); | 7847 ASSERT(current_block()->HasPredecessor()); |
| 7894 if (expr->is_jsruntime()) { | 7848 if (expr->is_jsruntime()) { |
| 7895 return Bailout("call to a JavaScript runtime function"); | 7849 return Bailout("call to a JavaScript runtime function"); |
| 7896 } | 7850 } |
| 7897 | 7851 |
| 7898 const Runtime::Function* function = expr->function(); | 7852 const Runtime::Function* function = expr->function(); |
| 7899 ASSERT(function != NULL); | 7853 ASSERT(function != NULL); |
| 7900 if (function->intrinsic_type == Runtime::INLINE) { | 7854 if (function->intrinsic_type == Runtime::INLINE) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 7918 Handle<String> name = expr->name(); | 7872 Handle<String> name = expr->name(); |
| 7919 int argument_count = expr->arguments()->length(); | 7873 int argument_count = expr->arguments()->length(); |
| 7920 HCallRuntime* call = | 7874 HCallRuntime* call = |
| 7921 new(zone()) HCallRuntime(context, name, function, argument_count); | 7875 new(zone()) HCallRuntime(context, name, function, argument_count); |
| 7922 Drop(argument_count); | 7876 Drop(argument_count); |
| 7923 return ast_context()->ReturnInstruction(call, expr->id()); | 7877 return ast_context()->ReturnInstruction(call, expr->id()); |
| 7924 } | 7878 } |
| 7925 } | 7879 } |
| 7926 | 7880 |
| 7927 | 7881 |
| 7928 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 7882 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
| 7929 ASSERT(!HasStackOverflow()); | 7883 ASSERT(!HasStackOverflow()); |
| 7930 ASSERT(current_block() != NULL); | 7884 ASSERT(current_block() != NULL); |
| 7931 ASSERT(current_block()->HasPredecessor()); | 7885 ASSERT(current_block()->HasPredecessor()); |
| 7932 switch (expr->op()) { | 7886 switch (expr->op()) { |
| 7933 case Token::DELETE: return VisitDelete(expr); | 7887 case Token::DELETE: return VisitDelete(expr); |
| 7934 case Token::VOID: return VisitVoid(expr); | 7888 case Token::VOID: return VisitVoid(expr); |
| 7935 case Token::TYPEOF: return VisitTypeof(expr); | 7889 case Token::TYPEOF: return VisitTypeof(expr); |
| 7936 case Token::ADD: return VisitAdd(expr); | 7890 case Token::ADD: return VisitAdd(expr); |
| 7937 case Token::SUB: return VisitSub(expr); | 7891 case Token::SUB: return VisitSub(expr); |
| 7938 case Token::BIT_NOT: return VisitBitNot(expr); | 7892 case Token::BIT_NOT: return VisitBitNot(expr); |
| 7939 case Token::NOT: return VisitNot(expr); | 7893 case Token::NOT: return VisitNot(expr); |
| 7940 default: UNREACHABLE(); | 7894 default: UNREACHABLE(); |
| 7941 } | 7895 } |
| 7942 } | 7896 } |
| 7943 | 7897 |
| 7944 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { | 7898 void HGraphBuilder::VisitDelete(UnaryOperation* expr) { |
| 7945 Property* prop = expr->expression()->AsProperty(); | 7899 Property* prop = expr->expression()->AsProperty(); |
| 7946 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 7900 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 7947 if (prop != NULL) { | 7901 if (prop != NULL) { |
| 7948 CHECK_ALIVE(VisitForValue(prop->obj())); | 7902 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7949 CHECK_ALIVE(VisitForValue(prop->key())); | 7903 CHECK_ALIVE(VisitForValue(prop->key())); |
| 7950 HValue* key = Pop(); | 7904 HValue* key = Pop(); |
| 7951 HValue* obj = Pop(); | 7905 HValue* obj = Pop(); |
| 7952 HValue* context = environment()->LookupContext(); | 7906 HValue* context = environment()->LookupContext(); |
| 7953 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key); | 7907 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key); |
| 7954 return ast_context()->ReturnInstruction(instr, expr->id()); | 7908 return ast_context()->ReturnInstruction(instr, expr->id()); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 7969 } | 7923 } |
| 7970 } else { | 7924 } else { |
| 7971 // Result of deleting non-property, non-variable reference is true. | 7925 // Result of deleting non-property, non-variable reference is true. |
| 7972 // Evaluate the subexpression for side effects. | 7926 // Evaluate the subexpression for side effects. |
| 7973 CHECK_ALIVE(VisitForEffect(expr->expression())); | 7927 CHECK_ALIVE(VisitForEffect(expr->expression())); |
| 7974 return ast_context()->ReturnValue(graph()->GetConstantTrue()); | 7928 return ast_context()->ReturnValue(graph()->GetConstantTrue()); |
| 7975 } | 7929 } |
| 7976 } | 7930 } |
| 7977 | 7931 |
| 7978 | 7932 |
| 7979 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) { | 7933 void HGraphBuilder::VisitVoid(UnaryOperation* expr) { |
| 7980 CHECK_ALIVE(VisitForEffect(expr->expression())); | 7934 CHECK_ALIVE(VisitForEffect(expr->expression())); |
| 7981 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 7935 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
| 7982 } | 7936 } |
| 7983 | 7937 |
| 7984 | 7938 |
| 7985 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { | 7939 void HGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
| 7986 CHECK_ALIVE(VisitForTypeOf(expr->expression())); | 7940 CHECK_ALIVE(VisitForTypeOf(expr->expression())); |
| 7987 HValue* value = Pop(); | 7941 HValue* value = Pop(); |
| 7988 HValue* context = environment()->LookupContext(); | 7942 HValue* context = environment()->LookupContext(); |
| 7989 HInstruction* instr = new(zone()) HTypeof(context, value); | 7943 HInstruction* instr = new(zone()) HTypeof(context, value); |
| 7990 return ast_context()->ReturnInstruction(instr, expr->id()); | 7944 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7991 } | 7945 } |
| 7992 | 7946 |
| 7993 | 7947 |
| 7994 void HOptimizedGraphBuilder::VisitAdd(UnaryOperation* expr) { | 7948 void HGraphBuilder::VisitAdd(UnaryOperation* expr) { |
| 7995 CHECK_ALIVE(VisitForValue(expr->expression())); | 7949 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 7996 HValue* value = Pop(); | 7950 HValue* value = Pop(); |
| 7997 HValue* context = environment()->LookupContext(); | 7951 HValue* context = environment()->LookupContext(); |
| 7998 HInstruction* instr = | 7952 HInstruction* instr = |
| 7999 new(zone()) HMul(context, value, graph()->GetConstant1()); | 7953 new(zone()) HMul(context, value, graph_->GetConstant1()); |
| 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::VisitSub(UnaryOperation* expr) { | 7958 void HGraphBuilder::VisitSub(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()->GetConstantMinus1()); | 7963 new(zone()) HMul(context, value, graph_->GetConstantMinus1()); |
| 8010 TypeInfo info = oracle()->UnaryType(expr); | 7964 TypeInfo info = oracle()->UnaryType(expr); |
| 8011 Representation rep = ToRepresentation(info); | 7965 Representation rep = ToRepresentation(info); |
| 8012 if (info.IsUninitialized()) { | 7966 if (info.IsUninitialized()) { |
| 8013 AddInstruction(new(zone()) HSoftDeoptimize); | 7967 AddInstruction(new(zone()) HSoftDeoptimize); |
| 8014 current_block()->MarkAsDeoptimizing(); | 7968 current_block()->MarkAsDeoptimizing(); |
| 8015 info = TypeInfo::Unknown(); | 7969 info = TypeInfo::Unknown(); |
| 8016 } | 7970 } |
| 8017 HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep); | 7971 HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep); |
| 8018 return ast_context()->ReturnInstruction(instr, expr->id()); | 7972 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 8019 } | 7973 } |
| 8020 | 7974 |
| 8021 | 7975 |
| 8022 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 7976 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
| 8023 CHECK_ALIVE(VisitForValue(expr->expression())); | 7977 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 8024 HValue* value = Pop(); | 7978 HValue* value = Pop(); |
| 8025 TypeInfo info = oracle()->UnaryType(expr); | 7979 TypeInfo info = oracle()->UnaryType(expr); |
| 8026 if (info.IsUninitialized()) { | 7980 if (info.IsUninitialized()) { |
| 8027 AddInstruction(new(zone()) HSoftDeoptimize); | 7981 AddInstruction(new(zone()) HSoftDeoptimize); |
| 8028 current_block()->MarkAsDeoptimizing(); | 7982 current_block()->MarkAsDeoptimizing(); |
| 8029 } | 7983 } |
| 8030 HInstruction* instr = new(zone()) HBitNot(value); | 7984 HInstruction* instr = new(zone()) HBitNot(value); |
| 8031 return ast_context()->ReturnInstruction(instr, expr->id()); | 7985 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 8032 } | 7986 } |
| 8033 | 7987 |
| 8034 | 7988 |
| 8035 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { | 7989 void HGraphBuilder::VisitNot(UnaryOperation* expr) { |
| 8036 if (ast_context()->IsTest()) { | 7990 if (ast_context()->IsTest()) { |
| 8037 TestContext* context = TestContext::cast(ast_context()); | 7991 TestContext* context = TestContext::cast(ast_context()); |
| 8038 VisitForControl(expr->expression(), | 7992 VisitForControl(expr->expression(), |
| 8039 context->if_false(), | 7993 context->if_false(), |
| 8040 context->if_true()); | 7994 context->if_true()); |
| 8041 return; | 7995 return; |
| 8042 } | 7996 } |
| 8043 | 7997 |
| 8044 if (ast_context()->IsEffect()) { | 7998 if (ast_context()->IsEffect()) { |
| 8045 VisitForEffect(expr->expression()); | 7999 VisitForEffect(expr->expression()); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 8069 materialize_true = NULL; | 8023 materialize_true = NULL; |
| 8070 } | 8024 } |
| 8071 | 8025 |
| 8072 HBasicBlock* join = | 8026 HBasicBlock* join = |
| 8073 CreateJoin(materialize_false, materialize_true, expr->id()); | 8027 CreateJoin(materialize_false, materialize_true, expr->id()); |
| 8074 set_current_block(join); | 8028 set_current_block(join); |
| 8075 if (join != NULL) return ast_context()->ReturnValue(Pop()); | 8029 if (join != NULL) return ast_context()->ReturnValue(Pop()); |
| 8076 } | 8030 } |
| 8077 | 8031 |
| 8078 | 8032 |
| 8079 HInstruction* HOptimizedGraphBuilder::BuildIncrement( | 8033 HInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input, |
| 8080 bool returns_original_input, | 8034 CountOperation* expr) { |
| 8081 CountOperation* expr) { | |
| 8082 // The input to the count operation is on top of the expression stack. | 8035 // The input to the count operation is on top of the expression stack. |
| 8083 TypeInfo info = oracle()->IncrementType(expr); | 8036 TypeInfo info = oracle()->IncrementType(expr); |
| 8084 Representation rep = ToRepresentation(info); | 8037 Representation rep = ToRepresentation(info); |
| 8085 if (rep.IsTagged()) { | 8038 if (rep.IsTagged()) { |
| 8086 rep = Representation::Integer32(); | 8039 rep = Representation::Integer32(); |
| 8087 } | 8040 } |
| 8088 | 8041 |
| 8089 if (returns_original_input) { | 8042 if (returns_original_input) { |
| 8090 // We need an explicit HValue representing ToNumber(input). The | 8043 // We need an explicit HValue representing ToNumber(input). The |
| 8091 // actual HChange instruction we need is (sometimes) added in a later | 8044 // actual HChange instruction we need is (sometimes) added in a later |
| 8092 // phase, so it is not available now to be used as an input to HAdd and | 8045 // phase, so it is not available now to be used as an input to HAdd and |
| 8093 // as the return value. | 8046 // as the return value. |
| 8094 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); | 8047 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); |
| 8095 AddInstruction(number_input); | 8048 AddInstruction(number_input); |
| 8096 Push(number_input); | 8049 Push(number_input); |
| 8097 } | 8050 } |
| 8098 | 8051 |
| 8099 // The addition has no side effects, so we do not need | 8052 // The addition has no side effects, so we do not need |
| 8100 // to simulate the expression stack after this instruction. | 8053 // to simulate the expression stack after this instruction. |
| 8101 // Any later failures deopt to the load of the input or earlier. | 8054 // Any later failures deopt to the load of the input or earlier. |
| 8102 HConstant* delta = (expr->op() == Token::INC) | 8055 HConstant* delta = (expr->op() == Token::INC) |
| 8103 ? graph()->GetConstant1() | 8056 ? graph_->GetConstant1() |
| 8104 : graph()->GetConstantMinus1(); | 8057 : graph_->GetConstantMinus1(); |
| 8105 HValue* context = environment()->LookupContext(); | 8058 HValue* context = environment()->LookupContext(); |
| 8106 HInstruction* instr = new(zone()) HAdd(context, Top(), delta); | 8059 HInstruction* instr = new(zone()) HAdd(context, Top(), delta); |
| 8107 // We can't insert a simulate here, because it would break deoptimization, | 8060 // We can't insert a simulate here, because it would break deoptimization, |
| 8108 // so the HAdd must not have side effects, so we must freeze its | 8061 // so the HAdd must not have side effects, so we must freeze its |
| 8109 // representation. | 8062 // representation. |
| 8110 instr->AssumeRepresentation(rep); | 8063 instr->AssumeRepresentation(rep); |
| 8111 instr->ClearAllSideEffects(); | 8064 instr->ClearAllSideEffects(); |
| 8112 AddInstruction(instr); | 8065 AddInstruction(instr); |
| 8113 return instr; | 8066 return instr; |
| 8114 } | 8067 } |
| 8115 | 8068 |
| 8116 | 8069 |
| 8117 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { | 8070 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| 8118 ASSERT(!HasStackOverflow()); | 8071 ASSERT(!HasStackOverflow()); |
| 8119 ASSERT(current_block() != NULL); | 8072 ASSERT(current_block() != NULL); |
| 8120 ASSERT(current_block()->HasPredecessor()); | 8073 ASSERT(current_block()->HasPredecessor()); |
| 8121 Expression* target = expr->expression(); | 8074 Expression* target = expr->expression(); |
| 8122 VariableProxy* proxy = target->AsVariableProxy(); | 8075 VariableProxy* proxy = target->AsVariableProxy(); |
| 8123 Property* prop = target->AsProperty(); | 8076 Property* prop = target->AsProperty(); |
| 8124 if (proxy == NULL && prop == NULL) { | 8077 if (proxy == NULL && prop == NULL) { |
| 8125 return Bailout("invalid lhs in count operation"); | 8078 return Bailout("invalid lhs in count operation"); |
| 8126 } | 8079 } |
| 8127 | 8080 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8191 return Bailout("lookup variable in count operation"); | 8144 return Bailout("lookup variable in count operation"); |
| 8192 } | 8145 } |
| 8193 | 8146 |
| 8194 } else { | 8147 } else { |
| 8195 // Argument of the count operation is a property. | 8148 // Argument of the count operation is a property. |
| 8196 ASSERT(prop != NULL); | 8149 ASSERT(prop != NULL); |
| 8197 prop->RecordTypeFeedback(oracle(), zone()); | 8150 prop->RecordTypeFeedback(oracle(), zone()); |
| 8198 | 8151 |
| 8199 if (prop->key()->IsPropertyName()) { | 8152 if (prop->key()->IsPropertyName()) { |
| 8200 // Named property. | 8153 // Named property. |
| 8201 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 8154 if (returns_original_input) Push(graph_->GetConstantUndefined()); |
| 8202 | 8155 |
| 8203 CHECK_ALIVE(VisitForValue(prop->obj())); | 8156 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 8204 HValue* object = Top(); | 8157 HValue* object = Top(); |
| 8205 | 8158 |
| 8206 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 8159 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 8207 Handle<Map> map; | 8160 Handle<Map> map; |
| 8208 HInstruction* load; | 8161 HInstruction* load; |
| 8209 bool monomorphic = prop->IsMonomorphic(); | 8162 bool monomorphic = prop->IsMonomorphic(); |
| 8210 if (monomorphic) { | 8163 if (monomorphic) { |
| 8211 map = prop->GetReceiverTypes()->first(); | 8164 map = prop->GetReceiverTypes()->first(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8252 // of the operation, and the placeholder with the original value if | 8205 // of the operation, and the placeholder with the original value if |
| 8253 // necessary. | 8206 // necessary. |
| 8254 environment()->SetExpressionStackAt(0, after); | 8207 environment()->SetExpressionStackAt(0, after); |
| 8255 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 8208 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
| 8256 if (store->HasObservableSideEffects()) { | 8209 if (store->HasObservableSideEffects()) { |
| 8257 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 8210 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 8258 } | 8211 } |
| 8259 | 8212 |
| 8260 } else { | 8213 } else { |
| 8261 // Keyed property. | 8214 // Keyed property. |
| 8262 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 8215 if (returns_original_input) Push(graph_->GetConstantUndefined()); |
| 8263 | 8216 |
| 8264 CHECK_ALIVE(VisitForValue(prop->obj())); | 8217 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 8265 CHECK_ALIVE(VisitForValue(prop->key())); | 8218 CHECK_ALIVE(VisitForValue(prop->key())); |
| 8266 HValue* obj = environment()->ExpressionStackAt(1); | 8219 HValue* obj = environment()->ExpressionStackAt(1); |
| 8267 HValue* key = environment()->ExpressionStackAt(0); | 8220 HValue* key = environment()->ExpressionStackAt(0); |
| 8268 | 8221 |
| 8269 bool has_side_effects = false; | 8222 bool has_side_effects = false; |
| 8270 HValue* load = HandleKeyedElementAccess( | 8223 HValue* load = HandleKeyedElementAccess( |
| 8271 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 8224 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
| 8272 false, // is_store | 8225 false, // is_store |
| (...skipping 19 matching lines...) Expand all Loading... |
| 8292 ASSERT(has_side_effects); // Stores always have side effects. | 8245 ASSERT(has_side_effects); // Stores always have side effects. |
| 8293 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 8246 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 8294 } | 8247 } |
| 8295 } | 8248 } |
| 8296 | 8249 |
| 8297 Drop(returns_original_input ? 2 : 1); | 8250 Drop(returns_original_input ? 2 : 1); |
| 8298 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 8251 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
| 8299 } | 8252 } |
| 8300 | 8253 |
| 8301 | 8254 |
| 8302 HStringCharCodeAt* HOptimizedGraphBuilder::BuildStringCharCodeAt( | 8255 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context, |
| 8303 HValue* context, | 8256 HValue* string, |
| 8304 HValue* string, | 8257 HValue* index) { |
| 8305 HValue* index) { | |
| 8306 AddInstruction(new(zone()) HCheckNonSmi(string)); | 8258 AddInstruction(new(zone()) HCheckNonSmi(string)); |
| 8307 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 8259 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
| 8308 HStringLength* length = new(zone()) HStringLength(string); | 8260 HStringLength* length = new(zone()) HStringLength(string); |
| 8309 AddInstruction(length); | 8261 AddInstruction(length); |
| 8310 HInstruction* checked_index = | 8262 HInstruction* checked_index = |
| 8311 AddInstruction(new(zone()) HBoundsCheck(index, length)); | 8263 AddInstruction(new(zone()) HBoundsCheck(index, length)); |
| 8312 return new(zone()) HStringCharCodeAt(context, string, checked_index); | 8264 return new(zone()) HStringCharCodeAt(context, string, checked_index); |
| 8313 } | 8265 } |
| 8314 | 8266 |
| 8315 // Checks if the given shift amounts have form: (sa) and (32 - sa). | 8267 // Checks if the given shift amounts have form: (sa) and (32 - sa). |
| 8316 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, | 8268 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, |
| 8317 HValue* const32_minus_sa) { | 8269 HValue* const32_minus_sa) { |
| 8318 if (!const32_minus_sa->IsSub()) return false; | 8270 if (!const32_minus_sa->IsSub()) return false; |
| 8319 HSub* sub = HSub::cast(const32_minus_sa); | 8271 HSub* sub = HSub::cast(const32_minus_sa); |
| 8320 HValue* const32 = sub->left(); | 8272 HValue* const32 = sub->left(); |
| 8321 if (!const32->IsConstant() || | 8273 if (!const32->IsConstant() || |
| 8322 HConstant::cast(const32)->Integer32Value() != 32) { | 8274 HConstant::cast(const32)->Integer32Value() != 32) { |
| 8323 return false; | 8275 return false; |
| 8324 } | 8276 } |
| 8325 return (sub->right() == sa); | 8277 return (sub->right() == sa); |
| 8326 } | 8278 } |
| 8327 | 8279 |
| 8328 | 8280 |
| 8329 // Checks if the left and the right are shift instructions with the oposite | 8281 // Checks if the left and the right are shift instructions with the oposite |
| 8330 // directions that can be replaced by one rotate right instruction or not. | 8282 // directions that can be replaced by one rotate right instruction or not. |
| 8331 // Returns the operand and the shift amount for the rotate instruction in the | 8283 // Returns the operand and the shift amount for the rotate instruction in the |
| 8332 // former case. | 8284 // former case. |
| 8333 bool HOptimizedGraphBuilder::MatchRotateRight(HValue* left, | 8285 bool HGraphBuilder::MatchRotateRight(HValue* left, |
| 8334 HValue* right, | 8286 HValue* right, |
| 8335 HValue** operand, | 8287 HValue** operand, |
| 8336 HValue** shift_amount) { | 8288 HValue** shift_amount) { |
| 8337 HShl* shl; | 8289 HShl* shl; |
| 8338 HShr* shr; | 8290 HShr* shr; |
| 8339 if (left->IsShl() && right->IsShr()) { | 8291 if (left->IsShl() && right->IsShr()) { |
| 8340 shl = HShl::cast(left); | 8292 shl = HShl::cast(left); |
| 8341 shr = HShr::cast(right); | 8293 shr = HShr::cast(right); |
| 8342 } else if (left->IsShr() && right->IsShl()) { | 8294 } else if (left->IsShr() && right->IsShl()) { |
| 8343 shl = HShl::cast(right); | 8295 shl = HShl::cast(right); |
| 8344 shr = HShr::cast(left); | 8296 shr = HShr::cast(left); |
| 8345 } else { | 8297 } else { |
| 8346 return false; | 8298 return false; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 8361 HConstant* right_const = HConstant::cast(right); | 8313 HConstant* right_const = HConstant::cast(right); |
| 8362 if (right_const->HasInteger32Value() && | 8314 if (right_const->HasInteger32Value() && |
| 8363 (right_const->Integer32Value() & 0x1f) != 0) { | 8315 (right_const->Integer32Value() & 0x1f) != 0) { |
| 8364 return false; | 8316 return false; |
| 8365 } | 8317 } |
| 8366 } | 8318 } |
| 8367 return true; | 8319 return true; |
| 8368 } | 8320 } |
| 8369 | 8321 |
| 8370 | 8322 |
| 8371 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 8323 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, |
| 8372 BinaryOperation* expr, | 8324 HValue* left, |
| 8373 HValue* left, | 8325 HValue* right) { |
| 8374 HValue* right) { | |
| 8375 HValue* context = environment()->LookupContext(); | 8326 HValue* context = environment()->LookupContext(); |
| 8376 TypeInfo left_info, right_info, result_info, combined_info; | 8327 TypeInfo left_info, right_info, result_info, combined_info; |
| 8377 oracle()->BinaryType(expr, &left_info, &right_info, &result_info); | 8328 oracle()->BinaryType(expr, &left_info, &right_info, &result_info); |
| 8378 Representation left_rep = ToRepresentation(left_info); | 8329 Representation left_rep = ToRepresentation(left_info); |
| 8379 Representation right_rep = ToRepresentation(right_info); | 8330 Representation right_rep = ToRepresentation(right_info); |
| 8380 Representation result_rep = ToRepresentation(result_info); | 8331 Representation result_rep = ToRepresentation(result_info); |
| 8381 if (left_info.IsUninitialized()) { | 8332 if (left_info.IsUninitialized()) { |
| 8382 // Can't have initialized one but not the other. | 8333 // Can't have initialized one but not the other. |
| 8383 ASSERT(right_info.IsUninitialized()); | 8334 ASSERT(right_info.IsUninitialized()); |
| 8384 AddInstruction(new(zone()) HSoftDeoptimize); | 8335 AddInstruction(new(zone()) HSoftDeoptimize); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8457 if (call == NULL) return false; | 8408 if (call == NULL) return false; |
| 8458 Literal* literal = expr->right()->AsLiteral(); | 8409 Literal* literal = expr->right()->AsLiteral(); |
| 8459 if (literal == NULL) return false; | 8410 if (literal == NULL) return false; |
| 8460 if (!literal->handle()->IsString()) return false; | 8411 if (!literal->handle()->IsString()) return false; |
| 8461 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; | 8412 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; |
| 8462 ASSERT(call->arguments()->length() == 1); | 8413 ASSERT(call->arguments()->length() == 1); |
| 8463 return true; | 8414 return true; |
| 8464 } | 8415 } |
| 8465 | 8416 |
| 8466 | 8417 |
| 8467 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 8418 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
| 8468 ASSERT(!HasStackOverflow()); | 8419 ASSERT(!HasStackOverflow()); |
| 8469 ASSERT(current_block() != NULL); | 8420 ASSERT(current_block() != NULL); |
| 8470 ASSERT(current_block()->HasPredecessor()); | 8421 ASSERT(current_block()->HasPredecessor()); |
| 8471 switch (expr->op()) { | 8422 switch (expr->op()) { |
| 8472 case Token::COMMA: | 8423 case Token::COMMA: |
| 8473 return VisitComma(expr); | 8424 return VisitComma(expr); |
| 8474 case Token::OR: | 8425 case Token::OR: |
| 8475 case Token::AND: | 8426 case Token::AND: |
| 8476 return VisitLogicalExpression(expr); | 8427 return VisitLogicalExpression(expr); |
| 8477 default: | 8428 default: |
| 8478 return VisitArithmeticExpression(expr); | 8429 return VisitArithmeticExpression(expr); |
| 8479 } | 8430 } |
| 8480 } | 8431 } |
| 8481 | 8432 |
| 8482 | 8433 |
| 8483 void HOptimizedGraphBuilder::VisitComma(BinaryOperation* expr) { | 8434 void HGraphBuilder::VisitComma(BinaryOperation* expr) { |
| 8484 CHECK_ALIVE(VisitForEffect(expr->left())); | 8435 CHECK_ALIVE(VisitForEffect(expr->left())); |
| 8485 // Visit the right subexpression in the same AST context as the entire | 8436 // Visit the right subexpression in the same AST context as the entire |
| 8486 // expression. | 8437 // expression. |
| 8487 Visit(expr->right()); | 8438 Visit(expr->right()); |
| 8488 } | 8439 } |
| 8489 | 8440 |
| 8490 | 8441 |
| 8491 void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { | 8442 void HGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { |
| 8492 bool is_logical_and = expr->op() == Token::AND; | 8443 bool is_logical_and = expr->op() == Token::AND; |
| 8493 if (ast_context()->IsTest()) { | 8444 if (ast_context()->IsTest()) { |
| 8494 TestContext* context = TestContext::cast(ast_context()); | 8445 TestContext* context = TestContext::cast(ast_context()); |
| 8495 // Translate left subexpression. | 8446 // Translate left subexpression. |
| 8496 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 8447 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
| 8497 if (is_logical_and) { | 8448 if (is_logical_and) { |
| 8498 CHECK_BAILOUT(VisitForControl(expr->left(), | 8449 CHECK_BAILOUT(VisitForControl(expr->left(), |
| 8499 eval_right, | 8450 eval_right, |
| 8500 context->if_false())); | 8451 context->if_false())); |
| 8501 } else { | 8452 } else { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8571 | 8522 |
| 8572 HBasicBlock* join_block = | 8523 HBasicBlock* join_block = |
| 8573 CreateJoin(empty_block, right_block, expr->id()); | 8524 CreateJoin(empty_block, right_block, expr->id()); |
| 8574 set_current_block(join_block); | 8525 set_current_block(join_block); |
| 8575 // We did not materialize any value in the predecessor environments, | 8526 // We did not materialize any value in the predecessor environments, |
| 8576 // so there is no need to handle it here. | 8527 // so there is no need to handle it here. |
| 8577 } | 8528 } |
| 8578 } | 8529 } |
| 8579 | 8530 |
| 8580 | 8531 |
| 8581 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { | 8532 void HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { |
| 8582 CHECK_ALIVE(VisitForValue(expr->left())); | 8533 CHECK_ALIVE(VisitForValue(expr->left())); |
| 8583 CHECK_ALIVE(VisitForValue(expr->right())); | 8534 CHECK_ALIVE(VisitForValue(expr->right())); |
| 8584 HValue* right = Pop(); | 8535 HValue* right = Pop(); |
| 8585 HValue* left = Pop(); | 8536 HValue* left = Pop(); |
| 8586 HInstruction* instr = BuildBinaryOperation(expr, left, right); | 8537 HInstruction* instr = BuildBinaryOperation(expr, left, right); |
| 8587 instr->set_position(expr->position()); | 8538 instr->set_position(expr->position()); |
| 8588 return ast_context()->ReturnInstruction(instr, expr->id()); | 8539 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 8589 } | 8540 } |
| 8590 | 8541 |
| 8591 | 8542 |
| 8592 Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) { | 8543 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { |
| 8593 if (info.IsUninitialized()) return Representation::None(); | 8544 if (info.IsUninitialized()) return Representation::None(); |
| 8594 if (info.IsSmi()) return Representation::Integer32(); | 8545 if (info.IsSmi()) return Representation::Integer32(); |
| 8595 if (info.IsInteger32()) return Representation::Integer32(); | 8546 if (info.IsInteger32()) return Representation::Integer32(); |
| 8596 if (info.IsDouble()) return Representation::Double(); | 8547 if (info.IsDouble()) return Representation::Double(); |
| 8597 if (info.IsNumber()) return Representation::Double(); | 8548 if (info.IsNumber()) return Representation::Double(); |
| 8598 return Representation::Tagged(); | 8549 return Representation::Tagged(); |
| 8599 } | 8550 } |
| 8600 | 8551 |
| 8601 | 8552 |
| 8602 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, | 8553 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, |
| 8603 HTypeof* typeof_expr, | 8554 HTypeof* typeof_expr, |
| 8604 Handle<String> check) { | 8555 Handle<String> check) { |
| 8605 // Note: The HTypeof itself is removed during canonicalization, if possible. | 8556 // Note: The HTypeof itself is removed during canonicalization, if possible. |
| 8606 HValue* value = typeof_expr->value(); | 8557 HValue* value = typeof_expr->value(); |
| 8607 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); | 8558 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); |
| 8608 instr->set_position(expr->position()); | 8559 instr->set_position(expr->position()); |
| 8609 return ast_context()->ReturnControl(instr, expr->id()); | 8560 return ast_context()->ReturnControl(instr, expr->id()); |
| 8610 } | 8561 } |
| 8611 | 8562 |
| 8612 | 8563 |
| 8613 static bool MatchLiteralCompareNil(HValue* left, | 8564 static bool MatchLiteralCompareNil(HValue* left, |
| 8614 Token::Value op, | 8565 Token::Value op, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8664 | 8615 |
| 8665 static bool IsLiteralCompareBool(HValue* left, | 8616 static bool IsLiteralCompareBool(HValue* left, |
| 8666 Token::Value op, | 8617 Token::Value op, |
| 8667 HValue* right) { | 8618 HValue* right) { |
| 8668 return op == Token::EQ_STRICT && | 8619 return op == Token::EQ_STRICT && |
| 8669 ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || | 8620 ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || |
| 8670 (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); | 8621 (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); |
| 8671 } | 8622 } |
| 8672 | 8623 |
| 8673 | 8624 |
| 8674 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 8625 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| 8675 ASSERT(!HasStackOverflow()); | 8626 ASSERT(!HasStackOverflow()); |
| 8676 ASSERT(current_block() != NULL); | 8627 ASSERT(current_block() != NULL); |
| 8677 ASSERT(current_block()->HasPredecessor()); | 8628 ASSERT(current_block()->HasPredecessor()); |
| 8678 if (IsClassOfTest(expr)) { | 8629 if (IsClassOfTest(expr)) { |
| 8679 CallRuntime* call = expr->left()->AsCallRuntime(); | 8630 CallRuntime* call = expr->left()->AsCallRuntime(); |
| 8680 ASSERT(call->arguments()->length() == 1); | 8631 ASSERT(call->arguments()->length() == 1); |
| 8681 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8632 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 8682 HValue* value = Pop(); | 8633 HValue* value = Pop(); |
| 8683 Literal* literal = expr->right()->AsLiteral(); | 8634 Literal* literal = expr->right()->AsLiteral(); |
| 8684 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 8635 Handle<String> rhs = Handle<String>::cast(literal->handle()); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8817 HCompareIDAndBranch* result = | 8768 HCompareIDAndBranch* result = |
| 8818 new(zone()) HCompareIDAndBranch(left, right, op); | 8769 new(zone()) HCompareIDAndBranch(left, right, op); |
| 8819 result->set_observed_input_representation(left_rep, right_rep); | 8770 result->set_observed_input_representation(left_rep, right_rep); |
| 8820 result->set_position(expr->position()); | 8771 result->set_position(expr->position()); |
| 8821 return ast_context()->ReturnControl(result, expr->id()); | 8772 return ast_context()->ReturnControl(result, expr->id()); |
| 8822 } | 8773 } |
| 8823 } | 8774 } |
| 8824 } | 8775 } |
| 8825 | 8776 |
| 8826 | 8777 |
| 8827 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 8778 void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
| 8828 HValue* value, | 8779 HValue* value, |
| 8829 NilValue nil) { | 8780 NilValue nil) { |
| 8830 ASSERT(!HasStackOverflow()); | 8781 ASSERT(!HasStackOverflow()); |
| 8831 ASSERT(current_block() != NULL); | 8782 ASSERT(current_block() != NULL); |
| 8832 ASSERT(current_block()->HasPredecessor()); | 8783 ASSERT(current_block()->HasPredecessor()); |
| 8833 EqualityKind kind = | 8784 EqualityKind kind = |
| 8834 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; | 8785 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; |
| 8835 HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil); | 8786 HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil); |
| 8836 instr->set_position(expr->position()); | 8787 instr->set_position(expr->position()); |
| 8837 return ast_context()->ReturnControl(instr, expr->id()); | 8788 return ast_context()->ReturnControl(instr, expr->id()); |
| 8838 } | 8789 } |
| 8839 | 8790 |
| 8840 | 8791 |
| 8841 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 8792 HInstruction* HGraphBuilder::BuildThisFunction() { |
| 8842 // If we share optimized code between different closures, the | 8793 // If we share optimized code between different closures, the |
| 8843 // this-function is not a constant, except inside an inlined body. | 8794 // this-function is not a constant, except inside an inlined body. |
| 8844 if (function_state()->outer() != NULL) { | 8795 if (function_state()->outer() != NULL) { |
| 8845 return new(zone()) HConstant( | 8796 return new(zone()) HConstant( |
| 8846 function_state()->compilation_info()->closure(), | 8797 function_state()->compilation_info()->closure(), |
| 8847 Representation::Tagged()); | 8798 Representation::Tagged()); |
| 8848 } else { | 8799 } else { |
| 8849 return new(zone()) HThisFunction; | 8800 return new(zone()) HThisFunction; |
| 8850 } | 8801 } |
| 8851 } | 8802 } |
| 8852 | 8803 |
| 8853 | 8804 |
| 8854 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 8805 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| 8855 ASSERT(!HasStackOverflow()); | 8806 ASSERT(!HasStackOverflow()); |
| 8856 ASSERT(current_block() != NULL); | 8807 ASSERT(current_block() != NULL); |
| 8857 ASSERT(current_block()->HasPredecessor()); | 8808 ASSERT(current_block()->HasPredecessor()); |
| 8858 HInstruction* instr = BuildThisFunction(); | 8809 HInstruction* instr = BuildThisFunction(); |
| 8859 return ast_context()->ReturnInstruction(instr, expr->id()); | 8810 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 8860 } | 8811 } |
| 8861 | 8812 |
| 8862 | 8813 |
| 8863 void HOptimizedGraphBuilder::VisitDeclarations( | 8814 void HGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) { |
| 8864 ZoneList<Declaration*>* declarations) { | |
| 8865 ASSERT(globals_.is_empty()); | 8815 ASSERT(globals_.is_empty()); |
| 8866 AstVisitor::VisitDeclarations(declarations); | 8816 AstVisitor::VisitDeclarations(declarations); |
| 8867 if (!globals_.is_empty()) { | 8817 if (!globals_.is_empty()) { |
| 8868 Handle<FixedArray> array = | 8818 Handle<FixedArray> array = |
| 8869 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); | 8819 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); |
| 8870 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); | 8820 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); |
| 8871 int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | | 8821 int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | |
| 8872 DeclareGlobalsNativeFlag::encode(info()->is_native()) | | 8822 DeclareGlobalsNativeFlag::encode(info()->is_native()) | |
| 8873 DeclareGlobalsLanguageMode::encode(info()->language_mode()); | 8823 DeclareGlobalsLanguageMode::encode(info()->language_mode()); |
| 8874 HInstruction* result = new(zone()) HDeclareGlobals( | 8824 HInstruction* result = new(zone()) HDeclareGlobals( |
| 8875 environment()->LookupContext(), array, flags); | 8825 environment()->LookupContext(), array, flags); |
| 8876 AddInstruction(result); | 8826 AddInstruction(result); |
| 8877 globals_.Clear(); | 8827 globals_.Clear(); |
| 8878 } | 8828 } |
| 8879 } | 8829 } |
| 8880 | 8830 |
| 8881 | 8831 |
| 8882 void HOptimizedGraphBuilder::VisitVariableDeclaration( | 8832 void HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* declaration) { |
| 8883 VariableDeclaration* declaration) { | |
| 8884 VariableProxy* proxy = declaration->proxy(); | 8833 VariableProxy* proxy = declaration->proxy(); |
| 8885 VariableMode mode = declaration->mode(); | 8834 VariableMode mode = declaration->mode(); |
| 8886 Variable* variable = proxy->var(); | 8835 Variable* variable = proxy->var(); |
| 8887 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; | 8836 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; |
| 8888 switch (variable->location()) { | 8837 switch (variable->location()) { |
| 8889 case Variable::UNALLOCATED: | 8838 case Variable::UNALLOCATED: |
| 8890 globals_.Add(variable->name(), zone()); | 8839 globals_.Add(variable->name(), zone()); |
| 8891 globals_.Add(variable->binding_needs_init() | 8840 globals_.Add(variable->binding_needs_init() |
| 8892 ? isolate()->factory()->the_hole_value() | 8841 ? isolate()->factory()->the_hole_value() |
| 8893 : isolate()->factory()->undefined_value(), zone()); | 8842 : isolate()->factory()->undefined_value(), zone()); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 8910 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8859 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); |
| 8911 } | 8860 } |
| 8912 } | 8861 } |
| 8913 break; | 8862 break; |
| 8914 case Variable::LOOKUP: | 8863 case Variable::LOOKUP: |
| 8915 return Bailout("unsupported lookup slot in declaration"); | 8864 return Bailout("unsupported lookup slot in declaration"); |
| 8916 } | 8865 } |
| 8917 } | 8866 } |
| 8918 | 8867 |
| 8919 | 8868 |
| 8920 void HOptimizedGraphBuilder::VisitFunctionDeclaration( | 8869 void HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* declaration) { |
| 8921 FunctionDeclaration* declaration) { | |
| 8922 VariableProxy* proxy = declaration->proxy(); | 8870 VariableProxy* proxy = declaration->proxy(); |
| 8923 Variable* variable = proxy->var(); | 8871 Variable* variable = proxy->var(); |
| 8924 switch (variable->location()) { | 8872 switch (variable->location()) { |
| 8925 case Variable::UNALLOCATED: { | 8873 case Variable::UNALLOCATED: { |
| 8926 globals_.Add(variable->name(), zone()); | 8874 globals_.Add(variable->name(), zone()); |
| 8927 Handle<SharedFunctionInfo> function = | 8875 Handle<SharedFunctionInfo> function = |
| 8928 Compiler::BuildFunctionInfo(declaration->fun(), info()->script()); | 8876 Compiler::BuildFunctionInfo(declaration->fun(), info()->script()); |
| 8929 // Check for stack-overflow exception. | 8877 // Check for stack-overflow exception. |
| 8930 if (function.is_null()) return SetStackOverflow(); | 8878 if (function.is_null()) return SetStackOverflow(); |
| 8931 globals_.Add(function, zone()); | 8879 globals_.Add(function, zone()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 8949 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); | 8897 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); |
| 8950 } | 8898 } |
| 8951 break; | 8899 break; |
| 8952 } | 8900 } |
| 8953 case Variable::LOOKUP: | 8901 case Variable::LOOKUP: |
| 8954 return Bailout("unsupported lookup slot in declaration"); | 8902 return Bailout("unsupported lookup slot in declaration"); |
| 8955 } | 8903 } |
| 8956 } | 8904 } |
| 8957 | 8905 |
| 8958 | 8906 |
| 8959 void HOptimizedGraphBuilder::VisitModuleDeclaration( | 8907 void HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
| 8960 ModuleDeclaration* declaration) { | |
| 8961 UNREACHABLE(); | 8908 UNREACHABLE(); |
| 8962 } | 8909 } |
| 8963 | 8910 |
| 8964 | 8911 |
| 8965 void HOptimizedGraphBuilder::VisitImportDeclaration( | 8912 void HGraphBuilder::VisitImportDeclaration(ImportDeclaration* declaration) { |
| 8966 ImportDeclaration* declaration) { | |
| 8967 UNREACHABLE(); | 8913 UNREACHABLE(); |
| 8968 } | 8914 } |
| 8969 | 8915 |
| 8970 | 8916 |
| 8971 void HOptimizedGraphBuilder::VisitExportDeclaration( | 8917 void HGraphBuilder::VisitExportDeclaration(ExportDeclaration* declaration) { |
| 8972 ExportDeclaration* declaration) { | |
| 8973 UNREACHABLE(); | 8918 UNREACHABLE(); |
| 8974 } | 8919 } |
| 8975 | 8920 |
| 8976 | 8921 |
| 8977 void HOptimizedGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) { | 8922 void HGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) { |
| 8978 UNREACHABLE(); | 8923 UNREACHABLE(); |
| 8979 } | 8924 } |
| 8980 | 8925 |
| 8981 | 8926 |
| 8982 void HOptimizedGraphBuilder::VisitModuleVariable(ModuleVariable* module) { | 8927 void HGraphBuilder::VisitModuleVariable(ModuleVariable* module) { |
| 8983 UNREACHABLE(); | 8928 UNREACHABLE(); |
| 8984 } | 8929 } |
| 8985 | 8930 |
| 8986 | 8931 |
| 8987 void HOptimizedGraphBuilder::VisitModulePath(ModulePath* module) { | 8932 void HGraphBuilder::VisitModulePath(ModulePath* module) { |
| 8988 UNREACHABLE(); | 8933 UNREACHABLE(); |
| 8989 } | 8934 } |
| 8990 | 8935 |
| 8991 | 8936 |
| 8992 void HOptimizedGraphBuilder::VisitModuleUrl(ModuleUrl* module) { | 8937 void HGraphBuilder::VisitModuleUrl(ModuleUrl* module) { |
| 8993 UNREACHABLE(); | 8938 UNREACHABLE(); |
| 8994 } | 8939 } |
| 8995 | 8940 |
| 8996 | 8941 |
| 8997 void HOptimizedGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { | 8942 void HGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { |
| 8998 UNREACHABLE(); | 8943 UNREACHABLE(); |
| 8999 } | 8944 } |
| 9000 | 8945 |
| 9001 | 8946 |
| 9002 // Generators for inline runtime functions. | 8947 // Generators for inline runtime functions. |
| 9003 // Support for types. | 8948 // Support for types. |
| 9004 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) { | 8949 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { |
| 9005 ASSERT(call->arguments()->length() == 1); | 8950 ASSERT(call->arguments()->length() == 1); |
| 9006 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8951 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9007 HValue* value = Pop(); | 8952 HValue* value = Pop(); |
| 9008 HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value); | 8953 HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value); |
| 9009 return ast_context()->ReturnControl(result, call->id()); | 8954 return ast_context()->ReturnControl(result, call->id()); |
| 9010 } | 8955 } |
| 9011 | 8956 |
| 9012 | 8957 |
| 9013 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { | 8958 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { |
| 9014 ASSERT(call->arguments()->length() == 1); | 8959 ASSERT(call->arguments()->length() == 1); |
| 9015 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8960 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9016 HValue* value = Pop(); | 8961 HValue* value = Pop(); |
| 9017 HHasInstanceTypeAndBranch* result = | 8962 HHasInstanceTypeAndBranch* result = |
| 9018 new(zone()) HHasInstanceTypeAndBranch(value, | 8963 new(zone()) HHasInstanceTypeAndBranch(value, |
| 9019 FIRST_SPEC_OBJECT_TYPE, | 8964 FIRST_SPEC_OBJECT_TYPE, |
| 9020 LAST_SPEC_OBJECT_TYPE); | 8965 LAST_SPEC_OBJECT_TYPE); |
| 9021 return ast_context()->ReturnControl(result, call->id()); | 8966 return ast_context()->ReturnControl(result, call->id()); |
| 9022 } | 8967 } |
| 9023 | 8968 |
| 9024 | 8969 |
| 9025 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) { | 8970 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { |
| 9026 ASSERT(call->arguments()->length() == 1); | 8971 ASSERT(call->arguments()->length() == 1); |
| 9027 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8972 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9028 HValue* value = Pop(); | 8973 HValue* value = Pop(); |
| 9029 HHasInstanceTypeAndBranch* result = | 8974 HHasInstanceTypeAndBranch* result = |
| 9030 new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE); | 8975 new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_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::GenerateHasCachedArrayIndex(CallRuntime* call) { | 8980 void HGraphBuilder::GenerateHasCachedArrayIndex(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 HHasCachedArrayIndexAndBranch* result = | 8984 HHasCachedArrayIndexAndBranch* result = |
| 9040 new(zone()) HHasCachedArrayIndexAndBranch(value); | 8985 new(zone()) HHasCachedArrayIndexAndBranch(value); |
| 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::GenerateIsArray(CallRuntime* call) { | 8990 void HGraphBuilder::GenerateIsArray(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 HHasInstanceTypeAndBranch* result = | 8994 HHasInstanceTypeAndBranch* result = |
| 9050 new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE); | 8995 new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE); |
| 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::GenerateIsRegExp(CallRuntime* call) { | 9000 void HGraphBuilder::GenerateIsRegExp(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_REGEXP_TYPE); | 9005 new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_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::GenerateIsObject(CallRuntime* call) { | 9010 void HGraphBuilder::GenerateIsObject(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 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); | 9014 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); |
| 9070 return ast_context()->ReturnControl(result, call->id()); | 9015 return ast_context()->ReturnControl(result, call->id()); |
| 9071 } | 9016 } |
| 9072 | 9017 |
| 9073 | 9018 |
| 9074 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { | 9019 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { |
| 9075 return Bailout("inlined runtime function: IsNonNegativeSmi"); | 9020 return Bailout("inlined runtime function: IsNonNegativeSmi"); |
| 9076 } | 9021 } |
| 9077 | 9022 |
| 9078 | 9023 |
| 9079 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { | 9024 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { |
| 9080 ASSERT(call->arguments()->length() == 1); | 9025 ASSERT(call->arguments()->length() == 1); |
| 9081 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9026 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9082 HValue* value = Pop(); | 9027 HValue* value = Pop(); |
| 9083 HIsUndetectableAndBranch* result = | 9028 HIsUndetectableAndBranch* result = |
| 9084 new(zone()) HIsUndetectableAndBranch(value); | 9029 new(zone()) HIsUndetectableAndBranch(value); |
| 9085 return ast_context()->ReturnControl(result, call->id()); | 9030 return ast_context()->ReturnControl(result, call->id()); |
| 9086 } | 9031 } |
| 9087 | 9032 |
| 9088 | 9033 |
| 9089 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( | 9034 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( |
| 9090 CallRuntime* call) { | 9035 CallRuntime* call) { |
| 9091 return Bailout( | 9036 return Bailout( |
| 9092 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); | 9037 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); |
| 9093 } | 9038 } |
| 9094 | 9039 |
| 9095 | 9040 |
| 9096 // Support for construct call checks. | 9041 // Support for construct call checks. |
| 9097 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { | 9042 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { |
| 9098 ASSERT(call->arguments()->length() == 0); | 9043 ASSERT(call->arguments()->length() == 0); |
| 9099 if (function_state()->outer() != NULL) { | 9044 if (function_state()->outer() != NULL) { |
| 9100 // We are generating graph for inlined function. | 9045 // We are generating graph for inlined function. |
| 9101 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN | 9046 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN |
| 9102 ? graph()->GetConstantTrue() | 9047 ? graph()->GetConstantTrue() |
| 9103 : graph()->GetConstantFalse(); | 9048 : graph()->GetConstantFalse(); |
| 9104 return ast_context()->ReturnValue(value); | 9049 return ast_context()->ReturnValue(value); |
| 9105 } else { | 9050 } else { |
| 9106 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, | 9051 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, |
| 9107 call->id()); | 9052 call->id()); |
| 9108 } | 9053 } |
| 9109 } | 9054 } |
| 9110 | 9055 |
| 9111 | 9056 |
| 9112 // Support for arguments.length and arguments[?]. | 9057 // Support for arguments.length and arguments[?]. |
| 9113 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { | 9058 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { |
| 9114 // Our implementation of arguments (based on this stack frame or an | 9059 // Our implementation of arguments (based on this stack frame or an |
| 9115 // adapter below it) does not work for inlined functions. This runtime | 9060 // adapter below it) does not work for inlined functions. This runtime |
| 9116 // function is blacklisted by AstNode::IsInlineable. | 9061 // function is blacklisted by AstNode::IsInlineable. |
| 9117 ASSERT(function_state()->outer() == NULL); | 9062 ASSERT(function_state()->outer() == NULL); |
| 9118 ASSERT(call->arguments()->length() == 0); | 9063 ASSERT(call->arguments()->length() == 0); |
| 9119 HInstruction* elements = AddInstruction( | 9064 HInstruction* elements = AddInstruction( |
| 9120 new(zone()) HArgumentsElements(false)); | 9065 new(zone()) HArgumentsElements(false)); |
| 9121 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); | 9066 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); |
| 9122 return ast_context()->ReturnInstruction(result, call->id()); | 9067 return ast_context()->ReturnInstruction(result, call->id()); |
| 9123 } | 9068 } |
| 9124 | 9069 |
| 9125 | 9070 |
| 9126 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { | 9071 void HGraphBuilder::GenerateArguments(CallRuntime* call) { |
| 9127 // Our implementation of arguments (based on this stack frame or an | 9072 // Our implementation of arguments (based on this stack frame or an |
| 9128 // adapter below it) does not work for inlined functions. This runtime | 9073 // adapter below it) does not work for inlined functions. This runtime |
| 9129 // function is blacklisted by AstNode::IsInlineable. | 9074 // function is blacklisted by AstNode::IsInlineable. |
| 9130 ASSERT(function_state()->outer() == NULL); | 9075 ASSERT(function_state()->outer() == NULL); |
| 9131 ASSERT(call->arguments()->length() == 1); | 9076 ASSERT(call->arguments()->length() == 1); |
| 9132 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9077 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9133 HValue* index = Pop(); | 9078 HValue* index = Pop(); |
| 9134 HInstruction* elements = AddInstruction( | 9079 HInstruction* elements = AddInstruction( |
| 9135 new(zone()) HArgumentsElements(false)); | 9080 new(zone()) HArgumentsElements(false)); |
| 9136 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); | 9081 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
| 9137 HInstruction* checked_index = | 9082 HInstruction* checked_index = |
| 9138 AddInstruction(new(zone()) HBoundsCheck(index, length)); | 9083 AddInstruction(new(zone()) HBoundsCheck(index, length)); |
| 9139 HAccessArgumentsAt* result = | 9084 HAccessArgumentsAt* result = |
| 9140 new(zone()) HAccessArgumentsAt(elements, length, checked_index); | 9085 new(zone()) HAccessArgumentsAt(elements, length, checked_index); |
| 9141 return ast_context()->ReturnInstruction(result, call->id()); | 9086 return ast_context()->ReturnInstruction(result, call->id()); |
| 9142 } | 9087 } |
| 9143 | 9088 |
| 9144 | 9089 |
| 9145 // Support for accessing the class and value fields of an object. | 9090 // Support for accessing the class and value fields of an object. |
| 9146 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { | 9091 void HGraphBuilder::GenerateClassOf(CallRuntime* call) { |
| 9147 // The special form detected by IsClassOfTest is detected before we get here | 9092 // The special form detected by IsClassOfTest is detected before we get here |
| 9148 // and does not cause a bailout. | 9093 // and does not cause a bailout. |
| 9149 return Bailout("inlined runtime function: ClassOf"); | 9094 return Bailout("inlined runtime function: ClassOf"); |
| 9150 } | 9095 } |
| 9151 | 9096 |
| 9152 | 9097 |
| 9153 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) { | 9098 void HGraphBuilder::GenerateValueOf(CallRuntime* call) { |
| 9154 ASSERT(call->arguments()->length() == 1); | 9099 ASSERT(call->arguments()->length() == 1); |
| 9155 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9100 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9156 HValue* value = Pop(); | 9101 HValue* value = Pop(); |
| 9157 HValueOf* result = new(zone()) HValueOf(value); | 9102 HValueOf* result = new(zone()) HValueOf(value); |
| 9158 return ast_context()->ReturnInstruction(result, call->id()); | 9103 return ast_context()->ReturnInstruction(result, call->id()); |
| 9159 } | 9104 } |
| 9160 | 9105 |
| 9161 | 9106 |
| 9162 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) { | 9107 void HGraphBuilder::GenerateDateField(CallRuntime* call) { |
| 9163 ASSERT(call->arguments()->length() == 2); | 9108 ASSERT(call->arguments()->length() == 2); |
| 9164 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); | 9109 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); |
| 9165 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle())); | 9110 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle())); |
| 9166 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9111 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9167 HValue* date = Pop(); | 9112 HValue* date = Pop(); |
| 9168 HDateField* result = new(zone()) HDateField(date, index); | 9113 HDateField* result = new(zone()) HDateField(date, index); |
| 9169 return ast_context()->ReturnInstruction(result, call->id()); | 9114 return ast_context()->ReturnInstruction(result, call->id()); |
| 9170 } | 9115 } |
| 9171 | 9116 |
| 9172 | 9117 |
| 9173 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar( | 9118 void HGraphBuilder::GenerateOneByteSeqStringSetChar( |
| 9174 CallRuntime* call) { | 9119 CallRuntime* call) { |
| 9175 ASSERT(call->arguments()->length() == 3); | 9120 ASSERT(call->arguments()->length() == 3); |
| 9176 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9121 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9177 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9122 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9178 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); | 9123 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); |
| 9179 HValue* value = Pop(); | 9124 HValue* value = Pop(); |
| 9180 HValue* index = Pop(); | 9125 HValue* index = Pop(); |
| 9181 HValue* string = Pop(); | 9126 HValue* string = Pop(); |
| 9182 HSeqStringSetChar* result = new(zone()) HSeqStringSetChar( | 9127 HSeqStringSetChar* result = new(zone()) HSeqStringSetChar( |
| 9183 String::ONE_BYTE_ENCODING, string, index, value); | 9128 String::ONE_BYTE_ENCODING, string, index, value); |
| 9184 return ast_context()->ReturnInstruction(result, call->id()); | 9129 return ast_context()->ReturnInstruction(result, call->id()); |
| 9185 } | 9130 } |
| 9186 | 9131 |
| 9187 | 9132 |
| 9188 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar( | 9133 void HGraphBuilder::GenerateTwoByteSeqStringSetChar( |
| 9189 CallRuntime* call) { | 9134 CallRuntime* call) { |
| 9190 ASSERT(call->arguments()->length() == 3); | 9135 ASSERT(call->arguments()->length() == 3); |
| 9191 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9136 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9192 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9137 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9193 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); | 9138 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); |
| 9194 HValue* value = Pop(); | 9139 HValue* value = Pop(); |
| 9195 HValue* index = Pop(); | 9140 HValue* index = Pop(); |
| 9196 HValue* string = Pop(); | 9141 HValue* string = Pop(); |
| 9197 HValue* context = environment()->LookupContext(); | 9142 HValue* context = environment()->LookupContext(); |
| 9198 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index); | 9143 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index); |
| 9199 AddInstruction(char_code); | 9144 AddInstruction(char_code); |
| 9200 HSeqStringSetChar* result = new(zone()) HSeqStringSetChar( | 9145 HSeqStringSetChar* result = new(zone()) HSeqStringSetChar( |
| 9201 String::TWO_BYTE_ENCODING, string, index, value); | 9146 String::TWO_BYTE_ENCODING, string, index, value); |
| 9202 return ast_context()->ReturnInstruction(result, call->id()); | 9147 return ast_context()->ReturnInstruction(result, call->id()); |
| 9203 } | 9148 } |
| 9204 | 9149 |
| 9205 | 9150 |
| 9206 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { | 9151 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { |
| 9207 ASSERT(call->arguments()->length() == 2); | 9152 ASSERT(call->arguments()->length() == 2); |
| 9208 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9153 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9209 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9154 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9210 HValue* value = Pop(); | 9155 HValue* value = Pop(); |
| 9211 HValue* object = Pop(); | 9156 HValue* object = Pop(); |
| 9212 // Check if object is a not a smi. | 9157 // Check if object is a not a smi. |
| 9213 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(object); | 9158 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(object); |
| 9214 HBasicBlock* if_smi = graph()->CreateBasicBlock(); | 9159 HBasicBlock* if_smi = graph()->CreateBasicBlock(); |
| 9215 HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); | 9160 HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); |
| 9216 HBasicBlock* join = graph()->CreateBasicBlock(); | 9161 HBasicBlock* join = graph()->CreateBasicBlock(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 9239 true, // in-object store. | 9184 true, // in-object store. |
| 9240 JSValue::kValueOffset)); | 9185 JSValue::kValueOffset)); |
| 9241 if_js_value->Goto(join); | 9186 if_js_value->Goto(join); |
| 9242 join->SetJoinId(call->id()); | 9187 join->SetJoinId(call->id()); |
| 9243 set_current_block(join); | 9188 set_current_block(join); |
| 9244 return ast_context()->ReturnValue(value); | 9189 return ast_context()->ReturnValue(value); |
| 9245 } | 9190 } |
| 9246 | 9191 |
| 9247 | 9192 |
| 9248 // Fast support for charCodeAt(n). | 9193 // Fast support for charCodeAt(n). |
| 9249 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 9194 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
| 9250 ASSERT(call->arguments()->length() == 2); | 9195 ASSERT(call->arguments()->length() == 2); |
| 9251 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9196 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9252 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9197 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9253 HValue* index = Pop(); | 9198 HValue* index = Pop(); |
| 9254 HValue* string = Pop(); | 9199 HValue* string = Pop(); |
| 9255 HValue* context = environment()->LookupContext(); | 9200 HValue* context = environment()->LookupContext(); |
| 9256 HStringCharCodeAt* result = BuildStringCharCodeAt(context, string, index); | 9201 HStringCharCodeAt* result = BuildStringCharCodeAt(context, string, index); |
| 9257 return ast_context()->ReturnInstruction(result, call->id()); | 9202 return ast_context()->ReturnInstruction(result, call->id()); |
| 9258 } | 9203 } |
| 9259 | 9204 |
| 9260 | 9205 |
| 9261 // Fast support for string.charAt(n) and string[n]. | 9206 // Fast support for string.charAt(n) and string[n]. |
| 9262 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { | 9207 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { |
| 9263 ASSERT(call->arguments()->length() == 1); | 9208 ASSERT(call->arguments()->length() == 1); |
| 9264 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9209 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9265 HValue* char_code = Pop(); | 9210 HValue* char_code = Pop(); |
| 9266 HValue* context = environment()->LookupContext(); | 9211 HValue* context = environment()->LookupContext(); |
| 9267 HStringCharFromCode* result = | 9212 HStringCharFromCode* result = |
| 9268 new(zone()) HStringCharFromCode(context, char_code); | 9213 new(zone()) HStringCharFromCode(context, char_code); |
| 9269 return ast_context()->ReturnInstruction(result, call->id()); | 9214 return ast_context()->ReturnInstruction(result, call->id()); |
| 9270 } | 9215 } |
| 9271 | 9216 |
| 9272 | 9217 |
| 9273 // Fast support for string.charAt(n) and string[n]. | 9218 // Fast support for string.charAt(n) and string[n]. |
| 9274 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) { | 9219 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { |
| 9275 ASSERT(call->arguments()->length() == 2); | 9220 ASSERT(call->arguments()->length() == 2); |
| 9276 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9221 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9277 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9222 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9278 HValue* index = Pop(); | 9223 HValue* index = Pop(); |
| 9279 HValue* string = Pop(); | 9224 HValue* string = Pop(); |
| 9280 HValue* context = environment()->LookupContext(); | 9225 HValue* context = environment()->LookupContext(); |
| 9281 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index); | 9226 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index); |
| 9282 AddInstruction(char_code); | 9227 AddInstruction(char_code); |
| 9283 HStringCharFromCode* result = | 9228 HStringCharFromCode* result = |
| 9284 new(zone()) HStringCharFromCode(context, char_code); | 9229 new(zone()) HStringCharFromCode(context, char_code); |
| 9285 return ast_context()->ReturnInstruction(result, call->id()); | 9230 return ast_context()->ReturnInstruction(result, call->id()); |
| 9286 } | 9231 } |
| 9287 | 9232 |
| 9288 | 9233 |
| 9289 // Fast support for object equality testing. | 9234 // Fast support for object equality testing. |
| 9290 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) { | 9235 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { |
| 9291 ASSERT(call->arguments()->length() == 2); | 9236 ASSERT(call->arguments()->length() == 2); |
| 9292 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9237 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9293 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9238 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9294 HValue* right = Pop(); | 9239 HValue* right = Pop(); |
| 9295 HValue* left = Pop(); | 9240 HValue* left = Pop(); |
| 9296 HCompareObjectEqAndBranch* result = | 9241 HCompareObjectEqAndBranch* result = |
| 9297 new(zone()) HCompareObjectEqAndBranch(left, right); | 9242 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 9298 return ast_context()->ReturnControl(result, call->id()); | 9243 return ast_context()->ReturnControl(result, call->id()); |
| 9299 } | 9244 } |
| 9300 | 9245 |
| 9301 | 9246 |
| 9302 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { | 9247 void HGraphBuilder::GenerateLog(CallRuntime* call) { |
| 9303 // %_Log is ignored in optimized code. | 9248 // %_Log is ignored in optimized code. |
| 9304 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 9249 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
| 9305 } | 9250 } |
| 9306 | 9251 |
| 9307 | 9252 |
| 9308 // Fast support for Math.random(). | 9253 // Fast support for Math.random(). |
| 9309 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { | 9254 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { |
| 9310 HValue* context = environment()->LookupContext(); | 9255 HValue* context = environment()->LookupContext(); |
| 9311 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 9256 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 9312 AddInstruction(global_object); | 9257 AddInstruction(global_object); |
| 9313 HRandom* result = new(zone()) HRandom(global_object); | 9258 HRandom* result = new(zone()) HRandom(global_object); |
| 9314 return ast_context()->ReturnInstruction(result, call->id()); | 9259 return ast_context()->ReturnInstruction(result, call->id()); |
| 9315 } | 9260 } |
| 9316 | 9261 |
| 9317 | 9262 |
| 9318 // Fast support for StringAdd. | 9263 // Fast support for StringAdd. |
| 9319 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 9264 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
| 9320 ASSERT_EQ(2, call->arguments()->length()); | 9265 ASSERT_EQ(2, call->arguments()->length()); |
| 9321 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9266 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9322 HValue* context = environment()->LookupContext(); | 9267 HValue* context = environment()->LookupContext(); |
| 9323 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); | 9268 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 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 // Fast support for SubString. | 9274 // Fast support for SubString. |
| 9330 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 9275 void HGraphBuilder::GenerateSubString(CallRuntime* call) { |
| 9331 ASSERT_EQ(3, call->arguments()->length()); | 9276 ASSERT_EQ(3, 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::SubString, 3); | 9279 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); |
| 9335 Drop(3); | 9280 Drop(3); |
| 9336 return ast_context()->ReturnInstruction(result, call->id()); | 9281 return ast_context()->ReturnInstruction(result, call->id()); |
| 9337 } | 9282 } |
| 9338 | 9283 |
| 9339 | 9284 |
| 9340 // Fast support for StringCompare. | 9285 // Fast support for StringCompare. |
| 9341 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { | 9286 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
| 9342 ASSERT_EQ(2, call->arguments()->length()); | 9287 ASSERT_EQ(2, 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::StringCompare, 2); | 9291 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); |
| 9347 Drop(2); | 9292 Drop(2); |
| 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 direct calls from JavaScript to native RegExp code. | 9297 // Support for direct calls from JavaScript to native RegExp code. |
| 9353 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { | 9298 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
| 9354 ASSERT_EQ(4, call->arguments()->length()); | 9299 ASSERT_EQ(4, call->arguments()->length()); |
| 9355 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9300 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9356 HValue* context = environment()->LookupContext(); | 9301 HValue* context = environment()->LookupContext(); |
| 9357 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); | 9302 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); |
| 9358 Drop(4); | 9303 Drop(4); |
| 9359 return ast_context()->ReturnInstruction(result, call->id()); | 9304 return ast_context()->ReturnInstruction(result, call->id()); |
| 9360 } | 9305 } |
| 9361 | 9306 |
| 9362 | 9307 |
| 9363 // Construct a RegExp exec result with two in-object properties. | 9308 // Construct a RegExp exec result with two in-object properties. |
| 9364 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { | 9309 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
| 9365 ASSERT_EQ(3, call->arguments()->length()); | 9310 ASSERT_EQ(3, call->arguments()->length()); |
| 9366 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9311 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9367 HValue* context = environment()->LookupContext(); | 9312 HValue* context = environment()->LookupContext(); |
| 9368 HCallStub* result = | 9313 HCallStub* result = |
| 9369 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); | 9314 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); |
| 9370 Drop(3); | 9315 Drop(3); |
| 9371 return ast_context()->ReturnInstruction(result, call->id()); | 9316 return ast_context()->ReturnInstruction(result, call->id()); |
| 9372 } | 9317 } |
| 9373 | 9318 |
| 9374 | 9319 |
| 9375 // Support for fast native caches. | 9320 // Support for fast native caches. |
| 9376 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 9321 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
| 9377 return Bailout("inlined runtime function: GetFromCache"); | 9322 return Bailout("inlined runtime function: GetFromCache"); |
| 9378 } | 9323 } |
| 9379 | 9324 |
| 9380 | 9325 |
| 9381 // Fast support for number to string. | 9326 // Fast support for number to string. |
| 9382 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 9327 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
| 9383 ASSERT_EQ(1, call->arguments()->length()); | 9328 ASSERT_EQ(1, call->arguments()->length()); |
| 9384 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9329 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9385 HValue* context = environment()->LookupContext(); | 9330 HValue* context = environment()->LookupContext(); |
| 9386 HCallStub* result = | 9331 HCallStub* result = |
| 9387 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); | 9332 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); |
| 9388 Drop(1); | 9333 Drop(1); |
| 9389 return ast_context()->ReturnInstruction(result, call->id()); | 9334 return ast_context()->ReturnInstruction(result, call->id()); |
| 9390 } | 9335 } |
| 9391 | 9336 |
| 9392 | 9337 |
| 9393 // Fast call for custom callbacks. | 9338 // Fast call for custom callbacks. |
| 9394 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 9339 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
| 9395 // 1 ~ The function to call is not itself an argument to the call. | 9340 // 1 ~ The function to call is not itself an argument to the call. |
| 9396 int arg_count = call->arguments()->length() - 1; | 9341 int arg_count = call->arguments()->length() - 1; |
| 9397 ASSERT(arg_count >= 1); // There's always at least a receiver. | 9342 ASSERT(arg_count >= 1); // There's always at least a receiver. |
| 9398 | 9343 |
| 9399 for (int i = 0; i < arg_count; ++i) { | 9344 for (int i = 0; i < arg_count; ++i) { |
| 9400 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); | 9345 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); |
| 9401 } | 9346 } |
| 9402 CHECK_ALIVE(VisitForValue(call->arguments()->last())); | 9347 CHECK_ALIVE(VisitForValue(call->arguments()->last())); |
| 9403 | 9348 |
| 9404 HValue* function = Pop(); | 9349 HValue* function = Pop(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 9428 Push(call_result); | 9373 Push(call_result); |
| 9429 if_nonfunction->Goto(join); | 9374 if_nonfunction->Goto(join); |
| 9430 | 9375 |
| 9431 set_current_block(join); | 9376 set_current_block(join); |
| 9432 join->SetJoinId(call->id()); | 9377 join->SetJoinId(call->id()); |
| 9433 return ast_context()->ReturnValue(Pop()); | 9378 return ast_context()->ReturnValue(Pop()); |
| 9434 } | 9379 } |
| 9435 | 9380 |
| 9436 | 9381 |
| 9437 // Fast call to math functions. | 9382 // Fast call to math functions. |
| 9438 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { | 9383 void HGraphBuilder::GenerateMathPow(CallRuntime* call) { |
| 9439 ASSERT_EQ(2, call->arguments()->length()); | 9384 ASSERT_EQ(2, call->arguments()->length()); |
| 9440 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9385 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9441 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9386 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9442 HValue* right = Pop(); | 9387 HValue* right = Pop(); |
| 9443 HValue* left = Pop(); | 9388 HValue* left = Pop(); |
| 9444 HPower* result = new(zone()) HPower(left, right); | 9389 HPower* result = new(zone()) HPower(left, right); |
| 9445 return ast_context()->ReturnInstruction(result, call->id()); | 9390 return ast_context()->ReturnInstruction(result, call->id()); |
| 9446 } | 9391 } |
| 9447 | 9392 |
| 9448 | 9393 |
| 9449 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) { | 9394 void HGraphBuilder::GenerateMathSin(CallRuntime* call) { |
| 9450 ASSERT_EQ(1, call->arguments()->length()); | 9395 ASSERT_EQ(1, call->arguments()->length()); |
| 9451 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9396 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9452 HValue* context = environment()->LookupContext(); | 9397 HValue* context = environment()->LookupContext(); |
| 9453 HCallStub* result = | 9398 HCallStub* result = |
| 9454 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9399 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| 9455 result->set_transcendental_type(TranscendentalCache::SIN); | 9400 result->set_transcendental_type(TranscendentalCache::SIN); |
| 9456 Drop(1); | 9401 Drop(1); |
| 9457 return ast_context()->ReturnInstruction(result, call->id()); | 9402 return ast_context()->ReturnInstruction(result, call->id()); |
| 9458 } | 9403 } |
| 9459 | 9404 |
| 9460 | 9405 |
| 9461 void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) { | 9406 void HGraphBuilder::GenerateMathCos(CallRuntime* call) { |
| 9462 ASSERT_EQ(1, call->arguments()->length()); | 9407 ASSERT_EQ(1, call->arguments()->length()); |
| 9463 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9408 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9464 HValue* context = environment()->LookupContext(); | 9409 HValue* context = environment()->LookupContext(); |
| 9465 HCallStub* result = | 9410 HCallStub* result = |
| 9466 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9411 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| 9467 result->set_transcendental_type(TranscendentalCache::COS); | 9412 result->set_transcendental_type(TranscendentalCache::COS); |
| 9468 Drop(1); | 9413 Drop(1); |
| 9469 return ast_context()->ReturnInstruction(result, call->id()); | 9414 return ast_context()->ReturnInstruction(result, call->id()); |
| 9470 } | 9415 } |
| 9471 | 9416 |
| 9472 | 9417 |
| 9473 void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) { | 9418 void HGraphBuilder::GenerateMathTan(CallRuntime* call) { |
| 9474 ASSERT_EQ(1, call->arguments()->length()); | 9419 ASSERT_EQ(1, call->arguments()->length()); |
| 9475 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9420 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9476 HValue* context = environment()->LookupContext(); | 9421 HValue* context = environment()->LookupContext(); |
| 9477 HCallStub* result = | 9422 HCallStub* result = |
| 9478 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9423 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| 9479 result->set_transcendental_type(TranscendentalCache::TAN); | 9424 result->set_transcendental_type(TranscendentalCache::TAN); |
| 9480 Drop(1); | 9425 Drop(1); |
| 9481 return ast_context()->ReturnInstruction(result, call->id()); | 9426 return ast_context()->ReturnInstruction(result, call->id()); |
| 9482 } | 9427 } |
| 9483 | 9428 |
| 9484 | 9429 |
| 9485 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) { | 9430 void HGraphBuilder::GenerateMathLog(CallRuntime* call) { |
| 9486 ASSERT_EQ(1, call->arguments()->length()); | 9431 ASSERT_EQ(1, call->arguments()->length()); |
| 9487 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9432 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9488 HValue* context = environment()->LookupContext(); | 9433 HValue* context = environment()->LookupContext(); |
| 9489 HCallStub* result = | 9434 HCallStub* result = |
| 9490 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9435 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| 9491 result->set_transcendental_type(TranscendentalCache::LOG); | 9436 result->set_transcendental_type(TranscendentalCache::LOG); |
| 9492 Drop(1); | 9437 Drop(1); |
| 9493 return ast_context()->ReturnInstruction(result, call->id()); | 9438 return ast_context()->ReturnInstruction(result, call->id()); |
| 9494 } | 9439 } |
| 9495 | 9440 |
| 9496 | 9441 |
| 9497 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { | 9442 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
| 9498 return Bailout("inlined runtime function: MathSqrt"); | 9443 return Bailout("inlined runtime function: MathSqrt"); |
| 9499 } | 9444 } |
| 9500 | 9445 |
| 9501 | 9446 |
| 9502 // Check whether two RegExps are equivalent | 9447 // Check whether two RegExps are equivalent |
| 9503 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { | 9448 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
| 9504 return Bailout("inlined runtime function: IsRegExpEquivalent"); | 9449 return Bailout("inlined runtime function: IsRegExpEquivalent"); |
| 9505 } | 9450 } |
| 9506 | 9451 |
| 9507 | 9452 |
| 9508 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { | 9453 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { |
| 9509 ASSERT(call->arguments()->length() == 1); | 9454 ASSERT(call->arguments()->length() == 1); |
| 9510 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9455 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9511 HValue* value = Pop(); | 9456 HValue* value = Pop(); |
| 9512 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); | 9457 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); |
| 9513 return ast_context()->ReturnInstruction(result, call->id()); | 9458 return ast_context()->ReturnInstruction(result, call->id()); |
| 9514 } | 9459 } |
| 9515 | 9460 |
| 9516 | 9461 |
| 9517 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { | 9462 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { |
| 9518 return Bailout("inlined runtime function: FastAsciiArrayJoin"); | 9463 return Bailout("inlined runtime function: FastAsciiArrayJoin"); |
| 9519 } | 9464 } |
| 9520 | 9465 |
| 9521 | 9466 |
| 9522 #undef CHECK_BAILOUT | 9467 #undef CHECK_BAILOUT |
| 9523 #undef CHECK_ALIVE | 9468 #undef CHECK_ALIVE |
| 9524 | 9469 |
| 9525 | 9470 |
| 9526 HEnvironment::HEnvironment(HEnvironment* outer, | 9471 HEnvironment::HEnvironment(HEnvironment* outer, |
| 9527 Scope* scope, | 9472 Scope* scope, |
| 9528 Handle<JSFunction> closure, | 9473 Handle<JSFunction> closure, |
| 9529 Zone* zone) | 9474 Zone* zone) |
| 9530 : closure_(closure), | 9475 : closure_(closure), |
| 9531 values_(0, zone), | 9476 values_(0, zone), |
| 9532 assigned_variables_(4, zone), | 9477 assigned_variables_(4, zone), |
| 9533 frame_type_(JS_FUNCTION), | 9478 frame_type_(JS_FUNCTION), |
| 9534 parameter_count_(0), | 9479 parameter_count_(0), |
| 9535 specials_count_(1), | 9480 specials_count_(1), |
| 9536 local_count_(0), | 9481 local_count_(0), |
| 9537 outer_(outer), | 9482 outer_(outer), |
| 9538 entry_(NULL), | 9483 entry_(NULL), |
| 9539 pop_count_(0), | 9484 pop_count_(0), |
| 9540 push_count_(0), | 9485 push_count_(0), |
| 9541 ast_id_(BailoutId::None()), | 9486 ast_id_(BailoutId::None()), |
| 9542 zone_(zone) { | 9487 zone_(zone) { |
| 9543 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); | 9488 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); |
| 9544 } | 9489 } |
| 9545 | 9490 |
| 9546 | 9491 |
| 9547 HEnvironment::HEnvironment(Zone* zone) | |
| 9548 : values_(0, zone), | |
| 9549 assigned_variables_(0, zone), | |
| 9550 frame_type_(STUB), | |
| 9551 parameter_count_(0), | |
| 9552 specials_count_(0), | |
| 9553 local_count_(0), | |
| 9554 outer_(NULL), | |
| 9555 entry_(NULL), | |
| 9556 pop_count_(0), | |
| 9557 push_count_(0), | |
| 9558 ast_id_(BailoutId::None()), | |
| 9559 zone_(zone) { | |
| 9560 Initialize(0, 0, 0); | |
| 9561 } | |
| 9562 | |
| 9563 | |
| 9564 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone) | 9492 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone) |
| 9565 : values_(0, zone), | 9493 : values_(0, zone), |
| 9566 assigned_variables_(0, zone), | 9494 assigned_variables_(0, zone), |
| 9567 frame_type_(JS_FUNCTION), | 9495 frame_type_(JS_FUNCTION), |
| 9568 parameter_count_(0), | 9496 parameter_count_(0), |
| 9569 specials_count_(1), | 9497 specials_count_(1), |
| 9570 local_count_(0), | 9498 local_count_(0), |
| 9571 outer_(NULL), | 9499 outer_(NULL), |
| 9572 entry_(NULL), | 9500 entry_(NULL), |
| 9573 pop_count_(0), | 9501 pop_count_(0), |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9821 | 9749 |
| 9822 | 9750 |
| 9823 void HEnvironment::PrintToStd() { | 9751 void HEnvironment::PrintToStd() { |
| 9824 HeapStringAllocator string_allocator; | 9752 HeapStringAllocator string_allocator; |
| 9825 StringStream trace(&string_allocator); | 9753 StringStream trace(&string_allocator); |
| 9826 PrintTo(&trace); | 9754 PrintTo(&trace); |
| 9827 PrintF("%s", *trace.ToCString()); | 9755 PrintF("%s", *trace.ToCString()); |
| 9828 } | 9756 } |
| 9829 | 9757 |
| 9830 | 9758 |
| 9831 void HTracer::TraceCompilation(CompilationInfo* info) { | 9759 void HTracer::TraceCompilation(FunctionLiteral* function) { |
| 9832 Tag tag(this, "compilation"); | 9760 Tag tag(this, "compilation"); |
| 9833 if (info->IsOptimizing()) { | 9761 Handle<String> name = function->debug_name(); |
| 9834 Handle<String> name = info->function()->debug_name(); | 9762 PrintStringProperty("name", *name->ToCString()); |
| 9835 PrintStringProperty("name", *name->ToCString()); | 9763 PrintStringProperty("method", *name->ToCString()); |
| 9836 PrintStringProperty("method", *name->ToCString()); | |
| 9837 } else { | |
| 9838 CodeStub::Major major_key = info->code_stub()->MajorKey(); | |
| 9839 PrintStringProperty("name", CodeStub::MajorName(major_key, false)); | |
| 9840 PrintStringProperty("method", "stub"); | |
| 9841 } | |
| 9842 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); | 9764 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); |
| 9843 } | 9765 } |
| 9844 | 9766 |
| 9845 | 9767 |
| 9846 void HTracer::TraceLithium(const char* name, LChunk* chunk) { | 9768 void HTracer::TraceLithium(const char* name, LChunk* chunk) { |
| 9847 Trace(name, chunk->graph(), chunk); | 9769 Trace(name, chunk->graph(), chunk); |
| 9848 } | 9770 } |
| 9849 | 9771 |
| 9850 | 9772 |
| 9851 void HTracer::TraceHydrogen(const char* name, HGraph* graph) { | 9773 void HTracer::TraceHydrogen(const char* name, HGraph* graph) { |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10160 } | 10082 } |
| 10161 } | 10083 } |
| 10162 | 10084 |
| 10163 #ifdef DEBUG | 10085 #ifdef DEBUG |
| 10164 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 10086 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 10165 if (allocator_ != NULL) allocator_->Verify(); | 10087 if (allocator_ != NULL) allocator_->Verify(); |
| 10166 #endif | 10088 #endif |
| 10167 } | 10089 } |
| 10168 | 10090 |
| 10169 } } // namespace v8::internal | 10091 } } // namespace v8::internal |
| OLD | NEW |