OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 939 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 increment_ = HAdd::New(zone(), context_, phi_, one); | 950 increment_ = HAdd::New(zone(), context_, phi_, one); |
951 } else { | 951 } else { |
952 increment_ = HSub::New(zone(), context_, phi_, one); | 952 increment_ = HSub::New(zone(), context_, phi_, one); |
953 } | 953 } |
954 increment_->ClearFlag(HValue::kCanOverflow); | 954 increment_->ClearFlag(HValue::kCanOverflow); |
955 builder_->AddInstruction(increment_); | 955 builder_->AddInstruction(increment_); |
956 } | 956 } |
957 | 957 |
958 // Push the new increment value on the expression stack to merge into the phi. | 958 // Push the new increment value on the expression stack to merge into the phi. |
959 builder_->environment()->Push(increment_); | 959 builder_->environment()->Push(increment_); |
960 HBasicBlock* last_block = builder_->current_block(); | 960 builder_->current_block()->GotoNoSimulate(header_block_); |
961 last_block->GotoNoSimulate(header_block_); | 961 header_block_->loop_information()->RegisterBackEdge(body_block_); |
962 header_block_->loop_information()->RegisterBackEdge(last_block); | |
963 | 962 |
964 builder_->set_current_block(exit_block_); | 963 builder_->set_current_block(exit_block_); |
965 // Pop the phi from the expression stack | 964 // Pop the phi from the expression stack |
966 builder_->environment()->Pop(); | 965 builder_->environment()->Pop(); |
967 finished_ = true; | 966 finished_ = true; |
968 } | 967 } |
969 | 968 |
970 | 969 |
971 HGraph* HGraphBuilder::CreateGraph() { | 970 HGraph* HGraphBuilder::CreateGraph() { |
972 graph_ = new(zone()) HGraph(info_); | 971 graph_ = new(zone()) HGraph(info_); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1043 current_block()->Goto(continuation); | 1042 current_block()->Goto(continuation); |
1044 } | 1043 } |
1045 } | 1044 } |
1046 | 1045 |
1047 | 1046 |
1048 void HGraphBuilder::PadEnvironmentForContinuation( | 1047 void HGraphBuilder::PadEnvironmentForContinuation( |
1049 HBasicBlock* from, | 1048 HBasicBlock* from, |
1050 HBasicBlock* continuation) { | 1049 HBasicBlock* continuation) { |
1051 if (continuation->last_environment() != NULL) { | 1050 if (continuation->last_environment() != NULL) { |
1052 // When merging from a deopt block to a continuation, resolve differences in | 1051 // When merging from a deopt block to a continuation, resolve differences in |
1053 // environment by pushing constant 0 and popping extra values so that the | 1052 // environment by pushing undefined and popping extra values so that the |
1054 // environments match during the join. Push 0 since it has the most specific | 1053 // environments match during the join. |
1055 // representation, and will not influence representation inference of the | |
1056 // phi. | |
1057 int continuation_env_length = continuation->last_environment()->length(); | 1054 int continuation_env_length = continuation->last_environment()->length(); |
1058 while (continuation_env_length != from->last_environment()->length()) { | 1055 while (continuation_env_length != from->last_environment()->length()) { |
1059 if (continuation_env_length > from->last_environment()->length()) { | 1056 if (continuation_env_length > from->last_environment()->length()) { |
1060 from->last_environment()->Push(graph()->GetConstant0()); | 1057 from->last_environment()->Push(graph()->GetConstantUndefined()); |
1061 } else { | 1058 } else { |
1062 from->last_environment()->Pop(); | 1059 from->last_environment()->Pop(); |
1063 } | 1060 } |
1064 } | 1061 } |
1065 } else { | 1062 } else { |
1066 ASSERT(continuation->predecessors()->length() == 0); | 1063 ASSERT(continuation->predecessors()->length() == 0); |
1067 } | 1064 } |
1068 } | 1065 } |
1069 | 1066 |
1070 | 1067 |
(...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1712 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant, | 1709 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant, |
1713 static_cast<HValue*>(NULL), kind); | 1710 static_cast<HValue*>(NULL), kind); |
1714 Add<HStoreKeyed>(object_elements, key_constant, value, kind); | 1711 Add<HStoreKeyed>(object_elements, key_constant, value, kind); |
1715 } | 1712 } |
1716 } | 1713 } |
1717 | 1714 |
1718 return object; | 1715 return object; |
1719 } | 1716 } |
1720 | 1717 |
1721 | 1718 |
| 1719 HInstruction* HGraphBuilder::BuildUnaryMathOp( |
| 1720 HValue* input, Handle<Type> type, Token::Value operation) { |
| 1721 // We only handle the numeric cases here |
| 1722 type = handle( |
| 1723 Type::Intersect(type, handle(Type::Number(), isolate())), isolate()); |
| 1724 |
| 1725 switch (operation) { |
| 1726 default: |
| 1727 UNREACHABLE(); |
| 1728 case Token::SUB: { |
| 1729 HInstruction* instr = |
| 1730 NewUncasted<HMul>(input, graph()->GetConstantMinus1()); |
| 1731 Representation rep = Representation::FromType(type); |
| 1732 if (type->Is(Type::None())) { |
| 1733 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 1734 } |
| 1735 if (instr->IsBinaryOperation()) { |
| 1736 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
| 1737 binop->set_observed_input_representation(1, rep); |
| 1738 binop->set_observed_input_representation(2, rep); |
| 1739 } |
| 1740 return instr; |
| 1741 } |
| 1742 case Token::BIT_NOT: |
| 1743 if (type->Is(Type::None())) { |
| 1744 Add<HDeoptimize>(Deoptimizer::SOFT); |
| 1745 } |
| 1746 return New<HBitNot>(input); |
| 1747 } |
| 1748 } |
| 1749 |
| 1750 |
1722 void HGraphBuilder::BuildCompareNil( | 1751 void HGraphBuilder::BuildCompareNil( |
1723 HValue* value, | 1752 HValue* value, |
1724 Handle<Type> type, | 1753 Handle<Type> type, |
1725 int position, | 1754 int position, |
1726 HIfContinuation* continuation) { | 1755 HIfContinuation* continuation) { |
1727 IfBuilder if_nil(this, position); | 1756 IfBuilder if_nil(this, position); |
1728 bool needs_or = false; | 1757 bool needs_or = false; |
1729 if (type->Maybe(Type::Null())) { | 1758 if (type->Maybe(Type::Null())) { |
1730 if (needs_or) if_nil.Or(); | 1759 if (needs_or) if_nil.Or(); |
1731 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); | 1760 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); |
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2542 | 2571 |
2543 void EffectContext::ReturnValue(HValue* value) { | 2572 void EffectContext::ReturnValue(HValue* value) { |
2544 // The value is simply ignored. | 2573 // The value is simply ignored. |
2545 } | 2574 } |
2546 | 2575 |
2547 | 2576 |
2548 void ValueContext::ReturnValue(HValue* value) { | 2577 void ValueContext::ReturnValue(HValue* value) { |
2549 // The value is tracked in the bailout environment, and communicated | 2578 // The value is tracked in the bailout environment, and communicated |
2550 // through the environment as the result of the expression. | 2579 // through the environment as the result of the expression. |
2551 if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) { | 2580 if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) { |
2552 owner()->Bailout(kBadValueContextForArgumentsValue); | 2581 owner()->Bailout("bad value context for arguments value"); |
2553 } | 2582 } |
2554 owner()->Push(value); | 2583 owner()->Push(value); |
2555 } | 2584 } |
2556 | 2585 |
2557 | 2586 |
2558 void TestContext::ReturnValue(HValue* value) { | 2587 void TestContext::ReturnValue(HValue* value) { |
2559 BuildBranch(value); | 2588 BuildBranch(value); |
2560 } | 2589 } |
2561 | 2590 |
2562 | 2591 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2594 } else { | 2623 } else { |
2595 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id); | 2624 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id); |
2596 owner()->set_current_block(join); | 2625 owner()->set_current_block(join); |
2597 } | 2626 } |
2598 } | 2627 } |
2599 | 2628 |
2600 | 2629 |
2601 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2630 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
2602 ASSERT(!instr->IsControlInstruction()); | 2631 ASSERT(!instr->IsControlInstruction()); |
2603 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2632 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
2604 return owner()->Bailout(kBadValueContextForArgumentsObjectValue); | 2633 return owner()->Bailout("bad value context for arguments object value"); |
2605 } | 2634 } |
2606 owner()->AddInstruction(instr); | 2635 owner()->AddInstruction(instr); |
2607 owner()->Push(instr); | 2636 owner()->Push(instr); |
2608 if (instr->HasObservableSideEffects()) { | 2637 if (instr->HasObservableSideEffects()) { |
2609 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 2638 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
2610 } | 2639 } |
2611 } | 2640 } |
2612 | 2641 |
2613 | 2642 |
2614 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 2643 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
2615 ASSERT(!instr->HasObservableSideEffects()); | 2644 ASSERT(!instr->HasObservableSideEffects()); |
2616 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2645 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
2617 return owner()->Bailout(kBadValueContextForArgumentsObjectValue); | 2646 return owner()->Bailout("bad value context for arguments object value"); |
2618 } | 2647 } |
2619 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); | 2648 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); |
2620 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); | 2649 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); |
2621 instr->SetSuccessorAt(0, materialize_true); | 2650 instr->SetSuccessorAt(0, materialize_true); |
2622 instr->SetSuccessorAt(1, materialize_false); | 2651 instr->SetSuccessorAt(1, materialize_false); |
2623 owner()->current_block()->Finish(instr); | 2652 owner()->current_block()->Finish(instr); |
2624 owner()->set_current_block(materialize_true); | 2653 owner()->set_current_block(materialize_true); |
2625 owner()->Push(owner()->graph()->GetConstantTrue()); | 2654 owner()->Push(owner()->graph()->GetConstantTrue()); |
2626 owner()->set_current_block(materialize_false); | 2655 owner()->set_current_block(materialize_false); |
2627 owner()->Push(owner()->graph()->GetConstantFalse()); | 2656 owner()->Push(owner()->graph()->GetConstantFalse()); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2697 } | 2726 } |
2698 | 2727 |
2699 | 2728 |
2700 void TestContext::BuildBranch(HValue* value) { | 2729 void TestContext::BuildBranch(HValue* value) { |
2701 // We expect the graph to be in edge-split form: there is no edge that | 2730 // We expect the graph to be in edge-split form: there is no edge that |
2702 // connects a branch node to a join node. We conservatively ensure that | 2731 // connects a branch node to a join node. We conservatively ensure that |
2703 // property by always adding an empty block on the outgoing edges of this | 2732 // property by always adding an empty block on the outgoing edges of this |
2704 // branch. | 2733 // branch. |
2705 HOptimizedGraphBuilder* builder = owner(); | 2734 HOptimizedGraphBuilder* builder = owner(); |
2706 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { | 2735 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { |
2707 builder->Bailout(kArgumentsObjectValueInATestContext); | 2736 builder->Bailout("arguments object value in a test context"); |
2708 } | 2737 } |
2709 if (value->IsConstant()) { | 2738 if (value->IsConstant()) { |
2710 HConstant* constant_value = HConstant::cast(value); | 2739 HConstant* constant_value = HConstant::cast(value); |
2711 if (constant_value->BooleanValue()) { | 2740 if (constant_value->BooleanValue()) { |
2712 builder->current_block()->Goto(if_true(), builder->function_state()); | 2741 builder->current_block()->Goto(if_true(), builder->function_state()); |
2713 } else { | 2742 } else { |
2714 builder->current_block()->Goto(if_false(), builder->function_state()); | 2743 builder->current_block()->Goto(if_false(), builder->function_state()); |
2715 } | 2744 } |
2716 builder->set_current_block(NULL); | 2745 builder->set_current_block(NULL); |
2717 return; | 2746 return; |
(...skipping 25 matching lines...) Expand all Loading... |
2743 } while (false) | 2772 } while (false) |
2744 | 2773 |
2745 | 2774 |
2746 #define CHECK_ALIVE_OR_RETURN(call, value) \ | 2775 #define CHECK_ALIVE_OR_RETURN(call, value) \ |
2747 do { \ | 2776 do { \ |
2748 call; \ | 2777 call; \ |
2749 if (HasStackOverflow() || current_block() == NULL) return value; \ | 2778 if (HasStackOverflow() || current_block() == NULL) return value; \ |
2750 } while (false) | 2779 } while (false) |
2751 | 2780 |
2752 | 2781 |
2753 void HOptimizedGraphBuilder::Bailout(BailoutReason reason) { | 2782 void HOptimizedGraphBuilder::Bailout(const char* reason) { |
2754 current_info()->set_bailout_reason(reason); | 2783 current_info()->set_bailout_reason(reason); |
2755 SetStackOverflow(); | 2784 SetStackOverflow(); |
2756 } | 2785 } |
2757 | 2786 |
2758 | 2787 |
2759 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { | 2788 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { |
2760 EffectContext for_effect(this); | 2789 EffectContext for_effect(this); |
2761 Visit(expr); | 2790 Visit(expr); |
2762 } | 2791 } |
2763 | 2792 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2802 void HOptimizedGraphBuilder::VisitExpressions( | 2831 void HOptimizedGraphBuilder::VisitExpressions( |
2803 ZoneList<Expression*>* exprs) { | 2832 ZoneList<Expression*>* exprs) { |
2804 for (int i = 0; i < exprs->length(); ++i) { | 2833 for (int i = 0; i < exprs->length(); ++i) { |
2805 CHECK_ALIVE(VisitForValue(exprs->at(i))); | 2834 CHECK_ALIVE(VisitForValue(exprs->at(i))); |
2806 } | 2835 } |
2807 } | 2836 } |
2808 | 2837 |
2809 | 2838 |
2810 bool HOptimizedGraphBuilder::BuildGraph() { | 2839 bool HOptimizedGraphBuilder::BuildGraph() { |
2811 if (current_info()->function()->is_generator()) { | 2840 if (current_info()->function()->is_generator()) { |
2812 Bailout(kFunctionIsAGenerator); | 2841 Bailout("function is a generator"); |
2813 return false; | 2842 return false; |
2814 } | 2843 } |
2815 Scope* scope = current_info()->scope(); | 2844 Scope* scope = current_info()->scope(); |
2816 if (scope->HasIllegalRedeclaration()) { | 2845 if (scope->HasIllegalRedeclaration()) { |
2817 Bailout(kFunctionWithIllegalRedeclaration); | 2846 Bailout("function with illegal redeclaration"); |
2818 return false; | 2847 return false; |
2819 } | 2848 } |
2820 if (scope->calls_eval()) { | 2849 if (scope->calls_eval()) { |
2821 Bailout(kFunctionCallsEval); | 2850 Bailout("function calls eval"); |
2822 return false; | 2851 return false; |
2823 } | 2852 } |
2824 SetUpScope(scope); | 2853 SetUpScope(scope); |
2825 | 2854 |
2826 // Add an edge to the body entry. This is warty: the graph's start | 2855 // Add an edge to the body entry. This is warty: the graph's start |
2827 // environment will be used by the Lithium translation as the initial | 2856 // environment will be used by the Lithium translation as the initial |
2828 // environment on graph entry, but it has now been mutated by the | 2857 // environment on graph entry, but it has now been mutated by the |
2829 // Hydrogen translation of the instructions in the start block. This | 2858 // Hydrogen translation of the instructions in the start block. This |
2830 // environment uses values which have not been defined yet. These | 2859 // environment uses values which have not been defined yet. These |
2831 // Hydrogen instructions will then be replayed by the Lithium | 2860 // Hydrogen instructions will then be replayed by the Lithium |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2877 !type_info->matches_inlined_type_change_checksum(composite_checksum)); | 2906 !type_info->matches_inlined_type_change_checksum(composite_checksum)); |
2878 type_info->set_inlined_type_change_checksum(composite_checksum); | 2907 type_info->set_inlined_type_change_checksum(composite_checksum); |
2879 | 2908 |
2880 // Perform any necessary OSR-specific cleanups or changes to the graph. | 2909 // Perform any necessary OSR-specific cleanups or changes to the graph. |
2881 osr_->FinishGraph(); | 2910 osr_->FinishGraph(); |
2882 | 2911 |
2883 return true; | 2912 return true; |
2884 } | 2913 } |
2885 | 2914 |
2886 | 2915 |
2887 bool HGraph::Optimize(BailoutReason* bailout_reason) { | 2916 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { |
| 2917 *bailout_reason = SmartArrayPointer<char>(); |
2888 OrderBlocks(); | 2918 OrderBlocks(); |
2889 AssignDominators(); | 2919 AssignDominators(); |
2890 | 2920 |
2891 // We need to create a HConstant "zero" now so that GVN will fold every | 2921 // We need to create a HConstant "zero" now so that GVN will fold every |
2892 // zero-valued constant in the graph together. | 2922 // zero-valued constant in the graph together. |
2893 // The constant is needed to make idef-based bounds check work: the pass | 2923 // The constant is needed to make idef-based bounds check work: the pass |
2894 // evaluates relations with "zero" and that zero cannot be created after GVN. | 2924 // evaluates relations with "zero" and that zero cannot be created after GVN. |
2895 GetConstant0(); | 2925 GetConstant0(); |
2896 | 2926 |
2897 #ifdef DEBUG | 2927 #ifdef DEBUG |
2898 // Do a full verify after building the graph and computing dominators. | 2928 // Do a full verify after building the graph and computing dominators. |
2899 Verify(true); | 2929 Verify(true); |
2900 #endif | 2930 #endif |
2901 | 2931 |
2902 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) { | 2932 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) { |
2903 Run<HEnvironmentLivenessAnalysisPhase>(); | 2933 Run<HEnvironmentLivenessAnalysisPhase>(); |
2904 } | 2934 } |
2905 | 2935 |
2906 Run<HPropagateDeoptimizingMarkPhase>(); | 2936 Run<HPropagateDeoptimizingMarkPhase>(); |
2907 if (!CheckConstPhiUses()) { | 2937 if (!CheckConstPhiUses()) { |
2908 *bailout_reason = kUnsupportedPhiUseOfConstVariable; | 2938 *bailout_reason = SmartArrayPointer<char>(StrDup( |
| 2939 "Unsupported phi use of const variable")); |
2909 return false; | 2940 return false; |
2910 } | 2941 } |
2911 Run<HRedundantPhiEliminationPhase>(); | 2942 Run<HRedundantPhiEliminationPhase>(); |
2912 if (!CheckArgumentsPhiUses()) { | 2943 if (!CheckArgumentsPhiUses()) { |
2913 *bailout_reason = kUnsupportedPhiUseOfArguments; | 2944 *bailout_reason = SmartArrayPointer<char>(StrDup( |
| 2945 "Unsupported phi use of arguments")); |
2914 return false; | 2946 return false; |
2915 } | 2947 } |
2916 | 2948 |
2917 // Remove dead code and phis | 2949 // Remove dead code and phis |
2918 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); | 2950 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); |
2919 CollectPhis(); | 2951 CollectPhis(); |
2920 | 2952 |
2921 if (has_osr()) osr()->FinishOsrValues(); | 2953 if (has_osr()) osr()->FinishOsrValues(); |
2922 | 2954 |
2923 Run<HInferRepresentationPhase>(); | 2955 Run<HInferRepresentationPhase>(); |
(...skipping 19 matching lines...) Expand all Loading... |
2943 | 2975 |
2944 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); | 2976 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); |
2945 | 2977 |
2946 if (FLAG_use_range) Run<HRangeAnalysisPhase>(); | 2978 if (FLAG_use_range) Run<HRangeAnalysisPhase>(); |
2947 | 2979 |
2948 Run<HComputeMinusZeroChecksPhase>(); | 2980 Run<HComputeMinusZeroChecksPhase>(); |
2949 | 2981 |
2950 // Eliminate redundant stack checks on backwards branches. | 2982 // Eliminate redundant stack checks on backwards branches. |
2951 Run<HStackCheckEliminationPhase>(); | 2983 Run<HStackCheckEliminationPhase>(); |
2952 | 2984 |
2953 if (FLAG_array_bounds_checks_elimination) { | 2985 if (FLAG_idefs) SetupInformativeDefinitions(); |
| 2986 if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) { |
2954 Run<HBoundsCheckEliminationPhase>(); | 2987 Run<HBoundsCheckEliminationPhase>(); |
2955 } | 2988 } |
2956 if (FLAG_array_bounds_checks_hoisting) { | 2989 if (FLAG_array_bounds_checks_hoisting && !FLAG_idefs) { |
2957 Run<HBoundsCheckHoistingPhase>(); | 2990 Run<HBoundsCheckHoistingPhase>(); |
2958 } | 2991 } |
2959 if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>(); | 2992 if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>(); |
2960 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); | 2993 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); |
2961 | 2994 |
2962 RestoreActualValues(); | 2995 RestoreActualValues(); |
2963 | 2996 |
2964 return true; | 2997 return true; |
2965 } | 2998 } |
2966 | 2999 |
2967 | 3000 |
| 3001 void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) { |
| 3002 for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) { |
| 3003 HPhi* phi = block->phis()->at(phi_index); |
| 3004 phi->AddInformativeDefinitions(); |
| 3005 phi->SetFlag(HValue::kIDefsProcessingDone); |
| 3006 // We do not support phis that "redefine just one operand". |
| 3007 ASSERT(!phi->IsInformativeDefinition()); |
| 3008 } |
| 3009 |
| 3010 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 3011 HInstruction* i = it.Current(); |
| 3012 i->AddInformativeDefinitions(); |
| 3013 i->SetFlag(HValue::kIDefsProcessingDone); |
| 3014 i->UpdateRedefinedUsesWhileSettingUpInformativeDefinitions(); |
| 3015 } |
| 3016 } |
| 3017 |
| 3018 |
| 3019 // This method is recursive, so if its stack frame is large it could |
| 3020 // cause a stack overflow. |
| 3021 // To keep the individual stack frames small we do the actual work inside |
| 3022 // SetupInformativeDefinitionsInBlock(); |
| 3023 void HGraph::SetupInformativeDefinitionsRecursively(HBasicBlock* block) { |
| 3024 SetupInformativeDefinitionsInBlock(block); |
| 3025 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { |
| 3026 SetupInformativeDefinitionsRecursively(block->dominated_blocks()->at(i)); |
| 3027 } |
| 3028 |
| 3029 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 3030 HInstruction* i = it.Current(); |
| 3031 if (i->IsBoundsCheck()) { |
| 3032 HBoundsCheck* check = HBoundsCheck::cast(i); |
| 3033 check->ApplyIndexChange(); |
| 3034 } |
| 3035 } |
| 3036 } |
| 3037 |
| 3038 |
| 3039 void HGraph::SetupInformativeDefinitions() { |
| 3040 HPhase phase("H_Setup informative definitions", this); |
| 3041 SetupInformativeDefinitionsRecursively(entry_block()); |
| 3042 } |
| 3043 |
| 3044 |
2968 void HGraph::RestoreActualValues() { | 3045 void HGraph::RestoreActualValues() { |
2969 HPhase phase("H_Restore actual values", this); | 3046 HPhase phase("H_Restore actual values", this); |
2970 | 3047 |
2971 for (int block_index = 0; block_index < blocks()->length(); block_index++) { | 3048 for (int block_index = 0; block_index < blocks()->length(); block_index++) { |
2972 HBasicBlock* block = blocks()->at(block_index); | 3049 HBasicBlock* block = blocks()->at(block_index); |
2973 | 3050 |
2974 #ifdef DEBUG | 3051 #ifdef DEBUG |
2975 for (int i = 0; i < block->phis()->length(); i++) { | 3052 for (int i = 0; i < block->phis()->length(); i++) { |
2976 HPhi* phi = block->phis()->at(i); | 3053 HPhi* phi = block->phis()->at(i); |
2977 ASSERT(phi->ActualValue() == phi); | 3054 ASSERT(phi->ActualValue() == phi); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3040 for (int i = environment()->parameter_count() + 1; | 3117 for (int i = environment()->parameter_count() + 1; |
3041 i < environment()->length(); | 3118 i < environment()->length(); |
3042 ++i) { | 3119 ++i) { |
3043 environment()->Bind(i, undefined_constant); | 3120 environment()->Bind(i, undefined_constant); |
3044 } | 3121 } |
3045 | 3122 |
3046 // Handle the arguments and arguments shadow variables specially (they do | 3123 // Handle the arguments and arguments shadow variables specially (they do |
3047 // not have declarations). | 3124 // not have declarations). |
3048 if (scope->arguments() != NULL) { | 3125 if (scope->arguments() != NULL) { |
3049 if (!scope->arguments()->IsStackAllocated()) { | 3126 if (!scope->arguments()->IsStackAllocated()) { |
3050 return Bailout(kContextAllocatedArguments); | 3127 return Bailout("context-allocated arguments"); |
3051 } | 3128 } |
3052 | 3129 |
3053 environment()->Bind(scope->arguments(), | 3130 environment()->Bind(scope->arguments(), |
3054 graph()->GetArgumentsObject()); | 3131 graph()->GetArgumentsObject()); |
3055 } | 3132 } |
3056 } | 3133 } |
3057 | 3134 |
3058 | 3135 |
3059 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { | 3136 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { |
3060 for (int i = 0; i < statements->length(); i++) { | 3137 for (int i = 0; i < statements->length(); i++) { |
3061 CHECK_ALIVE(Visit(statements->at(i))); | 3138 CHECK_ALIVE(Visit(statements->at(i))); |
3062 } | 3139 } |
3063 } | 3140 } |
3064 | 3141 |
3065 | 3142 |
3066 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) { | 3143 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) { |
3067 ASSERT(!HasStackOverflow()); | 3144 ASSERT(!HasStackOverflow()); |
3068 ASSERT(current_block() != NULL); | 3145 ASSERT(current_block() != NULL); |
3069 ASSERT(current_block()->HasPredecessor()); | 3146 ASSERT(current_block()->HasPredecessor()); |
3070 if (stmt->scope() != NULL) { | 3147 if (stmt->scope() != NULL) { |
3071 return Bailout(kScopedBlock); | 3148 return Bailout("ScopedBlock"); |
3072 } | 3149 } |
3073 BreakAndContinueInfo break_info(stmt); | 3150 BreakAndContinueInfo break_info(stmt); |
3074 { BreakAndContinueScope push(&break_info, this); | 3151 { BreakAndContinueScope push(&break_info, this); |
3075 CHECK_BAILOUT(VisitStatements(stmt->statements())); | 3152 CHECK_BAILOUT(VisitStatements(stmt->statements())); |
3076 } | 3153 } |
3077 HBasicBlock* break_block = break_info.break_block(); | 3154 HBasicBlock* break_block = break_info.break_block(); |
3078 if (break_block != NULL) { | 3155 if (break_block != NULL) { |
3079 if (current_block() != NULL) current_block()->Goto(break_block); | 3156 if (current_block() != NULL) current_block()->Goto(break_block); |
3080 break_block->SetJoinId(stmt->ExitId()); | 3157 break_block->SetJoinId(stmt->ExitId()); |
3081 set_current_block(break_block); | 3158 set_current_block(break_block); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3273 } | 3350 } |
3274 } | 3351 } |
3275 set_current_block(NULL); | 3352 set_current_block(NULL); |
3276 } | 3353 } |
3277 | 3354 |
3278 | 3355 |
3279 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { | 3356 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { |
3280 ASSERT(!HasStackOverflow()); | 3357 ASSERT(!HasStackOverflow()); |
3281 ASSERT(current_block() != NULL); | 3358 ASSERT(current_block() != NULL); |
3282 ASSERT(current_block()->HasPredecessor()); | 3359 ASSERT(current_block()->HasPredecessor()); |
3283 return Bailout(kWithStatement); | 3360 return Bailout("WithStatement"); |
3284 } | 3361 } |
3285 | 3362 |
3286 | 3363 |
3287 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 3364 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
3288 ASSERT(!HasStackOverflow()); | 3365 ASSERT(!HasStackOverflow()); |
3289 ASSERT(current_block() != NULL); | 3366 ASSERT(current_block() != NULL); |
3290 ASSERT(current_block()->HasPredecessor()); | 3367 ASSERT(current_block()->HasPredecessor()); |
3291 | 3368 |
3292 // We only optimize switch statements with smi-literal smi comparisons, | 3369 // We only optimize switch statements with smi-literal smi comparisons, |
3293 // with a bounded number of clauses. | 3370 // with a bounded number of clauses. |
3294 const int kCaseClauseLimit = 128; | 3371 const int kCaseClauseLimit = 128; |
3295 ZoneList<CaseClause*>* clauses = stmt->cases(); | 3372 ZoneList<CaseClause*>* clauses = stmt->cases(); |
3296 int clause_count = clauses->length(); | 3373 int clause_count = clauses->length(); |
3297 if (clause_count > kCaseClauseLimit) { | 3374 if (clause_count > kCaseClauseLimit) { |
3298 return Bailout(kSwitchStatementTooManyClauses); | 3375 return Bailout("SwitchStatement: too many clauses"); |
3299 } | 3376 } |
3300 | 3377 |
3301 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); | 3378 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); |
3302 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { | 3379 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { |
3303 return Bailout(kSwitchStatementMixedOrNonLiteralSwitchLabels); | 3380 return Bailout("SwitchStatement: mixed or non-literal switch labels"); |
3304 } | 3381 } |
3305 | 3382 |
3306 HValue* context = environment()->context(); | 3383 HValue* context = environment()->context(); |
3307 | 3384 |
3308 CHECK_ALIVE(VisitForValue(stmt->tag())); | 3385 CHECK_ALIVE(VisitForValue(stmt->tag())); |
3309 Add<HSimulate>(stmt->EntryId()); | 3386 Add<HSimulate>(stmt->EntryId()); |
3310 HValue* tag_value = Pop(); | 3387 HValue* tag_value = Pop(); |
3311 HBasicBlock* first_test_block = current_block(); | 3388 HBasicBlock* first_test_block = current_block(); |
3312 | 3389 |
3313 HUnaryControlInstruction* string_check = NULL; | 3390 HUnaryControlInstruction* string_check = NULL; |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3585 set_current_block(loop_exit); | 3662 set_current_block(loop_exit); |
3586 } | 3663 } |
3587 | 3664 |
3588 | 3665 |
3589 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 3666 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
3590 ASSERT(!HasStackOverflow()); | 3667 ASSERT(!HasStackOverflow()); |
3591 ASSERT(current_block() != NULL); | 3668 ASSERT(current_block() != NULL); |
3592 ASSERT(current_block()->HasPredecessor()); | 3669 ASSERT(current_block()->HasPredecessor()); |
3593 | 3670 |
3594 if (!FLAG_optimize_for_in) { | 3671 if (!FLAG_optimize_for_in) { |
3595 return Bailout(kForInStatementOptimizationIsDisabled); | 3672 return Bailout("ForInStatement optimization is disabled"); |
3596 } | 3673 } |
3597 | 3674 |
3598 if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) { | 3675 if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) { |
3599 return Bailout(kForInStatementIsNotFastCase); | 3676 return Bailout("ForInStatement is not fast case"); |
3600 } | 3677 } |
3601 | 3678 |
3602 if (!stmt->each()->IsVariableProxy() || | 3679 if (!stmt->each()->IsVariableProxy() || |
3603 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { | 3680 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { |
3604 return Bailout(kForInStatementWithNonLocalEachVariable); | 3681 return Bailout("ForInStatement with non-local each variable"); |
3605 } | 3682 } |
3606 | 3683 |
3607 Variable* each_var = stmt->each()->AsVariableProxy()->var(); | 3684 Variable* each_var = stmt->each()->AsVariableProxy()->var(); |
3608 | 3685 |
3609 CHECK_ALIVE(VisitForValue(stmt->enumerable())); | 3686 CHECK_ALIVE(VisitForValue(stmt->enumerable())); |
3610 HValue* enumerable = Top(); // Leave enumerable at the top. | 3687 HValue* enumerable = Top(); // Leave enumerable at the top. |
3611 | 3688 |
3612 HInstruction* map = Add<HForInPrepareMap>(enumerable); | 3689 HInstruction* map = Add<HForInPrepareMap>(enumerable); |
3613 Add<HSimulate>(stmt->PrepareId()); | 3690 Add<HSimulate>(stmt->PrepareId()); |
3614 | 3691 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3688 break_info.break_block()); | 3765 break_info.break_block()); |
3689 | 3766 |
3690 set_current_block(loop_exit); | 3767 set_current_block(loop_exit); |
3691 } | 3768 } |
3692 | 3769 |
3693 | 3770 |
3694 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { | 3771 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { |
3695 ASSERT(!HasStackOverflow()); | 3772 ASSERT(!HasStackOverflow()); |
3696 ASSERT(current_block() != NULL); | 3773 ASSERT(current_block() != NULL); |
3697 ASSERT(current_block()->HasPredecessor()); | 3774 ASSERT(current_block()->HasPredecessor()); |
3698 return Bailout(kForOfStatement); | 3775 return Bailout("ForOfStatement"); |
3699 } | 3776 } |
3700 | 3777 |
3701 | 3778 |
3702 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 3779 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
3703 ASSERT(!HasStackOverflow()); | 3780 ASSERT(!HasStackOverflow()); |
3704 ASSERT(current_block() != NULL); | 3781 ASSERT(current_block() != NULL); |
3705 ASSERT(current_block()->HasPredecessor()); | 3782 ASSERT(current_block()->HasPredecessor()); |
3706 return Bailout(kTryCatchStatement); | 3783 return Bailout("TryCatchStatement"); |
3707 } | 3784 } |
3708 | 3785 |
3709 | 3786 |
3710 void HOptimizedGraphBuilder::VisitTryFinallyStatement( | 3787 void HOptimizedGraphBuilder::VisitTryFinallyStatement( |
3711 TryFinallyStatement* stmt) { | 3788 TryFinallyStatement* stmt) { |
3712 ASSERT(!HasStackOverflow()); | 3789 ASSERT(!HasStackOverflow()); |
3713 ASSERT(current_block() != NULL); | 3790 ASSERT(current_block() != NULL); |
3714 ASSERT(current_block()->HasPredecessor()); | 3791 ASSERT(current_block()->HasPredecessor()); |
3715 return Bailout(kTryFinallyStatement); | 3792 return Bailout("TryFinallyStatement"); |
3716 } | 3793 } |
3717 | 3794 |
3718 | 3795 |
3719 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 3796 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
3720 ASSERT(!HasStackOverflow()); | 3797 ASSERT(!HasStackOverflow()); |
3721 ASSERT(current_block() != NULL); | 3798 ASSERT(current_block() != NULL); |
3722 ASSERT(current_block()->HasPredecessor()); | 3799 ASSERT(current_block()->HasPredecessor()); |
3723 return Bailout(kDebuggerStatement); | 3800 return Bailout("DebuggerStatement"); |
3724 } | 3801 } |
3725 | 3802 |
3726 | 3803 |
3727 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( | 3804 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( |
3728 Code* unoptimized_code, FunctionLiteral* expr) { | 3805 Code* unoptimized_code, FunctionLiteral* expr) { |
3729 int start_position = expr->start_position(); | 3806 int start_position = expr->start_position(); |
3730 for (RelocIterator it(unoptimized_code); !it.done(); it.next()) { | 3807 for (RelocIterator it(unoptimized_code); !it.done(); it.next()) { |
3731 RelocInfo* rinfo = it.rinfo(); | 3808 RelocInfo* rinfo = it.rinfo(); |
3732 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; | 3809 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; |
3733 Object* obj = rinfo->target_object(); | 3810 Object* obj = rinfo->target_object(); |
(...skipping 25 matching lines...) Expand all Loading... |
3759 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); | 3836 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); |
3760 return ast_context()->ReturnInstruction(instr, expr->id()); | 3837 return ast_context()->ReturnInstruction(instr, expr->id()); |
3761 } | 3838 } |
3762 | 3839 |
3763 | 3840 |
3764 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( | 3841 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( |
3765 SharedFunctionInfoLiteral* expr) { | 3842 SharedFunctionInfoLiteral* expr) { |
3766 ASSERT(!HasStackOverflow()); | 3843 ASSERT(!HasStackOverflow()); |
3767 ASSERT(current_block() != NULL); | 3844 ASSERT(current_block() != NULL); |
3768 ASSERT(current_block()->HasPredecessor()); | 3845 ASSERT(current_block()->HasPredecessor()); |
3769 return Bailout(kSharedFunctionInfoLiteral); | 3846 return Bailout("SharedFunctionInfoLiteral"); |
3770 } | 3847 } |
3771 | 3848 |
3772 | 3849 |
3773 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) { | 3850 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) { |
3774 ASSERT(!HasStackOverflow()); | 3851 ASSERT(!HasStackOverflow()); |
3775 ASSERT(current_block() != NULL); | 3852 ASSERT(current_block() != NULL); |
3776 ASSERT(current_block()->HasPredecessor()); | 3853 ASSERT(current_block()->HasPredecessor()); |
3777 HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 3854 HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
3778 HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 3855 HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
3779 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); | 3856 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3839 | 3916 |
3840 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 3917 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
3841 ASSERT(!HasStackOverflow()); | 3918 ASSERT(!HasStackOverflow()); |
3842 ASSERT(current_block() != NULL); | 3919 ASSERT(current_block() != NULL); |
3843 ASSERT(current_block()->HasPredecessor()); | 3920 ASSERT(current_block()->HasPredecessor()); |
3844 Variable* variable = expr->var(); | 3921 Variable* variable = expr->var(); |
3845 switch (variable->location()) { | 3922 switch (variable->location()) { |
3846 case Variable::UNALLOCATED: { | 3923 case Variable::UNALLOCATED: { |
3847 if (IsLexicalVariableMode(variable->mode())) { | 3924 if (IsLexicalVariableMode(variable->mode())) { |
3848 // TODO(rossberg): should this be an ASSERT? | 3925 // TODO(rossberg): should this be an ASSERT? |
3849 return Bailout(kReferenceToGlobalLexicalVariable); | 3926 return Bailout("reference to global lexical variable"); |
3850 } | 3927 } |
3851 // Handle known global constants like 'undefined' specially to avoid a | 3928 // Handle known global constants like 'undefined' specially to avoid a |
3852 // load from a global cell for them. | 3929 // load from a global cell for them. |
3853 Handle<Object> constant_value = | 3930 Handle<Object> constant_value = |
3854 isolate()->factory()->GlobalConstantFor(variable->name()); | 3931 isolate()->factory()->GlobalConstantFor(variable->name()); |
3855 if (!constant_value.is_null()) { | 3932 if (!constant_value.is_null()) { |
3856 HConstant* instr = New<HConstant>(constant_value); | 3933 HConstant* instr = New<HConstant>(constant_value); |
3857 return ast_context()->ReturnInstruction(instr, expr->id()); | 3934 return ast_context()->ReturnInstruction(instr, expr->id()); |
3858 } | 3935 } |
3859 | 3936 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3896 return ast_context()->ReturnInstruction(instr, expr->id()); | 3973 return ast_context()->ReturnInstruction(instr, expr->id()); |
3897 } | 3974 } |
3898 } | 3975 } |
3899 | 3976 |
3900 case Variable::PARAMETER: | 3977 case Variable::PARAMETER: |
3901 case Variable::LOCAL: { | 3978 case Variable::LOCAL: { |
3902 HValue* value = LookupAndMakeLive(variable); | 3979 HValue* value = LookupAndMakeLive(variable); |
3903 if (value == graph()->GetConstantHole()) { | 3980 if (value == graph()->GetConstantHole()) { |
3904 ASSERT(IsDeclaredVariableMode(variable->mode()) && | 3981 ASSERT(IsDeclaredVariableMode(variable->mode()) && |
3905 variable->mode() != VAR); | 3982 variable->mode() != VAR); |
3906 return Bailout(kReferenceToUninitializedVariable); | 3983 return Bailout("reference to uninitialized variable"); |
3907 } | 3984 } |
3908 return ast_context()->ReturnValue(value); | 3985 return ast_context()->ReturnValue(value); |
3909 } | 3986 } |
3910 | 3987 |
3911 case Variable::CONTEXT: { | 3988 case Variable::CONTEXT: { |
3912 HValue* context = BuildContextChainWalk(variable); | 3989 HValue* context = BuildContextChainWalk(variable); |
3913 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable); | 3990 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable); |
3914 return ast_context()->ReturnInstruction(instr, expr->id()); | 3991 return ast_context()->ReturnInstruction(instr, expr->id()); |
3915 } | 3992 } |
3916 | 3993 |
3917 case Variable::LOOKUP: | 3994 case Variable::LOOKUP: |
3918 return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup); | 3995 return Bailout("reference to a variable which requires dynamic lookup"); |
3919 } | 3996 } |
3920 } | 3997 } |
3921 | 3998 |
3922 | 3999 |
3923 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { | 4000 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { |
3924 ASSERT(!HasStackOverflow()); | 4001 ASSERT(!HasStackOverflow()); |
3925 ASSERT(current_block() != NULL); | 4002 ASSERT(current_block() != NULL); |
3926 ASSERT(current_block()->HasPredecessor()); | 4003 ASSERT(current_block()->HasPredecessor()); |
3927 HConstant* instr = New<HConstant>(expr->value()); | 4004 HConstant* instr = New<HConstant>(expr->value()); |
3928 return ast_context()->ReturnInstruction(instr, expr->id()); | 4005 return ast_context()->ReturnInstruction(instr, expr->id()); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4029 | 4106 |
4030 // Determines whether the given array or object literal boilerplate satisfies | 4107 // Determines whether the given array or object literal boilerplate satisfies |
4031 // all limits to be considered for fast deep-copying and computes the total | 4108 // all limits to be considered for fast deep-copying and computes the total |
4032 // size of all objects that are part of the graph. | 4109 // size of all objects that are part of the graph. |
4033 static bool IsFastLiteral(Handle<JSObject> boilerplate, | 4110 static bool IsFastLiteral(Handle<JSObject> boilerplate, |
4034 int max_depth, | 4111 int max_depth, |
4035 int* max_properties, | 4112 int* max_properties, |
4036 int* data_size, | 4113 int* data_size, |
4037 int* pointer_size) { | 4114 int* pointer_size) { |
4038 if (boilerplate->map()->is_deprecated()) { | 4115 if (boilerplate->map()->is_deprecated()) { |
4039 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate); | 4116 Handle<Object> result = |
| 4117 JSObject::TryMigrateInstance(boilerplate); |
4040 if (result->IsSmi()) return false; | 4118 if (result->IsSmi()) return false; |
4041 } | 4119 } |
4042 | 4120 |
4043 ASSERT(max_depth >= 0 && *max_properties >= 0); | 4121 ASSERT(max_depth >= 0 && *max_properties >= 0); |
4044 if (max_depth == 0) return false; | 4122 if (max_depth == 0) return false; |
4045 | 4123 |
4046 Isolate* isolate = boilerplate->GetIsolate(); | 4124 Isolate* isolate = boilerplate->GetIsolate(); |
4047 Handle<FixedArrayBase> elements(boilerplate->elements()); | 4125 Handle<FixedArrayBase> elements(boilerplate->elements()); |
4048 if (elements->length() > 0 && | 4126 if (elements->length() > 0 && |
4049 elements->map() != isolate->heap()->fixed_cow_array_map()) { | 4127 elements->map() != isolate->heap()->fixed_cow_array_map()) { |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4206 } | 4284 } |
4207 } else { | 4285 } else { |
4208 CHECK_ALIVE(VisitForEffect(value)); | 4286 CHECK_ALIVE(VisitForEffect(value)); |
4209 } | 4287 } |
4210 break; | 4288 break; |
4211 } | 4289 } |
4212 // Fall through. | 4290 // Fall through. |
4213 case ObjectLiteral::Property::PROTOTYPE: | 4291 case ObjectLiteral::Property::PROTOTYPE: |
4214 case ObjectLiteral::Property::SETTER: | 4292 case ObjectLiteral::Property::SETTER: |
4215 case ObjectLiteral::Property::GETTER: | 4293 case ObjectLiteral::Property::GETTER: |
4216 return Bailout(kObjectLiteralWithComplexProperty); | 4294 return Bailout("Object literal with complex property"); |
4217 default: UNREACHABLE(); | 4295 default: UNREACHABLE(); |
4218 } | 4296 } |
4219 } | 4297 } |
4220 | 4298 |
4221 if (expr->has_function()) { | 4299 if (expr->has_function()) { |
4222 // Return the result of the transformation to fast properties | 4300 // Return the result of the transformation to fast properties |
4223 // instead of the original since this operation changes the map | 4301 // instead of the original since this operation changes the map |
4224 // of the object. This makes sure that the original object won't | 4302 // of the object. This makes sure that the original object won't |
4225 // be used by other optimized code before it is transformed | 4303 // be used by other optimized code before it is transformed |
4226 // (e.g. because of code motion). | 4304 // (e.g. because of code motion). |
(...skipping 18 matching lines...) Expand all Loading... |
4245 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); | 4323 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); |
4246 bool uninitialized = false; | 4324 bool uninitialized = false; |
4247 Handle<Object> literals_cell(literals->get(expr->literal_index()), | 4325 Handle<Object> literals_cell(literals->get(expr->literal_index()), |
4248 isolate()); | 4326 isolate()); |
4249 Handle<Object> raw_boilerplate; | 4327 Handle<Object> raw_boilerplate; |
4250 if (literals_cell->IsUndefined()) { | 4328 if (literals_cell->IsUndefined()) { |
4251 uninitialized = true; | 4329 uninitialized = true; |
4252 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( | 4330 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( |
4253 isolate(), literals, expr->constant_elements()); | 4331 isolate(), literals, expr->constant_elements()); |
4254 if (raw_boilerplate.is_null()) { | 4332 if (raw_boilerplate.is_null()) { |
4255 return Bailout(kArrayBoilerplateCreationFailed); | 4333 return Bailout("array boilerplate creation failed"); |
4256 } | 4334 } |
4257 | 4335 |
4258 site = isolate()->factory()->NewAllocationSite(); | 4336 site = isolate()->factory()->NewAllocationSite(); |
4259 site->set_transition_info(*raw_boilerplate); | 4337 site->set_transition_info(*raw_boilerplate); |
4260 literals->set(expr->literal_index(), *site); | 4338 literals->set(expr->literal_index(), *site); |
4261 | 4339 |
4262 if (JSObject::cast(*raw_boilerplate)->elements()->map() == | 4340 if (JSObject::cast(*raw_boilerplate)->elements()->map() == |
4263 isolate()->heap()->fixed_cow_array_map()) { | 4341 isolate()->heap()->fixed_cow_array_map()) { |
4264 isolate()->counters()->cow_arrays_created_runtime()->Increment(); | 4342 isolate()->counters()->cow_arrays_created_runtime()->Increment(); |
4265 } | 4343 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4336 HInstruction* elements = NULL; | 4414 HInstruction* elements = NULL; |
4337 | 4415 |
4338 for (int i = 0; i < length; i++) { | 4416 for (int i = 0; i < length; i++) { |
4339 Expression* subexpr = subexprs->at(i); | 4417 Expression* subexpr = subexprs->at(i); |
4340 // If the subexpression is a literal or a simple materialized literal it | 4418 // If the subexpression is a literal or a simple materialized literal it |
4341 // is already set in the cloned array. | 4419 // is already set in the cloned array. |
4342 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 4420 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
4343 | 4421 |
4344 CHECK_ALIVE(VisitForValue(subexpr)); | 4422 CHECK_ALIVE(VisitForValue(subexpr)); |
4345 HValue* value = Pop(); | 4423 HValue* value = Pop(); |
4346 if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral); | 4424 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); |
4347 | 4425 |
4348 elements = AddLoadElements(literal); | 4426 elements = AddLoadElements(literal); |
4349 | 4427 |
4350 HValue* key = Add<HConstant>(i); | 4428 HValue* key = Add<HConstant>(i); |
4351 | 4429 |
4352 switch (boilerplate_elements_kind) { | 4430 switch (boilerplate_elements_kind) { |
4353 case FAST_SMI_ELEMENTS: | 4431 case FAST_SMI_ELEMENTS: |
4354 case FAST_HOLEY_SMI_ELEMENTS: | 4432 case FAST_HOLEY_SMI_ELEMENTS: |
4355 case FAST_ELEMENTS: | 4433 case FAST_ELEMENTS: |
4356 case FAST_HOLEY_ELEMENTS: | 4434 case FAST_HOLEY_ELEMENTS: |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4416 // readonly or turned into a setter by some meanwhile modifications on the | 4494 // readonly or turned into a setter by some meanwhile modifications on the |
4417 // prototype chain. | 4495 // prototype chain. |
4418 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { | 4496 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { |
4419 Object* proto = map->prototype(); | 4497 Object* proto = map->prototype(); |
4420 // First check that the prototype chain isn't affected already. | 4498 // First check that the prototype chain isn't affected already. |
4421 LookupResult proto_result(isolate()); | 4499 LookupResult proto_result(isolate()); |
4422 proto->Lookup(*name, &proto_result); | 4500 proto->Lookup(*name, &proto_result); |
4423 if (proto_result.IsProperty()) { | 4501 if (proto_result.IsProperty()) { |
4424 // If the inherited property could induce readonly-ness, bail out. | 4502 // If the inherited property could induce readonly-ness, bail out. |
4425 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) { | 4503 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) { |
4426 Bailout(kImproperObjectOnPrototypeChainForStore); | 4504 Bailout("improper object on prototype chain for store"); |
4427 return NULL; | 4505 return NULL; |
4428 } | 4506 } |
4429 // We only need to check up to the preexisting property. | 4507 // We only need to check up to the preexisting property. |
4430 proto = proto_result.holder(); | 4508 proto = proto_result.holder(); |
4431 } else { | 4509 } else { |
4432 // Otherwise, find the top prototype. | 4510 // Otherwise, find the top prototype. |
4433 while (proto->GetPrototype(isolate())->IsJSObject()) { | 4511 while (proto->GetPrototype(isolate())->IsJSObject()) { |
4434 proto = proto->GetPrototype(isolate()); | 4512 proto = proto->GetPrototype(isolate()); |
4435 } | 4513 } |
4436 ASSERT(proto->GetPrototype(isolate())->IsNull()); | 4514 ASSERT(proto->GetPrototype(isolate())->IsNull()); |
4437 } | 4515 } |
4438 ASSERT(proto->IsJSObject()); | 4516 ASSERT(proto->IsJSObject()); |
4439 BuildCheckPrototypeMaps( | 4517 Add<HCheckPrototypeMaps>( |
4440 Handle<JSObject>(JSObject::cast(map->prototype())), | 4518 Handle<JSObject>(JSObject::cast(map->prototype())), |
4441 Handle<JSObject>(JSObject::cast(proto))); | 4519 Handle<JSObject>(JSObject::cast(proto)), top_info()); |
4442 } | 4520 } |
4443 | 4521 |
4444 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); | 4522 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); |
4445 bool transition_to_field = lookup->IsTransitionToField(*map); | 4523 bool transition_to_field = lookup->IsTransitionToField(*map); |
4446 | 4524 |
4447 HStoreNamedField *instr; | 4525 HStoreNamedField *instr; |
4448 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { | 4526 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { |
4449 HObjectAccess heap_number_access = | 4527 HObjectAccess heap_number_access = |
4450 field_access.WithRepresentation(Representation::Tagged()); | 4528 field_access.WithRepresentation(Representation::Tagged()); |
4451 if (transition_to_field) { | 4529 if (transition_to_field) { |
(...skipping 17 matching lines...) Expand all Loading... |
4469 HObjectAccess::ForHeapNumberValue(), | 4547 HObjectAccess::ForHeapNumberValue(), |
4470 value); | 4548 value); |
4471 } | 4549 } |
4472 } else { | 4550 } else { |
4473 // This is a normal store. | 4551 // This is a normal store. |
4474 instr = New<HStoreNamedField>(object, field_access, value); | 4552 instr = New<HStoreNamedField>(object, field_access, value); |
4475 } | 4553 } |
4476 | 4554 |
4477 if (transition_to_field) { | 4555 if (transition_to_field) { |
4478 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 4556 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
4479 HConstant* transition_constant = Add<HConstant>(transition); | 4557 instr->SetTransition(transition, top_info()); |
4480 instr->SetTransition(transition_constant, top_info()); | |
4481 // TODO(fschneider): Record the new map type of the object in the IR to | 4558 // TODO(fschneider): Record the new map type of the object in the IR to |
4482 // enable elimination of redundant checks after the transition store. | 4559 // enable elimination of redundant checks after the transition store. |
4483 instr->SetGVNFlag(kChangesMaps); | 4560 instr->SetGVNFlag(kChangesMaps); |
4484 } | 4561 } |
4485 return instr; | 4562 return instr; |
4486 } | 4563 } |
4487 | 4564 |
4488 | 4565 |
4489 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( | 4566 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( |
4490 HValue* object, | 4567 HValue* object, |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4586 } | 4663 } |
4587 | 4664 |
4588 LookupInPrototypes(map, name, &lookup); | 4665 LookupInPrototypes(map, name, &lookup); |
4589 if (!lookup.IsField()) return NULL; | 4666 if (!lookup.IsField()) return NULL; |
4590 | 4667 |
4591 BuildCheckHeapObject(object); | 4668 BuildCheckHeapObject(object); |
4592 Add<HCheckMaps>(object, types); | 4669 Add<HCheckMaps>(object, types); |
4593 | 4670 |
4594 Handle<JSObject> holder(lookup.holder()); | 4671 Handle<JSObject> holder(lookup.holder()); |
4595 Handle<Map> holder_map(holder->map()); | 4672 Handle<Map> holder_map(holder->map()); |
4596 BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder); | 4673 Add<HCheckPrototypeMaps>( |
| 4674 Handle<JSObject>::cast(prototype), holder, top_info()); |
4597 HValue* holder_value = Add<HConstant>(holder); | 4675 HValue* holder_value = Add<HConstant>(holder); |
4598 return BuildLoadNamedField(holder_value, | 4676 return BuildLoadNamedField(holder_value, |
4599 HObjectAccess::ForField(holder_map, &lookup, name)); | 4677 HObjectAccess::ForField(holder_map, &lookup, name)); |
4600 } | 4678 } |
4601 | 4679 |
4602 | 4680 |
4603 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 4681 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
4604 Property* expr, | 4682 Property* expr, |
4605 HValue* object, | 4683 HValue* object, |
4606 SmallMapList* types, | 4684 SmallMapList* types, |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4920 Property* prop = target->AsProperty(); | 4998 Property* prop = target->AsProperty(); |
4921 ASSERT(proxy == NULL || prop == NULL); | 4999 ASSERT(proxy == NULL || prop == NULL); |
4922 | 5000 |
4923 // We have a second position recorded in the FullCodeGenerator to have | 5001 // We have a second position recorded in the FullCodeGenerator to have |
4924 // type feedback for the binary operation. | 5002 // type feedback for the binary operation. |
4925 BinaryOperation* operation = expr->binary_operation(); | 5003 BinaryOperation* operation = expr->binary_operation(); |
4926 | 5004 |
4927 if (proxy != NULL) { | 5005 if (proxy != NULL) { |
4928 Variable* var = proxy->var(); | 5006 Variable* var = proxy->var(); |
4929 if (var->mode() == LET) { | 5007 if (var->mode() == LET) { |
4930 return Bailout(kUnsupportedLetCompoundAssignment); | 5008 return Bailout("unsupported let compound assignment"); |
4931 } | 5009 } |
4932 | 5010 |
4933 CHECK_ALIVE(VisitForValue(operation)); | 5011 CHECK_ALIVE(VisitForValue(operation)); |
4934 | 5012 |
4935 switch (var->location()) { | 5013 switch (var->location()) { |
4936 case Variable::UNALLOCATED: | 5014 case Variable::UNALLOCATED: |
4937 HandleGlobalVariableAssignment(var, | 5015 HandleGlobalVariableAssignment(var, |
4938 Top(), | 5016 Top(), |
4939 expr->position(), | 5017 expr->position(), |
4940 expr->AssignmentId()); | 5018 expr->AssignmentId()); |
4941 break; | 5019 break; |
4942 | 5020 |
4943 case Variable::PARAMETER: | 5021 case Variable::PARAMETER: |
4944 case Variable::LOCAL: | 5022 case Variable::LOCAL: |
4945 if (var->mode() == CONST) { | 5023 if (var->mode() == CONST) { |
4946 return Bailout(kUnsupportedConstCompoundAssignment); | 5024 return Bailout("unsupported const compound assignment"); |
4947 } | 5025 } |
4948 BindIfLive(var, Top()); | 5026 BindIfLive(var, Top()); |
4949 break; | 5027 break; |
4950 | 5028 |
4951 case Variable::CONTEXT: { | 5029 case Variable::CONTEXT: { |
4952 // Bail out if we try to mutate a parameter value in a function | 5030 // Bail out if we try to mutate a parameter value in a function |
4953 // using the arguments object. We do not (yet) correctly handle the | 5031 // using the arguments object. We do not (yet) correctly handle the |
4954 // arguments property of the function. | 5032 // arguments property of the function. |
4955 if (current_info()->scope()->arguments() != NULL) { | 5033 if (current_info()->scope()->arguments() != NULL) { |
4956 // Parameters will be allocated to context slots. We have no | 5034 // Parameters will be allocated to context slots. We have no |
4957 // direct way to detect that the variable is a parameter so we do | 5035 // direct way to detect that the variable is a parameter so we do |
4958 // a linear search of the parameter variables. | 5036 // a linear search of the parameter variables. |
4959 int count = current_info()->scope()->num_parameters(); | 5037 int count = current_info()->scope()->num_parameters(); |
4960 for (int i = 0; i < count; ++i) { | 5038 for (int i = 0; i < count; ++i) { |
4961 if (var == current_info()->scope()->parameter(i)) { | 5039 if (var == current_info()->scope()->parameter(i)) { |
4962 Bailout(kAssignmentToParameterFunctionUsesArgumentsObject); | 5040 Bailout( |
| 5041 "assignment to parameter, function uses arguments object"); |
4963 } | 5042 } |
4964 } | 5043 } |
4965 } | 5044 } |
4966 | 5045 |
4967 HStoreContextSlot::Mode mode; | 5046 HStoreContextSlot::Mode mode; |
4968 | 5047 |
4969 switch (var->mode()) { | 5048 switch (var->mode()) { |
4970 case LET: | 5049 case LET: |
4971 mode = HStoreContextSlot::kCheckDeoptimize; | 5050 mode = HStoreContextSlot::kCheckDeoptimize; |
4972 break; | 5051 break; |
(...skipping 10 matching lines...) Expand all Loading... |
4983 HValue* context = BuildContextChainWalk(var); | 5062 HValue* context = BuildContextChainWalk(var); |
4984 HStoreContextSlot* instr = Add<HStoreContextSlot>( | 5063 HStoreContextSlot* instr = Add<HStoreContextSlot>( |
4985 context, var->index(), mode, Top()); | 5064 context, var->index(), mode, Top()); |
4986 if (instr->HasObservableSideEffects()) { | 5065 if (instr->HasObservableSideEffects()) { |
4987 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5066 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
4988 } | 5067 } |
4989 break; | 5068 break; |
4990 } | 5069 } |
4991 | 5070 |
4992 case Variable::LOOKUP: | 5071 case Variable::LOOKUP: |
4993 return Bailout(kCompoundAssignmentToLookupSlot); | 5072 return Bailout("compound assignment to lookup slot"); |
4994 } | 5073 } |
4995 return ast_context()->ReturnValue(Pop()); | 5074 return ast_context()->ReturnValue(Pop()); |
4996 | 5075 |
4997 } else if (prop != NULL) { | 5076 } else if (prop != NULL) { |
4998 if (prop->key()->IsPropertyName()) { | 5077 if (prop->key()->IsPropertyName()) { |
4999 // Named property. | 5078 // Named property. |
5000 CHECK_ALIVE(VisitForValue(prop->obj())); | 5079 CHECK_ALIVE(VisitForValue(prop->obj())); |
5001 HValue* object = Top(); | 5080 HValue* object = Top(); |
5002 | 5081 |
5003 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 5082 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5072 | 5151 |
5073 // Drop the simulated receiver, key, and value. Return the value. | 5152 // Drop the simulated receiver, key, and value. Return the value. |
5074 Drop(3); | 5153 Drop(3); |
5075 Push(instr); | 5154 Push(instr); |
5076 ASSERT(has_side_effects); // Stores always have side effects. | 5155 ASSERT(has_side_effects); // Stores always have side effects. |
5077 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5156 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5078 return ast_context()->ReturnValue(Pop()); | 5157 return ast_context()->ReturnValue(Pop()); |
5079 } | 5158 } |
5080 | 5159 |
5081 } else { | 5160 } else { |
5082 return Bailout(kInvalidLhsInCompoundAssignment); | 5161 return Bailout("invalid lhs in compound assignment"); |
5083 } | 5162 } |
5084 } | 5163 } |
5085 | 5164 |
5086 | 5165 |
5087 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { | 5166 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { |
5088 ASSERT(!HasStackOverflow()); | 5167 ASSERT(!HasStackOverflow()); |
5089 ASSERT(current_block() != NULL); | 5168 ASSERT(current_block() != NULL); |
5090 ASSERT(current_block()->HasPredecessor()); | 5169 ASSERT(current_block()->HasPredecessor()); |
5091 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 5170 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
5092 Property* prop = expr->target()->AsProperty(); | 5171 Property* prop = expr->target()->AsProperty(); |
(...skipping 16 matching lines...) Expand all Loading... |
5109 } | 5188 } |
5110 | 5189 |
5111 if (var->IsStackAllocated()) { | 5190 if (var->IsStackAllocated()) { |
5112 // We insert a use of the old value to detect unsupported uses of const | 5191 // We insert a use of the old value to detect unsupported uses of const |
5113 // variables (e.g. initialization inside a loop). | 5192 // variables (e.g. initialization inside a loop). |
5114 HValue* old_value = environment()->Lookup(var); | 5193 HValue* old_value = environment()->Lookup(var); |
5115 Add<HUseConst>(old_value); | 5194 Add<HUseConst>(old_value); |
5116 } | 5195 } |
5117 } else if (var->mode() == CONST_HARMONY) { | 5196 } else if (var->mode() == CONST_HARMONY) { |
5118 if (expr->op() != Token::INIT_CONST_HARMONY) { | 5197 if (expr->op() != Token::INIT_CONST_HARMONY) { |
5119 return Bailout(kNonInitializerAssignmentToConst); | 5198 return Bailout("non-initializer assignment to const"); |
5120 } | 5199 } |
5121 } | 5200 } |
5122 | 5201 |
5123 if (proxy->IsArguments()) return Bailout(kAssignmentToArguments); | 5202 if (proxy->IsArguments()) return Bailout("assignment to arguments"); |
5124 | 5203 |
5125 // Handle the assignment. | 5204 // Handle the assignment. |
5126 switch (var->location()) { | 5205 switch (var->location()) { |
5127 case Variable::UNALLOCATED: | 5206 case Variable::UNALLOCATED: |
5128 CHECK_ALIVE(VisitForValue(expr->value())); | 5207 CHECK_ALIVE(VisitForValue(expr->value())); |
5129 HandleGlobalVariableAssignment(var, | 5208 HandleGlobalVariableAssignment(var, |
5130 Top(), | 5209 Top(), |
5131 expr->position(), | 5210 expr->position(), |
5132 expr->AssignmentId()); | 5211 expr->AssignmentId()); |
5133 return ast_context()->ReturnValue(Pop()); | 5212 return ast_context()->ReturnValue(Pop()); |
5134 | 5213 |
5135 case Variable::PARAMETER: | 5214 case Variable::PARAMETER: |
5136 case Variable::LOCAL: { | 5215 case Variable::LOCAL: { |
5137 // Perform an initialization check for let declared variables | 5216 // Perform an initialization check for let declared variables |
5138 // or parameters. | 5217 // or parameters. |
5139 if (var->mode() == LET && expr->op() == Token::ASSIGN) { | 5218 if (var->mode() == LET && expr->op() == Token::ASSIGN) { |
5140 HValue* env_value = environment()->Lookup(var); | 5219 HValue* env_value = environment()->Lookup(var); |
5141 if (env_value == graph()->GetConstantHole()) { | 5220 if (env_value == graph()->GetConstantHole()) { |
5142 return Bailout(kAssignmentToLetVariableBeforeInitialization); | 5221 return Bailout("assignment to let variable before initialization"); |
5143 } | 5222 } |
5144 } | 5223 } |
5145 // We do not allow the arguments object to occur in a context where it | 5224 // We do not allow the arguments object to occur in a context where it |
5146 // may escape, but assignments to stack-allocated locals are | 5225 // may escape, but assignments to stack-allocated locals are |
5147 // permitted. | 5226 // permitted. |
5148 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); | 5227 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); |
5149 HValue* value = Pop(); | 5228 HValue* value = Pop(); |
5150 BindIfLive(var, value); | 5229 BindIfLive(var, value); |
5151 return ast_context()->ReturnValue(value); | 5230 return ast_context()->ReturnValue(value); |
5152 } | 5231 } |
5153 | 5232 |
5154 case Variable::CONTEXT: { | 5233 case Variable::CONTEXT: { |
5155 // Bail out if we try to mutate a parameter value in a function using | 5234 // Bail out if we try to mutate a parameter value in a function using |
5156 // the arguments object. We do not (yet) correctly handle the | 5235 // the arguments object. We do not (yet) correctly handle the |
5157 // arguments property of the function. | 5236 // arguments property of the function. |
5158 if (current_info()->scope()->arguments() != NULL) { | 5237 if (current_info()->scope()->arguments() != NULL) { |
5159 // Parameters will rewrite to context slots. We have no direct way | 5238 // Parameters will rewrite to context slots. We have no direct way |
5160 // to detect that the variable is a parameter. | 5239 // to detect that the variable is a parameter. |
5161 int count = current_info()->scope()->num_parameters(); | 5240 int count = current_info()->scope()->num_parameters(); |
5162 for (int i = 0; i < count; ++i) { | 5241 for (int i = 0; i < count; ++i) { |
5163 if (var == current_info()->scope()->parameter(i)) { | 5242 if (var == current_info()->scope()->parameter(i)) { |
5164 return Bailout(kAssignmentToParameterInArgumentsObject); | 5243 return Bailout("assignment to parameter in arguments object"); |
5165 } | 5244 } |
5166 } | 5245 } |
5167 } | 5246 } |
5168 | 5247 |
5169 CHECK_ALIVE(VisitForValue(expr->value())); | 5248 CHECK_ALIVE(VisitForValue(expr->value())); |
5170 HStoreContextSlot::Mode mode; | 5249 HStoreContextSlot::Mode mode; |
5171 if (expr->op() == Token::ASSIGN) { | 5250 if (expr->op() == Token::ASSIGN) { |
5172 switch (var->mode()) { | 5251 switch (var->mode()) { |
5173 case LET: | 5252 case LET: |
5174 mode = HStoreContextSlot::kCheckDeoptimize; | 5253 mode = HStoreContextSlot::kCheckDeoptimize; |
(...skipping 20 matching lines...) Expand all Loading... |
5195 HValue* context = BuildContextChainWalk(var); | 5274 HValue* context = BuildContextChainWalk(var); |
5196 HStoreContextSlot* instr = Add<HStoreContextSlot>( | 5275 HStoreContextSlot* instr = Add<HStoreContextSlot>( |
5197 context, var->index(), mode, Top()); | 5276 context, var->index(), mode, Top()); |
5198 if (instr->HasObservableSideEffects()) { | 5277 if (instr->HasObservableSideEffects()) { |
5199 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5278 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5200 } | 5279 } |
5201 return ast_context()->ReturnValue(Pop()); | 5280 return ast_context()->ReturnValue(Pop()); |
5202 } | 5281 } |
5203 | 5282 |
5204 case Variable::LOOKUP: | 5283 case Variable::LOOKUP: |
5205 return Bailout(kAssignmentToLOOKUPVariable); | 5284 return Bailout("assignment to LOOKUP variable"); |
5206 } | 5285 } |
5207 } else { | 5286 } else { |
5208 return Bailout(kInvalidLeftHandSideInAssignment); | 5287 return Bailout("invalid left-hand side in assignment"); |
5209 } | 5288 } |
5210 } | 5289 } |
5211 | 5290 |
5212 | 5291 |
5213 void HOptimizedGraphBuilder::VisitYield(Yield* expr) { | 5292 void HOptimizedGraphBuilder::VisitYield(Yield* expr) { |
5214 // Generators are not optimized, so we should never get here. | 5293 // Generators are not optimized, so we should never get here. |
5215 UNREACHABLE(); | 5294 UNREACHABLE(); |
5216 } | 5295 } |
5217 | 5296 |
5218 | 5297 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5320 return New<HConstant>(constant); | 5399 return New<HConstant>(constant); |
5321 } | 5400 } |
5322 | 5401 |
5323 // Handle a load from a known field somewhere in the prototype chain. | 5402 // Handle a load from a known field somewhere in the prototype chain. |
5324 LookupInPrototypes(map, name, &lookup); | 5403 LookupInPrototypes(map, name, &lookup); |
5325 if (lookup.IsField()) { | 5404 if (lookup.IsField()) { |
5326 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5405 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
5327 Handle<JSObject> holder(lookup.holder()); | 5406 Handle<JSObject> holder(lookup.holder()); |
5328 Handle<Map> holder_map(holder->map()); | 5407 Handle<Map> holder_map(holder->map()); |
5329 AddCheckMap(object, map); | 5408 AddCheckMap(object, map); |
5330 BuildCheckPrototypeMaps(prototype, holder); | 5409 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); |
5331 HValue* holder_value = Add<HConstant>(holder); | 5410 HValue* holder_value = Add<HConstant>(holder); |
5332 return BuildLoadNamedField(holder_value, | 5411 return BuildLoadNamedField(holder_value, |
5333 HObjectAccess::ForField(holder_map, &lookup, name)); | 5412 HObjectAccess::ForField(holder_map, &lookup, name)); |
5334 } | 5413 } |
5335 | 5414 |
5336 // Handle a load of a constant function somewhere in the prototype chain. | 5415 // Handle a load of a constant function somewhere in the prototype chain. |
5337 if (lookup.IsConstant()) { | 5416 if (lookup.IsConstant()) { |
5338 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5417 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
5339 Handle<JSObject> holder(lookup.holder()); | 5418 Handle<JSObject> holder(lookup.holder()); |
5340 Handle<Map> holder_map(holder->map()); | 5419 Handle<Map> holder_map(holder->map()); |
5341 AddCheckMap(object, map); | 5420 AddCheckMap(object, map); |
5342 BuildCheckPrototypeMaps(prototype, holder); | 5421 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); |
5343 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); | 5422 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); |
5344 return New<HConstant>(constant); | 5423 return New<HConstant>(constant); |
5345 } | 5424 } |
5346 | 5425 |
5347 // No luck, do a generic load. | 5426 // No luck, do a generic load. |
5348 return BuildLoadNamedGeneric(object, name, expr); | 5427 return BuildLoadNamedGeneric(object, name, expr); |
5349 } | 5428 } |
5350 | 5429 |
5351 | 5430 |
5352 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 5431 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
(...skipping 15 matching lines...) Expand all Loading... |
5368 if (dependency) { | 5447 if (dependency) { |
5369 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 5448 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
5370 } | 5449 } |
5371 | 5450 |
5372 // Loads from a "stock" fast holey double arrays can elide the hole check. | 5451 // Loads from a "stock" fast holey double arrays can elide the hole check. |
5373 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; | 5452 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; |
5374 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && | 5453 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && |
5375 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 5454 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
5376 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); | 5455 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); |
5377 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); | 5456 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); |
5378 BuildCheckPrototypeMaps(prototype, object_prototype); | 5457 Add<HCheckPrototypeMaps>(prototype, object_prototype, top_info()); |
5379 load_mode = ALLOW_RETURN_HOLE; | 5458 load_mode = ALLOW_RETURN_HOLE; |
5380 graph()->MarkDependsOnEmptyArrayProtoElements(); | 5459 graph()->MarkDependsOnEmptyArrayProtoElements(); |
5381 } | 5460 } |
5382 | 5461 |
5383 return BuildUncheckedMonomorphicElementAccess( | 5462 return BuildUncheckedMonomorphicElementAccess( |
5384 object, key, val, | 5463 object, key, val, |
5385 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | 5464 mapcheck, map->instance_type() == JS_ARRAY_TYPE, |
5386 map->elements_kind(), is_store, load_mode, store_mode); | 5465 map->elements_kind(), is_store, load_mode, store_mode); |
5387 } | 5466 } |
5388 | 5467 |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5814 Drop(1); | 5893 Drop(1); |
5815 } | 5894 } |
5816 } | 5895 } |
5817 return ast_context()->ReturnValue(load); | 5896 return ast_context()->ReturnValue(load); |
5818 } | 5897 } |
5819 instr->set_position(expr->position()); | 5898 instr->set_position(expr->position()); |
5820 return ast_context()->ReturnInstruction(instr, expr->id()); | 5899 return ast_context()->ReturnInstruction(instr, expr->id()); |
5821 } | 5900 } |
5822 | 5901 |
5823 | 5902 |
5824 void HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, | |
5825 CompilationInfo* info) { | |
5826 HConstant* constant_value = New<HConstant>(constant); | |
5827 | |
5828 if (constant->map()->CanOmitMapChecks()) { | |
5829 constant->map()->AddDependentCompilationInfo( | |
5830 DependentCode::kPrototypeCheckGroup, info); | |
5831 return; | |
5832 } | |
5833 | |
5834 AddInstruction(constant_value); | |
5835 HCheckMaps* check = | |
5836 Add<HCheckMaps>(constant_value, handle(constant->map()), info); | |
5837 check->ClearGVNFlag(kDependsOnElementsKind); | |
5838 } | |
5839 | |
5840 | |
5841 void HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype, | |
5842 Handle<JSObject> holder) { | |
5843 BuildConstantMapCheck(prototype, top_info()); | |
5844 while (!prototype.is_identical_to(holder)) { | |
5845 prototype = handle(JSObject::cast(prototype->GetPrototype())); | |
5846 BuildConstantMapCheck(prototype, top_info()); | |
5847 } | |
5848 } | |
5849 | |
5850 | |
5851 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 5903 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
5852 Handle<Map> receiver_map) { | 5904 Handle<Map> receiver_map) { |
5853 if (!holder.is_null()) { | 5905 if (!holder.is_null()) { |
5854 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 5906 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
5855 BuildCheckPrototypeMaps(prototype, holder); | 5907 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); |
5856 } | 5908 } |
5857 } | 5909 } |
5858 | 5910 |
5859 | 5911 |
5860 void HOptimizedGraphBuilder::AddCheckConstantFunction( | 5912 void HOptimizedGraphBuilder::AddCheckConstantFunction( |
5861 Handle<JSObject> holder, | 5913 Handle<JSObject> holder, |
5862 HValue* receiver, | 5914 HValue* receiver, |
5863 Handle<Map> receiver_map) { | 5915 Handle<Map> receiver_map) { |
5864 // Constant functions have the nice property that the map will change if they | 5916 // Constant functions have the nice property that the map will change if they |
5865 // are overwritten. Therefore it is enough to check the map of the holder and | 5917 // are overwritten. Therefore it is enough to check the map of the holder and |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6217 return false; | 6269 return false; |
6218 } | 6270 } |
6219 | 6271 |
6220 // Parse and allocate variables. | 6272 // Parse and allocate variables. |
6221 CompilationInfo target_info(target, zone()); | 6273 CompilationInfo target_info(target, zone()); |
6222 Handle<SharedFunctionInfo> target_shared(target->shared()); | 6274 Handle<SharedFunctionInfo> target_shared(target->shared()); |
6223 if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info)) { | 6275 if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info)) { |
6224 if (target_info.isolate()->has_pending_exception()) { | 6276 if (target_info.isolate()->has_pending_exception()) { |
6225 // Parse or scope error, never optimize this function. | 6277 // Parse or scope error, never optimize this function. |
6226 SetStackOverflow(); | 6278 SetStackOverflow(); |
6227 target_shared->DisableOptimization(kParseScopeError); | 6279 target_shared->DisableOptimization("parse/scope error"); |
6228 } | 6280 } |
6229 TraceInline(target, caller, "parse failure"); | 6281 TraceInline(target, caller, "parse failure"); |
6230 return false; | 6282 return false; |
6231 } | 6283 } |
6232 | 6284 |
6233 if (target_info.scope()->num_heap_slots() > 0) { | 6285 if (target_info.scope()->num_heap_slots() > 0) { |
6234 TraceInline(target, caller, "target has context-allocated variables"); | 6286 TraceInline(target, caller, "target has context-allocated variables"); |
6235 return false; | 6287 return false; |
6236 } | 6288 } |
6237 FunctionLiteral* function = target_info.function(); | 6289 FunctionLiteral* function = target_info.function(); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6356 function->scope()->arguments(), | 6408 function->scope()->arguments(), |
6357 arguments_object, undefined_receiver); | 6409 arguments_object, undefined_receiver); |
6358 function_state()->set_entry(enter_inlined); | 6410 function_state()->set_entry(enter_inlined); |
6359 | 6411 |
6360 VisitDeclarations(target_info.scope()->declarations()); | 6412 VisitDeclarations(target_info.scope()->declarations()); |
6361 VisitStatements(function->body()); | 6413 VisitStatements(function->body()); |
6362 if (HasStackOverflow()) { | 6414 if (HasStackOverflow()) { |
6363 // Bail out if the inline function did, as we cannot residualize a call | 6415 // Bail out if the inline function did, as we cannot residualize a call |
6364 // instead. | 6416 // instead. |
6365 TraceInline(target, caller, "inline graph construction failed"); | 6417 TraceInline(target, caller, "inline graph construction failed"); |
6366 target_shared->DisableOptimization(kInliningBailedOut); | 6418 target_shared->DisableOptimization("inlining bailed out"); |
6367 inline_bailout_ = true; | 6419 inline_bailout_ = true; |
6368 delete target_state; | 6420 delete target_state; |
6369 return true; | 6421 return true; |
6370 } | 6422 } |
6371 | 6423 |
6372 // Update inlined nodes count. | 6424 // Update inlined nodes count. |
6373 inlined_count_ += nodes_added; | 6425 inlined_count_ += nodes_added; |
6374 | 6426 |
6375 Handle<Code> unoptimized_code(target_shared->code()); | 6427 Handle<Code> unoptimized_code(target_shared->code()); |
6376 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 6428 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6586 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 6638 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
6587 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 6639 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
6588 switch (id) { | 6640 switch (id) { |
6589 case kStringCharCodeAt: | 6641 case kStringCharCodeAt: |
6590 case kStringCharAt: | 6642 case kStringCharAt: |
6591 if (argument_count == 2 && check_type == STRING_CHECK) { | 6643 if (argument_count == 2 && check_type == STRING_CHECK) { |
6592 HValue* index = Pop(); | 6644 HValue* index = Pop(); |
6593 HValue* string = Pop(); | 6645 HValue* string = Pop(); |
6594 HValue* context = environment()->context(); | 6646 HValue* context = environment()->context(); |
6595 ASSERT(!expr->holder().is_null()); | 6647 ASSERT(!expr->holder().is_null()); |
6596 BuildCheckPrototypeMaps(Call::GetPrototypeForPrimitiveCheck( | 6648 Add<HCheckPrototypeMaps>(Call::GetPrototypeForPrimitiveCheck( |
6597 STRING_CHECK, expr->holder()->GetIsolate()), | 6649 STRING_CHECK, expr->holder()->GetIsolate()), |
6598 expr->holder()); | 6650 expr->holder(), top_info()); |
6599 HInstruction* char_code = | 6651 HInstruction* char_code = |
6600 BuildStringCharCodeAt(string, index); | 6652 BuildStringCharCodeAt(string, index); |
6601 if (id == kStringCharCodeAt) { | 6653 if (id == kStringCharCodeAt) { |
6602 ast_context()->ReturnInstruction(char_code, expr->id()); | 6654 ast_context()->ReturnInstruction(char_code, expr->id()); |
6603 return true; | 6655 return true; |
6604 } | 6656 } |
6605 AddInstruction(char_code); | 6657 AddInstruction(char_code); |
6606 HInstruction* result = | 6658 HInstruction* result = |
6607 HStringCharFromCode::New(zone(), context, char_code); | 6659 HStringCharFromCode::New(zone(), context, char_code); |
6608 ast_context()->ReturnInstruction(result, expr->id()); | 6660 ast_context()->ReturnInstruction(result, expr->id()); |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6901 | 6953 |
6902 } else { | 6954 } else { |
6903 HValue* context = environment()->context(); | 6955 HValue* context = environment()->context(); |
6904 call = PreProcessCall( | 6956 call = PreProcessCall( |
6905 new(zone()) HCallNamed(context, name, argument_count)); | 6957 new(zone()) HCallNamed(context, name, argument_count)); |
6906 } | 6958 } |
6907 | 6959 |
6908 } else { | 6960 } else { |
6909 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 6961 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
6910 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 6962 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
6911 return Bailout(kPossibleDirectCallToEval); | 6963 return Bailout("possible direct call to eval"); |
6912 } | 6964 } |
6913 | 6965 |
6914 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); | 6966 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); |
6915 if (global_call) { | 6967 if (global_call) { |
6916 Variable* var = proxy->var(); | 6968 Variable* var = proxy->var(); |
6917 bool known_global_function = false; | 6969 bool known_global_function = false; |
6918 // If there is a global property cell for the name at compile time and | 6970 // If there is a global property cell for the name at compile time and |
6919 // access check is not enabled we assume that the function will not change | 6971 // access check is not enabled we assume that the function will not change |
6920 // and generate optimized code for calling the function. | 6972 // and generate optimized code for calling the function. |
6921 LookupResult lookup(isolate()); | 6973 LookupResult lookup(isolate()); |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7169 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 7221 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
7170 }; | 7222 }; |
7171 #undef INLINE_FUNCTION_GENERATOR_ADDRESS | 7223 #undef INLINE_FUNCTION_GENERATOR_ADDRESS |
7172 | 7224 |
7173 | 7225 |
7174 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 7226 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
7175 ASSERT(!HasStackOverflow()); | 7227 ASSERT(!HasStackOverflow()); |
7176 ASSERT(current_block() != NULL); | 7228 ASSERT(current_block() != NULL); |
7177 ASSERT(current_block()->HasPredecessor()); | 7229 ASSERT(current_block()->HasPredecessor()); |
7178 if (expr->is_jsruntime()) { | 7230 if (expr->is_jsruntime()) { |
7179 return Bailout(kCallToAJavaScriptRuntimeFunction); | 7231 return Bailout("call to a JavaScript runtime function"); |
7180 } | 7232 } |
7181 | 7233 |
7182 const Runtime::Function* function = expr->function(); | 7234 const Runtime::Function* function = expr->function(); |
7183 ASSERT(function != NULL); | 7235 ASSERT(function != NULL); |
7184 if (function->intrinsic_type == Runtime::INLINE) { | 7236 if (function->intrinsic_type == Runtime::INLINE) { |
7185 ASSERT(expr->name()->length() > 0); | 7237 ASSERT(expr->name()->length() > 0); |
7186 ASSERT(expr->name()->Get(0) == '_'); | 7238 ASSERT(expr->name()->Get(0) == '_'); |
7187 // Call to an inline function. | 7239 // Call to an inline function. |
7188 int lookup_index = static_cast<int>(function->function_id) - | 7240 int lookup_index = static_cast<int>(function->function_id) - |
7189 static_cast<int>(Runtime::kFirstInlineFunction); | 7241 static_cast<int>(Runtime::kFirstInlineFunction); |
(...skipping 19 matching lines...) Expand all Loading... |
7209 | 7261 |
7210 | 7262 |
7211 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 7263 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
7212 ASSERT(!HasStackOverflow()); | 7264 ASSERT(!HasStackOverflow()); |
7213 ASSERT(current_block() != NULL); | 7265 ASSERT(current_block() != NULL); |
7214 ASSERT(current_block()->HasPredecessor()); | 7266 ASSERT(current_block()->HasPredecessor()); |
7215 switch (expr->op()) { | 7267 switch (expr->op()) { |
7216 case Token::DELETE: return VisitDelete(expr); | 7268 case Token::DELETE: return VisitDelete(expr); |
7217 case Token::VOID: return VisitVoid(expr); | 7269 case Token::VOID: return VisitVoid(expr); |
7218 case Token::TYPEOF: return VisitTypeof(expr); | 7270 case Token::TYPEOF: return VisitTypeof(expr); |
| 7271 case Token::SUB: return VisitSub(expr); |
| 7272 case Token::BIT_NOT: return VisitBitNot(expr); |
7219 case Token::NOT: return VisitNot(expr); | 7273 case Token::NOT: return VisitNot(expr); |
7220 default: UNREACHABLE(); | 7274 default: UNREACHABLE(); |
7221 } | 7275 } |
7222 } | 7276 } |
7223 | 7277 |
7224 | 7278 |
7225 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { | 7279 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { |
7226 Property* prop = expr->expression()->AsProperty(); | 7280 Property* prop = expr->expression()->AsProperty(); |
7227 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 7281 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
7228 if (prop != NULL) { | 7282 if (prop != NULL) { |
7229 CHECK_ALIVE(VisitForValue(prop->obj())); | 7283 CHECK_ALIVE(VisitForValue(prop->obj())); |
7230 CHECK_ALIVE(VisitForValue(prop->key())); | 7284 CHECK_ALIVE(VisitForValue(prop->key())); |
7231 HValue* key = Pop(); | 7285 HValue* key = Pop(); |
7232 HValue* obj = Pop(); | 7286 HValue* obj = Pop(); |
7233 HValue* function = AddLoadJSBuiltin(Builtins::DELETE); | 7287 HValue* function = AddLoadJSBuiltin(Builtins::DELETE); |
7234 Add<HPushArgument>(obj); | 7288 Add<HPushArgument>(obj); |
7235 Add<HPushArgument>(key); | 7289 Add<HPushArgument>(key); |
7236 Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag())); | 7290 Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag())); |
7237 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 7291 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
7238 // even though we are certain to pass the correct number of arguments here. | 7292 // even though we are certain to pass the correct number of arguments here. |
7239 HInstruction* instr = New<HInvokeFunction>(function, 3); | 7293 HInstruction* instr = New<HInvokeFunction>(function, 3); |
7240 return ast_context()->ReturnInstruction(instr, expr->id()); | 7294 return ast_context()->ReturnInstruction(instr, expr->id()); |
7241 } else if (proxy != NULL) { | 7295 } else if (proxy != NULL) { |
7242 Variable* var = proxy->var(); | 7296 Variable* var = proxy->var(); |
7243 if (var->IsUnallocated()) { | 7297 if (var->IsUnallocated()) { |
7244 Bailout(kDeleteWithGlobalVariable); | 7298 Bailout("delete with global variable"); |
7245 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 7299 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
7246 // Result of deleting non-global variables is false. 'this' is not | 7300 // Result of deleting non-global variables is false. 'this' is not |
7247 // really a variable, though we implement it as one. The | 7301 // really a variable, though we implement it as one. The |
7248 // subexpression does not have side effects. | 7302 // subexpression does not have side effects. |
7249 HValue* value = var->is_this() | 7303 HValue* value = var->is_this() |
7250 ? graph()->GetConstantTrue() | 7304 ? graph()->GetConstantTrue() |
7251 : graph()->GetConstantFalse(); | 7305 : graph()->GetConstantFalse(); |
7252 return ast_context()->ReturnValue(value); | 7306 return ast_context()->ReturnValue(value); |
7253 } else { | 7307 } else { |
7254 Bailout(kDeleteWithNonGlobalVariable); | 7308 Bailout("delete with non-global variable"); |
7255 } | 7309 } |
7256 } else { | 7310 } else { |
7257 // Result of deleting non-property, non-variable reference is true. | 7311 // Result of deleting non-property, non-variable reference is true. |
7258 // Evaluate the subexpression for side effects. | 7312 // Evaluate the subexpression for side effects. |
7259 CHECK_ALIVE(VisitForEffect(expr->expression())); | 7313 CHECK_ALIVE(VisitForEffect(expr->expression())); |
7260 return ast_context()->ReturnValue(graph()->GetConstantTrue()); | 7314 return ast_context()->ReturnValue(graph()->GetConstantTrue()); |
7261 } | 7315 } |
7262 } | 7316 } |
7263 | 7317 |
7264 | 7318 |
7265 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) { | 7319 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) { |
7266 CHECK_ALIVE(VisitForEffect(expr->expression())); | 7320 CHECK_ALIVE(VisitForEffect(expr->expression())); |
7267 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 7321 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
7268 } | 7322 } |
7269 | 7323 |
7270 | 7324 |
7271 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { | 7325 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
7272 CHECK_ALIVE(VisitForTypeOf(expr->expression())); | 7326 CHECK_ALIVE(VisitForTypeOf(expr->expression())); |
7273 HValue* value = Pop(); | 7327 HValue* value = Pop(); |
7274 HValue* context = environment()->context(); | 7328 HValue* context = environment()->context(); |
7275 HInstruction* instr = new(zone()) HTypeof(context, value); | 7329 HInstruction* instr = new(zone()) HTypeof(context, value); |
7276 return ast_context()->ReturnInstruction(instr, expr->id()); | 7330 return ast_context()->ReturnInstruction(instr, expr->id()); |
7277 } | 7331 } |
7278 | 7332 |
7279 | 7333 |
| 7334 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { |
| 7335 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 7336 Handle<Type> operand_type = expr->expression()->bounds().lower; |
| 7337 HValue* value = TruncateToNumber(Pop(), &operand_type); |
| 7338 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB); |
| 7339 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7340 } |
| 7341 |
| 7342 |
| 7343 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
| 7344 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 7345 Handle<Type> operand_type = expr->expression()->bounds().lower; |
| 7346 HValue* value = TruncateToNumber(Pop(), &operand_type); |
| 7347 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT); |
| 7348 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7349 } |
| 7350 |
| 7351 |
7280 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { | 7352 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { |
7281 if (ast_context()->IsTest()) { | 7353 if (ast_context()->IsTest()) { |
7282 TestContext* context = TestContext::cast(ast_context()); | 7354 TestContext* context = TestContext::cast(ast_context()); |
7283 VisitForControl(expr->expression(), | 7355 VisitForControl(expr->expression(), |
7284 context->if_false(), | 7356 context->if_false(), |
7285 context->if_true()); | 7357 context->if_true()); |
7286 return; | 7358 return; |
7287 } | 7359 } |
7288 | 7360 |
7289 if (ast_context()->IsEffect()) { | 7361 if (ast_context()->IsEffect()) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7358 | 7430 |
7359 | 7431 |
7360 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { | 7432 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { |
7361 ASSERT(!HasStackOverflow()); | 7433 ASSERT(!HasStackOverflow()); |
7362 ASSERT(current_block() != NULL); | 7434 ASSERT(current_block() != NULL); |
7363 ASSERT(current_block()->HasPredecessor()); | 7435 ASSERT(current_block()->HasPredecessor()); |
7364 Expression* target = expr->expression(); | 7436 Expression* target = expr->expression(); |
7365 VariableProxy* proxy = target->AsVariableProxy(); | 7437 VariableProxy* proxy = target->AsVariableProxy(); |
7366 Property* prop = target->AsProperty(); | 7438 Property* prop = target->AsProperty(); |
7367 if (proxy == NULL && prop == NULL) { | 7439 if (proxy == NULL && prop == NULL) { |
7368 return Bailout(kInvalidLhsInCountOperation); | 7440 return Bailout("invalid lhs in count operation"); |
7369 } | 7441 } |
7370 | 7442 |
7371 // Match the full code generator stack by simulating an extra stack | 7443 // Match the full code generator stack by simulating an extra stack |
7372 // element for postfix operations in a non-effect context. The return | 7444 // element for postfix operations in a non-effect context. The return |
7373 // value is ToNumber(input). | 7445 // value is ToNumber(input). |
7374 bool returns_original_input = | 7446 bool returns_original_input = |
7375 expr->is_postfix() && !ast_context()->IsEffect(); | 7447 expr->is_postfix() && !ast_context()->IsEffect(); |
7376 HValue* input = NULL; // ToNumber(original_input). | 7448 HValue* input = NULL; // ToNumber(original_input). |
7377 HValue* after = NULL; // The result after incrementing or decrementing. | 7449 HValue* after = NULL; // The result after incrementing or decrementing. |
7378 | 7450 |
7379 if (proxy != NULL) { | 7451 if (proxy != NULL) { |
7380 Variable* var = proxy->var(); | 7452 Variable* var = proxy->var(); |
7381 if (var->mode() == CONST) { | 7453 if (var->mode() == CONST) { |
7382 return Bailout(kUnsupportedCountOperationWithConst); | 7454 return Bailout("unsupported count operation with const"); |
7383 } | 7455 } |
7384 // Argument of the count operation is a variable, not a property. | 7456 // Argument of the count operation is a variable, not a property. |
7385 ASSERT(prop == NULL); | 7457 ASSERT(prop == NULL); |
7386 CHECK_ALIVE(VisitForValue(target)); | 7458 CHECK_ALIVE(VisitForValue(target)); |
7387 | 7459 |
7388 after = BuildIncrement(returns_original_input, expr); | 7460 after = BuildIncrement(returns_original_input, expr); |
7389 input = returns_original_input ? Top() : Pop(); | 7461 input = returns_original_input ? Top() : Pop(); |
7390 Push(after); | 7462 Push(after); |
7391 | 7463 |
7392 switch (var->location()) { | 7464 switch (var->location()) { |
(...skipping 13 matching lines...) Expand all Loading... |
7406 // Bail out if we try to mutate a parameter value in a function | 7478 // Bail out if we try to mutate a parameter value in a function |
7407 // using the arguments object. We do not (yet) correctly handle the | 7479 // using the arguments object. We do not (yet) correctly handle the |
7408 // arguments property of the function. | 7480 // arguments property of the function. |
7409 if (current_info()->scope()->arguments() != NULL) { | 7481 if (current_info()->scope()->arguments() != NULL) { |
7410 // Parameters will rewrite to context slots. We have no direct | 7482 // Parameters will rewrite to context slots. We have no direct |
7411 // way to detect that the variable is a parameter so we use a | 7483 // way to detect that the variable is a parameter so we use a |
7412 // linear search of the parameter list. | 7484 // linear search of the parameter list. |
7413 int count = current_info()->scope()->num_parameters(); | 7485 int count = current_info()->scope()->num_parameters(); |
7414 for (int i = 0; i < count; ++i) { | 7486 for (int i = 0; i < count; ++i) { |
7415 if (var == current_info()->scope()->parameter(i)) { | 7487 if (var == current_info()->scope()->parameter(i)) { |
7416 return Bailout(kAssignmentToParameterInArgumentsObject); | 7488 return Bailout("assignment to parameter in arguments object"); |
7417 } | 7489 } |
7418 } | 7490 } |
7419 } | 7491 } |
7420 | 7492 |
7421 HValue* context = BuildContextChainWalk(var); | 7493 HValue* context = BuildContextChainWalk(var); |
7422 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) | 7494 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) |
7423 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; | 7495 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; |
7424 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 7496 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
7425 mode, after); | 7497 mode, after); |
7426 if (instr->HasObservableSideEffects()) { | 7498 if (instr->HasObservableSideEffects()) { |
7427 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7499 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
7428 } | 7500 } |
7429 break; | 7501 break; |
7430 } | 7502 } |
7431 | 7503 |
7432 case Variable::LOOKUP: | 7504 case Variable::LOOKUP: |
7433 return Bailout(kLookupVariableInCountOperation); | 7505 return Bailout("lookup variable in count operation"); |
7434 } | 7506 } |
7435 | 7507 |
7436 } else { | 7508 } else { |
7437 // Argument of the count operation is a property. | 7509 // Argument of the count operation is a property. |
7438 ASSERT(prop != NULL); | 7510 ASSERT(prop != NULL); |
7439 | 7511 |
7440 if (prop->key()->IsPropertyName()) { | 7512 if (prop->key()->IsPropertyName()) { |
7441 // Named property. | 7513 // Named property. |
7442 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 7514 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
7443 | 7515 |
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8012 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 8084 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
8013 BuildCheckHeapObject(right); | 8085 BuildCheckHeapObject(right); |
8014 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 8086 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
8015 HCompareObjectEqAndBranch* result = | 8087 HCompareObjectEqAndBranch* result = |
8016 new(zone()) HCompareObjectEqAndBranch(left, right); | 8088 new(zone()) HCompareObjectEqAndBranch(left, right); |
8017 result->set_position(expr->position()); | 8089 result->set_position(expr->position()); |
8018 return ast_context()->ReturnControl(result, expr->id()); | 8090 return ast_context()->ReturnControl(result, expr->id()); |
8019 } | 8091 } |
8020 } | 8092 } |
8021 default: | 8093 default: |
8022 return Bailout(kUnsupportedNonPrimitiveCompare); | 8094 return Bailout("Unsupported non-primitive compare"); |
8023 } | 8095 } |
8024 } else if (combined_type->Is(Type::InternalizedString()) && | 8096 } else if (combined_type->Is(Type::InternalizedString()) && |
8025 Token::IsEqualityOp(op)) { | 8097 Token::IsEqualityOp(op)) { |
8026 BuildCheckHeapObject(left); | 8098 BuildCheckHeapObject(left); |
8027 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); | 8099 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); |
8028 BuildCheckHeapObject(right); | 8100 BuildCheckHeapObject(right); |
8029 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); | 8101 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); |
8030 HCompareObjectEqAndBranch* result = | 8102 HCompareObjectEqAndBranch* result = |
8031 new(zone()) HCompareObjectEqAndBranch(left, right); | 8103 new(zone()) HCompareObjectEqAndBranch(left, right); |
8032 result->set_position(expr->position()); | 8104 result->set_position(expr->position()); |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8479 HValue* value = graph()->GetConstantHole(); | 8551 HValue* value = graph()->GetConstantHole(); |
8480 HValue* context = environment()->context(); | 8552 HValue* context = environment()->context(); |
8481 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8553 HStoreContextSlot* store = Add<HStoreContextSlot>( |
8482 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8554 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
8483 if (store->HasObservableSideEffects()) { | 8555 if (store->HasObservableSideEffects()) { |
8484 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); | 8556 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
8485 } | 8557 } |
8486 } | 8558 } |
8487 break; | 8559 break; |
8488 case Variable::LOOKUP: | 8560 case Variable::LOOKUP: |
8489 return Bailout(kUnsupportedLookupSlotInDeclaration); | 8561 return Bailout("unsupported lookup slot in declaration"); |
8490 } | 8562 } |
8491 } | 8563 } |
8492 | 8564 |
8493 | 8565 |
8494 void HOptimizedGraphBuilder::VisitFunctionDeclaration( | 8566 void HOptimizedGraphBuilder::VisitFunctionDeclaration( |
8495 FunctionDeclaration* declaration) { | 8567 FunctionDeclaration* declaration) { |
8496 VariableProxy* proxy = declaration->proxy(); | 8568 VariableProxy* proxy = declaration->proxy(); |
8497 Variable* variable = proxy->var(); | 8569 Variable* variable = proxy->var(); |
8498 switch (variable->location()) { | 8570 switch (variable->location()) { |
8499 case Variable::UNALLOCATED: { | 8571 case Variable::UNALLOCATED: { |
(...skipping 17 matching lines...) Expand all Loading... |
8517 HValue* value = Pop(); | 8589 HValue* value = Pop(); |
8518 HValue* context = environment()->context(); | 8590 HValue* context = environment()->context(); |
8519 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8591 HStoreContextSlot* store = Add<HStoreContextSlot>( |
8520 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8592 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
8521 if (store->HasObservableSideEffects()) { | 8593 if (store->HasObservableSideEffects()) { |
8522 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); | 8594 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
8523 } | 8595 } |
8524 break; | 8596 break; |
8525 } | 8597 } |
8526 case Variable::LOOKUP: | 8598 case Variable::LOOKUP: |
8527 return Bailout(kUnsupportedLookupSlotInDeclaration); | 8599 return Bailout("unsupported lookup slot in declaration"); |
8528 } | 8600 } |
8529 } | 8601 } |
8530 | 8602 |
8531 | 8603 |
8532 void HOptimizedGraphBuilder::VisitModuleDeclaration( | 8604 void HOptimizedGraphBuilder::VisitModuleDeclaration( |
8533 ModuleDeclaration* declaration) { | 8605 ModuleDeclaration* declaration) { |
8534 UNREACHABLE(); | 8606 UNREACHABLE(); |
8535 } | 8607 } |
8536 | 8608 |
8537 | 8609 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8638 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) { | 8710 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) { |
8639 ASSERT(call->arguments()->length() == 1); | 8711 ASSERT(call->arguments()->length() == 1); |
8640 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8712 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8641 HValue* value = Pop(); | 8713 HValue* value = Pop(); |
8642 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); | 8714 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); |
8643 return ast_context()->ReturnControl(result, call->id()); | 8715 return ast_context()->ReturnControl(result, call->id()); |
8644 } | 8716 } |
8645 | 8717 |
8646 | 8718 |
8647 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { | 8719 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { |
8648 return Bailout(kInlinedRuntimeFunctionIsNonNegativeSmi); | 8720 return Bailout("inlined runtime function: IsNonNegativeSmi"); |
8649 } | 8721 } |
8650 | 8722 |
8651 | 8723 |
8652 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { | 8724 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { |
8653 ASSERT(call->arguments()->length() == 1); | 8725 ASSERT(call->arguments()->length() == 1); |
8654 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8726 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8655 HValue* value = Pop(); | 8727 HValue* value = Pop(); |
8656 HIsUndetectableAndBranch* result = | 8728 HIsUndetectableAndBranch* result = |
8657 new(zone()) HIsUndetectableAndBranch(value); | 8729 new(zone()) HIsUndetectableAndBranch(value); |
8658 return ast_context()->ReturnControl(result, call->id()); | 8730 return ast_context()->ReturnControl(result, call->id()); |
8659 } | 8731 } |
8660 | 8732 |
8661 | 8733 |
8662 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( | 8734 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( |
8663 CallRuntime* call) { | 8735 CallRuntime* call) { |
8664 return Bailout(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf); | 8736 return Bailout( |
| 8737 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); |
8665 } | 8738 } |
8666 | 8739 |
8667 | 8740 |
8668 // Support for construct call checks. | 8741 // Support for construct call checks. |
8669 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { | 8742 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { |
8670 ASSERT(call->arguments()->length() == 0); | 8743 ASSERT(call->arguments()->length() == 0); |
8671 if (function_state()->outer() != NULL) { | 8744 if (function_state()->outer() != NULL) { |
8672 // We are generating graph for inlined function. | 8745 // We are generating graph for inlined function. |
8673 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN | 8746 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN |
8674 ? graph()->GetConstantTrue() | 8747 ? graph()->GetConstantTrue() |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8708 HAccessArgumentsAt* result = | 8781 HAccessArgumentsAt* result = |
8709 new(zone()) HAccessArgumentsAt(elements, length, checked_index); | 8782 new(zone()) HAccessArgumentsAt(elements, length, checked_index); |
8710 return ast_context()->ReturnInstruction(result, call->id()); | 8783 return ast_context()->ReturnInstruction(result, call->id()); |
8711 } | 8784 } |
8712 | 8785 |
8713 | 8786 |
8714 // Support for accessing the class and value fields of an object. | 8787 // Support for accessing the class and value fields of an object. |
8715 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { | 8788 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { |
8716 // The special form detected by IsClassOfTest is detected before we get here | 8789 // The special form detected by IsClassOfTest is detected before we get here |
8717 // and does not cause a bailout. | 8790 // and does not cause a bailout. |
8718 return Bailout(kInlinedRuntimeFunctionClassOf); | 8791 return Bailout("inlined runtime function: ClassOf"); |
8719 } | 8792 } |
8720 | 8793 |
8721 | 8794 |
8722 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) { | 8795 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) { |
8723 ASSERT(call->arguments()->length() == 1); | 8796 ASSERT(call->arguments()->length() == 1); |
8724 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8797 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8725 HValue* value = Pop(); | 8798 HValue* value = Pop(); |
8726 HValueOf* result = new(zone()) HValueOf(value); | 8799 HValueOf* result = new(zone()) HValueOf(value); |
8727 return ast_context()->ReturnInstruction(result, call->id()); | 8800 return ast_context()->ReturnInstruction(result, call->id()); |
8728 } | 8801 } |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8925 HValue* context = environment()->context(); | 8998 HValue* context = environment()->context(); |
8926 HCallStub* result = | 8999 HCallStub* result = |
8927 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); | 9000 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); |
8928 Drop(3); | 9001 Drop(3); |
8929 return ast_context()->ReturnInstruction(result, call->id()); | 9002 return ast_context()->ReturnInstruction(result, call->id()); |
8930 } | 9003 } |
8931 | 9004 |
8932 | 9005 |
8933 // Support for fast native caches. | 9006 // Support for fast native caches. |
8934 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 9007 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
8935 return Bailout(kInlinedRuntimeFunctionGetFromCache); | 9008 return Bailout("inlined runtime function: GetFromCache"); |
8936 } | 9009 } |
8937 | 9010 |
8938 | 9011 |
8939 // Fast support for number to string. | 9012 // Fast support for number to string. |
8940 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 9013 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
8941 ASSERT_EQ(1, call->arguments()->length()); | 9014 ASSERT_EQ(1, call->arguments()->length()); |
8942 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9015 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
8943 HValue* context = environment()->context(); | 9016 HValue* context = environment()->context(); |
8944 HCallStub* result = | 9017 HCallStub* result = |
8945 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); | 9018 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9055 HValue* value = Pop(); | 9128 HValue* value = Pop(); |
9056 HValue* context = environment()->context(); | 9129 HValue* context = environment()->context(); |
9057 HInstruction* result = | 9130 HInstruction* result = |
9058 HUnaryMathOperation::New(zone(), context, value, kMathSqrt); | 9131 HUnaryMathOperation::New(zone(), context, value, kMathSqrt); |
9059 return ast_context()->ReturnInstruction(result, call->id()); | 9132 return ast_context()->ReturnInstruction(result, call->id()); |
9060 } | 9133 } |
9061 | 9134 |
9062 | 9135 |
9063 // Check whether two RegExps are equivalent | 9136 // Check whether two RegExps are equivalent |
9064 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { | 9137 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
9065 return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent); | 9138 return Bailout("inlined runtime function: IsRegExpEquivalent"); |
9066 } | 9139 } |
9067 | 9140 |
9068 | 9141 |
9069 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { | 9142 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { |
9070 ASSERT(call->arguments()->length() == 1); | 9143 ASSERT(call->arguments()->length() == 1); |
9071 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9144 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9072 HValue* value = Pop(); | 9145 HValue* value = Pop(); |
9073 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); | 9146 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); |
9074 return ast_context()->ReturnInstruction(result, call->id()); | 9147 return ast_context()->ReturnInstruction(result, call->id()); |
9075 } | 9148 } |
9076 | 9149 |
9077 | 9150 |
9078 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { | 9151 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { |
9079 return Bailout(kInlinedRuntimeFunctionFastAsciiArrayJoin); | 9152 return Bailout("inlined runtime function: FastAsciiArrayJoin"); |
9080 } | 9153 } |
9081 | 9154 |
9082 | 9155 |
9083 // Support for generators. | 9156 // Support for generators. |
9084 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) { | 9157 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) { |
9085 return Bailout(kInlinedRuntimeFunctionGeneratorNext); | 9158 return Bailout("inlined runtime function: GeneratorNext"); |
9086 } | 9159 } |
9087 | 9160 |
9088 | 9161 |
9089 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) { | 9162 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) { |
9090 return Bailout(kInlinedRuntimeFunctionGeneratorThrow); | 9163 return Bailout("inlined runtime function: GeneratorThrow"); |
9091 } | 9164 } |
9092 | 9165 |
9093 | 9166 |
9094 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode( | 9167 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode( |
9095 CallRuntime* call) { | 9168 CallRuntime* call) { |
9096 AddInstruction(new(zone()) HDebugBreak()); | 9169 AddInstruction(new(zone()) HDebugBreak()); |
9097 return ast_context()->ReturnValue(graph()->GetConstant0()); | 9170 return ast_context()->ReturnValue(graph()->GetConstant0()); |
9098 } | 9171 } |
9099 | 9172 |
9100 | 9173 |
(...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9706 if (ShouldProduceTraceOutput()) { | 9779 if (ShouldProduceTraceOutput()) { |
9707 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9780 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9708 } | 9781 } |
9709 | 9782 |
9710 #ifdef DEBUG | 9783 #ifdef DEBUG |
9711 graph_->Verify(false); // No full verify. | 9784 graph_->Verify(false); // No full verify. |
9712 #endif | 9785 #endif |
9713 } | 9786 } |
9714 | 9787 |
9715 } } // namespace v8::internal | 9788 } } // namespace v8::internal |
OLD | NEW |