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 2560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2571 | 2571 |
2572 void EffectContext::ReturnValue(HValue* value) { | 2572 void EffectContext::ReturnValue(HValue* value) { |
2573 // The value is simply ignored. | 2573 // The value is simply ignored. |
2574 } | 2574 } |
2575 | 2575 |
2576 | 2576 |
2577 void ValueContext::ReturnValue(HValue* value) { | 2577 void ValueContext::ReturnValue(HValue* value) { |
2578 // The value is tracked in the bailout environment, and communicated | 2578 // The value is tracked in the bailout environment, and communicated |
2579 // through the environment as the result of the expression. | 2579 // through the environment as the result of the expression. |
2580 if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) { | 2580 if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) { |
2581 owner()->Bailout("bad value context for arguments value"); | 2581 owner()->Bailout(kBadValueContextForArgumentsValue); |
2582 } | 2582 } |
2583 owner()->Push(value); | 2583 owner()->Push(value); |
2584 } | 2584 } |
2585 | 2585 |
2586 | 2586 |
2587 void TestContext::ReturnValue(HValue* value) { | 2587 void TestContext::ReturnValue(HValue* value) { |
2588 BuildBranch(value); | 2588 BuildBranch(value); |
2589 } | 2589 } |
2590 | 2590 |
2591 | 2591 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2623 } else { | 2623 } else { |
2624 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id); | 2624 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id); |
2625 owner()->set_current_block(join); | 2625 owner()->set_current_block(join); |
2626 } | 2626 } |
2627 } | 2627 } |
2628 | 2628 |
2629 | 2629 |
2630 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2630 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
2631 ASSERT(!instr->IsControlInstruction()); | 2631 ASSERT(!instr->IsControlInstruction()); |
2632 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2632 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
2633 return owner()->Bailout("bad value context for arguments object value"); | 2633 return owner()->Bailout(kBadValueContextForArgumentsObjectValue); |
2634 } | 2634 } |
2635 owner()->AddInstruction(instr); | 2635 owner()->AddInstruction(instr); |
2636 owner()->Push(instr); | 2636 owner()->Push(instr); |
2637 if (instr->HasObservableSideEffects()) { | 2637 if (instr->HasObservableSideEffects()) { |
2638 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 2638 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
2639 } | 2639 } |
2640 } | 2640 } |
2641 | 2641 |
2642 | 2642 |
2643 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 2643 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
2644 ASSERT(!instr->HasObservableSideEffects()); | 2644 ASSERT(!instr->HasObservableSideEffects()); |
2645 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2645 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
2646 return owner()->Bailout("bad value context for arguments object value"); | 2646 return owner()->Bailout(kBadValueContextForArgumentsObjectValue); |
2647 } | 2647 } |
2648 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); | 2648 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); |
2649 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); | 2649 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); |
2650 instr->SetSuccessorAt(0, materialize_true); | 2650 instr->SetSuccessorAt(0, materialize_true); |
2651 instr->SetSuccessorAt(1, materialize_false); | 2651 instr->SetSuccessorAt(1, materialize_false); |
2652 owner()->current_block()->Finish(instr); | 2652 owner()->current_block()->Finish(instr); |
2653 owner()->set_current_block(materialize_true); | 2653 owner()->set_current_block(materialize_true); |
2654 owner()->Push(owner()->graph()->GetConstantTrue()); | 2654 owner()->Push(owner()->graph()->GetConstantTrue()); |
2655 owner()->set_current_block(materialize_false); | 2655 owner()->set_current_block(materialize_false); |
2656 owner()->Push(owner()->graph()->GetConstantFalse()); | 2656 owner()->Push(owner()->graph()->GetConstantFalse()); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2726 } | 2726 } |
2727 | 2727 |
2728 | 2728 |
2729 void TestContext::BuildBranch(HValue* value) { | 2729 void TestContext::BuildBranch(HValue* value) { |
2730 // 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 |
2731 // 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 |
2732 // 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 |
2733 // branch. | 2733 // branch. |
2734 HOptimizedGraphBuilder* builder = owner(); | 2734 HOptimizedGraphBuilder* builder = owner(); |
2735 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { | 2735 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { |
2736 builder->Bailout("arguments object value in a test context"); | 2736 builder->Bailout(kArgumentsObjectValueInATestContext); |
2737 } | 2737 } |
2738 if (value->IsConstant()) { | 2738 if (value->IsConstant()) { |
2739 HConstant* constant_value = HConstant::cast(value); | 2739 HConstant* constant_value = HConstant::cast(value); |
2740 if (constant_value->BooleanValue()) { | 2740 if (constant_value->BooleanValue()) { |
2741 builder->current_block()->Goto(if_true(), builder->function_state()); | 2741 builder->current_block()->Goto(if_true(), builder->function_state()); |
2742 } else { | 2742 } else { |
2743 builder->current_block()->Goto(if_false(), builder->function_state()); | 2743 builder->current_block()->Goto(if_false(), builder->function_state()); |
2744 } | 2744 } |
2745 builder->set_current_block(NULL); | 2745 builder->set_current_block(NULL); |
2746 return; | 2746 return; |
(...skipping 25 matching lines...) Expand all Loading... |
2772 } while (false) | 2772 } while (false) |
2773 | 2773 |
2774 | 2774 |
2775 #define CHECK_ALIVE_OR_RETURN(call, value) \ | 2775 #define CHECK_ALIVE_OR_RETURN(call, value) \ |
2776 do { \ | 2776 do { \ |
2777 call; \ | 2777 call; \ |
2778 if (HasStackOverflow() || current_block() == NULL) return value; \ | 2778 if (HasStackOverflow() || current_block() == NULL) return value; \ |
2779 } while (false) | 2779 } while (false) |
2780 | 2780 |
2781 | 2781 |
2782 void HOptimizedGraphBuilder::Bailout(const char* reason) { | 2782 void HOptimizedGraphBuilder::Bailout(BailoutReason reason) { |
2783 current_info()->set_bailout_reason(reason); | 2783 current_info()->set_bailout_reason(reason); |
2784 SetStackOverflow(); | 2784 SetStackOverflow(); |
2785 } | 2785 } |
2786 | 2786 |
2787 | 2787 |
2788 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { | 2788 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { |
2789 EffectContext for_effect(this); | 2789 EffectContext for_effect(this); |
2790 Visit(expr); | 2790 Visit(expr); |
2791 } | 2791 } |
2792 | 2792 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2831 void HOptimizedGraphBuilder::VisitExpressions( | 2831 void HOptimizedGraphBuilder::VisitExpressions( |
2832 ZoneList<Expression*>* exprs) { | 2832 ZoneList<Expression*>* exprs) { |
2833 for (int i = 0; i < exprs->length(); ++i) { | 2833 for (int i = 0; i < exprs->length(); ++i) { |
2834 CHECK_ALIVE(VisitForValue(exprs->at(i))); | 2834 CHECK_ALIVE(VisitForValue(exprs->at(i))); |
2835 } | 2835 } |
2836 } | 2836 } |
2837 | 2837 |
2838 | 2838 |
2839 bool HOptimizedGraphBuilder::BuildGraph() { | 2839 bool HOptimizedGraphBuilder::BuildGraph() { |
2840 if (current_info()->function()->is_generator()) { | 2840 if (current_info()->function()->is_generator()) { |
2841 Bailout("function is a generator"); | 2841 Bailout(kFunctionIsAGenerator); |
2842 return false; | 2842 return false; |
2843 } | 2843 } |
2844 Scope* scope = current_info()->scope(); | 2844 Scope* scope = current_info()->scope(); |
2845 if (scope->HasIllegalRedeclaration()) { | 2845 if (scope->HasIllegalRedeclaration()) { |
2846 Bailout("function with illegal redeclaration"); | 2846 Bailout(kFunctionWithIllegalRedeclaration); |
2847 return false; | 2847 return false; |
2848 } | 2848 } |
2849 if (scope->calls_eval()) { | 2849 if (scope->calls_eval()) { |
2850 Bailout("function calls eval"); | 2850 Bailout(kFunctionCallsEval); |
2851 return false; | 2851 return false; |
2852 } | 2852 } |
2853 SetUpScope(scope); | 2853 SetUpScope(scope); |
2854 | 2854 |
2855 // 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 |
2856 // environment will be used by the Lithium translation as the initial | 2856 // environment will be used by the Lithium translation as the initial |
2857 // 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 |
2858 // Hydrogen translation of the instructions in the start block. This | 2858 // Hydrogen translation of the instructions in the start block. This |
2859 // environment uses values which have not been defined yet. These | 2859 // environment uses values which have not been defined yet. These |
2860 // 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... |
2906 !type_info->matches_inlined_type_change_checksum(composite_checksum)); | 2906 !type_info->matches_inlined_type_change_checksum(composite_checksum)); |
2907 type_info->set_inlined_type_change_checksum(composite_checksum); | 2907 type_info->set_inlined_type_change_checksum(composite_checksum); |
2908 | 2908 |
2909 // Perform any necessary OSR-specific cleanups or changes to the graph. | 2909 // Perform any necessary OSR-specific cleanups or changes to the graph. |
2910 osr_->FinishGraph(); | 2910 osr_->FinishGraph(); |
2911 | 2911 |
2912 return true; | 2912 return true; |
2913 } | 2913 } |
2914 | 2914 |
2915 | 2915 |
2916 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { | 2916 bool HGraph::Optimize(BailoutReason* bailout_reason) { |
2917 *bailout_reason = SmartArrayPointer<char>(); | |
2918 OrderBlocks(); | 2917 OrderBlocks(); |
2919 AssignDominators(); | 2918 AssignDominators(); |
2920 | 2919 |
2921 // We need to create a HConstant "zero" now so that GVN will fold every | 2920 // We need to create a HConstant "zero" now so that GVN will fold every |
2922 // zero-valued constant in the graph together. | 2921 // zero-valued constant in the graph together. |
2923 // The constant is needed to make idef-based bounds check work: the pass | 2922 // The constant is needed to make idef-based bounds check work: the pass |
2924 // evaluates relations with "zero" and that zero cannot be created after GVN. | 2923 // evaluates relations with "zero" and that zero cannot be created after GVN. |
2925 GetConstant0(); | 2924 GetConstant0(); |
2926 | 2925 |
2927 #ifdef DEBUG | 2926 #ifdef DEBUG |
2928 // Do a full verify after building the graph and computing dominators. | 2927 // Do a full verify after building the graph and computing dominators. |
2929 Verify(true); | 2928 Verify(true); |
2930 #endif | 2929 #endif |
2931 | 2930 |
2932 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) { | 2931 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) { |
2933 Run<HEnvironmentLivenessAnalysisPhase>(); | 2932 Run<HEnvironmentLivenessAnalysisPhase>(); |
2934 } | 2933 } |
2935 | 2934 |
2936 Run<HPropagateDeoptimizingMarkPhase>(); | 2935 Run<HPropagateDeoptimizingMarkPhase>(); |
2937 if (!CheckConstPhiUses()) { | 2936 if (!CheckConstPhiUses()) { |
2938 *bailout_reason = SmartArrayPointer<char>(StrDup( | 2937 *bailout_reason = kUnsupportedPhiUseOfConstVariable; |
2939 "Unsupported phi use of const variable")); | |
2940 return false; | 2938 return false; |
2941 } | 2939 } |
2942 Run<HRedundantPhiEliminationPhase>(); | 2940 Run<HRedundantPhiEliminationPhase>(); |
2943 if (!CheckArgumentsPhiUses()) { | 2941 if (!CheckArgumentsPhiUses()) { |
2944 *bailout_reason = SmartArrayPointer<char>(StrDup( | 2942 *bailout_reason = kUnsupportedPhiUseOfArguments; |
2945 "Unsupported phi use of arguments")); | |
2946 return false; | 2943 return false; |
2947 } | 2944 } |
2948 | 2945 |
2949 // Remove dead code and phis | 2946 // Remove dead code and phis |
2950 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); | 2947 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); |
2951 CollectPhis(); | 2948 CollectPhis(); |
2952 | 2949 |
2953 if (has_osr()) osr()->FinishOsrValues(); | 2950 if (has_osr()) osr()->FinishOsrValues(); |
2954 | 2951 |
2955 Run<HInferRepresentationPhase>(); | 2952 Run<HInferRepresentationPhase>(); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3117 for (int i = environment()->parameter_count() + 1; | 3114 for (int i = environment()->parameter_count() + 1; |
3118 i < environment()->length(); | 3115 i < environment()->length(); |
3119 ++i) { | 3116 ++i) { |
3120 environment()->Bind(i, undefined_constant); | 3117 environment()->Bind(i, undefined_constant); |
3121 } | 3118 } |
3122 | 3119 |
3123 // Handle the arguments and arguments shadow variables specially (they do | 3120 // Handle the arguments and arguments shadow variables specially (they do |
3124 // not have declarations). | 3121 // not have declarations). |
3125 if (scope->arguments() != NULL) { | 3122 if (scope->arguments() != NULL) { |
3126 if (!scope->arguments()->IsStackAllocated()) { | 3123 if (!scope->arguments()->IsStackAllocated()) { |
3127 return Bailout("context-allocated arguments"); | 3124 return Bailout(kContextAllocatedArguments); |
3128 } | 3125 } |
3129 | 3126 |
3130 environment()->Bind(scope->arguments(), | 3127 environment()->Bind(scope->arguments(), |
3131 graph()->GetArgumentsObject()); | 3128 graph()->GetArgumentsObject()); |
3132 } | 3129 } |
3133 } | 3130 } |
3134 | 3131 |
3135 | 3132 |
3136 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { | 3133 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { |
3137 for (int i = 0; i < statements->length(); i++) { | 3134 for (int i = 0; i < statements->length(); i++) { |
3138 CHECK_ALIVE(Visit(statements->at(i))); | 3135 CHECK_ALIVE(Visit(statements->at(i))); |
3139 } | 3136 } |
3140 } | 3137 } |
3141 | 3138 |
3142 | 3139 |
3143 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) { | 3140 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) { |
3144 ASSERT(!HasStackOverflow()); | 3141 ASSERT(!HasStackOverflow()); |
3145 ASSERT(current_block() != NULL); | 3142 ASSERT(current_block() != NULL); |
3146 ASSERT(current_block()->HasPredecessor()); | 3143 ASSERT(current_block()->HasPredecessor()); |
3147 if (stmt->scope() != NULL) { | 3144 if (stmt->scope() != NULL) { |
3148 return Bailout("ScopedBlock"); | 3145 return Bailout(kScopedBlock); |
3149 } | 3146 } |
3150 BreakAndContinueInfo break_info(stmt); | 3147 BreakAndContinueInfo break_info(stmt); |
3151 { BreakAndContinueScope push(&break_info, this); | 3148 { BreakAndContinueScope push(&break_info, this); |
3152 CHECK_BAILOUT(VisitStatements(stmt->statements())); | 3149 CHECK_BAILOUT(VisitStatements(stmt->statements())); |
3153 } | 3150 } |
3154 HBasicBlock* break_block = break_info.break_block(); | 3151 HBasicBlock* break_block = break_info.break_block(); |
3155 if (break_block != NULL) { | 3152 if (break_block != NULL) { |
3156 if (current_block() != NULL) current_block()->Goto(break_block); | 3153 if (current_block() != NULL) current_block()->Goto(break_block); |
3157 break_block->SetJoinId(stmt->ExitId()); | 3154 break_block->SetJoinId(stmt->ExitId()); |
3158 set_current_block(break_block); | 3155 set_current_block(break_block); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3350 } | 3347 } |
3351 } | 3348 } |
3352 set_current_block(NULL); | 3349 set_current_block(NULL); |
3353 } | 3350 } |
3354 | 3351 |
3355 | 3352 |
3356 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { | 3353 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { |
3357 ASSERT(!HasStackOverflow()); | 3354 ASSERT(!HasStackOverflow()); |
3358 ASSERT(current_block() != NULL); | 3355 ASSERT(current_block() != NULL); |
3359 ASSERT(current_block()->HasPredecessor()); | 3356 ASSERT(current_block()->HasPredecessor()); |
3360 return Bailout("WithStatement"); | 3357 return Bailout(kWithStatement); |
3361 } | 3358 } |
3362 | 3359 |
3363 | 3360 |
3364 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 3361 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
3365 ASSERT(!HasStackOverflow()); | 3362 ASSERT(!HasStackOverflow()); |
3366 ASSERT(current_block() != NULL); | 3363 ASSERT(current_block() != NULL); |
3367 ASSERT(current_block()->HasPredecessor()); | 3364 ASSERT(current_block()->HasPredecessor()); |
3368 | 3365 |
3369 // We only optimize switch statements with smi-literal smi comparisons, | 3366 // We only optimize switch statements with smi-literal smi comparisons, |
3370 // with a bounded number of clauses. | 3367 // with a bounded number of clauses. |
3371 const int kCaseClauseLimit = 128; | 3368 const int kCaseClauseLimit = 128; |
3372 ZoneList<CaseClause*>* clauses = stmt->cases(); | 3369 ZoneList<CaseClause*>* clauses = stmt->cases(); |
3373 int clause_count = clauses->length(); | 3370 int clause_count = clauses->length(); |
3374 if (clause_count > kCaseClauseLimit) { | 3371 if (clause_count > kCaseClauseLimit) { |
3375 return Bailout("SwitchStatement: too many clauses"); | 3372 return Bailout(kSwitchStatementTooManyClauses); |
3376 } | 3373 } |
3377 | 3374 |
3378 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); | 3375 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); |
3379 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { | 3376 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { |
3380 return Bailout("SwitchStatement: mixed or non-literal switch labels"); | 3377 return Bailout(kSwitchStatementMixedOrNonLiteralSwitchLabels); |
3381 } | 3378 } |
3382 | 3379 |
3383 HValue* context = environment()->context(); | 3380 HValue* context = environment()->context(); |
3384 | 3381 |
3385 CHECK_ALIVE(VisitForValue(stmt->tag())); | 3382 CHECK_ALIVE(VisitForValue(stmt->tag())); |
3386 Add<HSimulate>(stmt->EntryId()); | 3383 Add<HSimulate>(stmt->EntryId()); |
3387 HValue* tag_value = Pop(); | 3384 HValue* tag_value = Pop(); |
3388 HBasicBlock* first_test_block = current_block(); | 3385 HBasicBlock* first_test_block = current_block(); |
3389 | 3386 |
3390 HUnaryControlInstruction* string_check = NULL; | 3387 HUnaryControlInstruction* string_check = NULL; |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3662 set_current_block(loop_exit); | 3659 set_current_block(loop_exit); |
3663 } | 3660 } |
3664 | 3661 |
3665 | 3662 |
3666 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 3663 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
3667 ASSERT(!HasStackOverflow()); | 3664 ASSERT(!HasStackOverflow()); |
3668 ASSERT(current_block() != NULL); | 3665 ASSERT(current_block() != NULL); |
3669 ASSERT(current_block()->HasPredecessor()); | 3666 ASSERT(current_block()->HasPredecessor()); |
3670 | 3667 |
3671 if (!FLAG_optimize_for_in) { | 3668 if (!FLAG_optimize_for_in) { |
3672 return Bailout("ForInStatement optimization is disabled"); | 3669 return Bailout(kForInStatementOptimizationIsDisabled); |
3673 } | 3670 } |
3674 | 3671 |
3675 if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) { | 3672 if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) { |
3676 return Bailout("ForInStatement is not fast case"); | 3673 return Bailout(kForInStatementIsNotFastCase); |
3677 } | 3674 } |
3678 | 3675 |
3679 if (!stmt->each()->IsVariableProxy() || | 3676 if (!stmt->each()->IsVariableProxy() || |
3680 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { | 3677 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { |
3681 return Bailout("ForInStatement with non-local each variable"); | 3678 return Bailout(kForInStatementWithNonLocalEachVariable); |
3682 } | 3679 } |
3683 | 3680 |
3684 Variable* each_var = stmt->each()->AsVariableProxy()->var(); | 3681 Variable* each_var = stmt->each()->AsVariableProxy()->var(); |
3685 | 3682 |
3686 CHECK_ALIVE(VisitForValue(stmt->enumerable())); | 3683 CHECK_ALIVE(VisitForValue(stmt->enumerable())); |
3687 HValue* enumerable = Top(); // Leave enumerable at the top. | 3684 HValue* enumerable = Top(); // Leave enumerable at the top. |
3688 | 3685 |
3689 HInstruction* map = Add<HForInPrepareMap>(enumerable); | 3686 HInstruction* map = Add<HForInPrepareMap>(enumerable); |
3690 Add<HSimulate>(stmt->PrepareId()); | 3687 Add<HSimulate>(stmt->PrepareId()); |
3691 | 3688 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3765 break_info.break_block()); | 3762 break_info.break_block()); |
3766 | 3763 |
3767 set_current_block(loop_exit); | 3764 set_current_block(loop_exit); |
3768 } | 3765 } |
3769 | 3766 |
3770 | 3767 |
3771 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { | 3768 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { |
3772 ASSERT(!HasStackOverflow()); | 3769 ASSERT(!HasStackOverflow()); |
3773 ASSERT(current_block() != NULL); | 3770 ASSERT(current_block() != NULL); |
3774 ASSERT(current_block()->HasPredecessor()); | 3771 ASSERT(current_block()->HasPredecessor()); |
3775 return Bailout("ForOfStatement"); | 3772 return Bailout(kForOfStatement); |
3776 } | 3773 } |
3777 | 3774 |
3778 | 3775 |
3779 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 3776 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
3780 ASSERT(!HasStackOverflow()); | 3777 ASSERT(!HasStackOverflow()); |
3781 ASSERT(current_block() != NULL); | 3778 ASSERT(current_block() != NULL); |
3782 ASSERT(current_block()->HasPredecessor()); | 3779 ASSERT(current_block()->HasPredecessor()); |
3783 return Bailout("TryCatchStatement"); | 3780 return Bailout(kTryCatchStatement); |
3784 } | 3781 } |
3785 | 3782 |
3786 | 3783 |
3787 void HOptimizedGraphBuilder::VisitTryFinallyStatement( | 3784 void HOptimizedGraphBuilder::VisitTryFinallyStatement( |
3788 TryFinallyStatement* stmt) { | 3785 TryFinallyStatement* stmt) { |
3789 ASSERT(!HasStackOverflow()); | 3786 ASSERT(!HasStackOverflow()); |
3790 ASSERT(current_block() != NULL); | 3787 ASSERT(current_block() != NULL); |
3791 ASSERT(current_block()->HasPredecessor()); | 3788 ASSERT(current_block()->HasPredecessor()); |
3792 return Bailout("TryFinallyStatement"); | 3789 return Bailout(kTryFinallyStatement); |
3793 } | 3790 } |
3794 | 3791 |
3795 | 3792 |
3796 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 3793 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
3797 ASSERT(!HasStackOverflow()); | 3794 ASSERT(!HasStackOverflow()); |
3798 ASSERT(current_block() != NULL); | 3795 ASSERT(current_block() != NULL); |
3799 ASSERT(current_block()->HasPredecessor()); | 3796 ASSERT(current_block()->HasPredecessor()); |
3800 return Bailout("DebuggerStatement"); | 3797 return Bailout(kDebuggerStatement); |
3801 } | 3798 } |
3802 | 3799 |
3803 | 3800 |
3804 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( | 3801 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( |
3805 Code* unoptimized_code, FunctionLiteral* expr) { | 3802 Code* unoptimized_code, FunctionLiteral* expr) { |
3806 int start_position = expr->start_position(); | 3803 int start_position = expr->start_position(); |
3807 for (RelocIterator it(unoptimized_code); !it.done(); it.next()) { | 3804 for (RelocIterator it(unoptimized_code); !it.done(); it.next()) { |
3808 RelocInfo* rinfo = it.rinfo(); | 3805 RelocInfo* rinfo = it.rinfo(); |
3809 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; | 3806 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; |
3810 Object* obj = rinfo->target_object(); | 3807 Object* obj = rinfo->target_object(); |
(...skipping 25 matching lines...) Expand all Loading... |
3836 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); | 3833 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); |
3837 return ast_context()->ReturnInstruction(instr, expr->id()); | 3834 return ast_context()->ReturnInstruction(instr, expr->id()); |
3838 } | 3835 } |
3839 | 3836 |
3840 | 3837 |
3841 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( | 3838 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( |
3842 SharedFunctionInfoLiteral* expr) { | 3839 SharedFunctionInfoLiteral* expr) { |
3843 ASSERT(!HasStackOverflow()); | 3840 ASSERT(!HasStackOverflow()); |
3844 ASSERT(current_block() != NULL); | 3841 ASSERT(current_block() != NULL); |
3845 ASSERT(current_block()->HasPredecessor()); | 3842 ASSERT(current_block()->HasPredecessor()); |
3846 return Bailout("SharedFunctionInfoLiteral"); | 3843 return Bailout(kSharedFunctionInfoLiteral); |
3847 } | 3844 } |
3848 | 3845 |
3849 | 3846 |
3850 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) { | 3847 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) { |
3851 ASSERT(!HasStackOverflow()); | 3848 ASSERT(!HasStackOverflow()); |
3852 ASSERT(current_block() != NULL); | 3849 ASSERT(current_block() != NULL); |
3853 ASSERT(current_block()->HasPredecessor()); | 3850 ASSERT(current_block()->HasPredecessor()); |
3854 HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 3851 HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
3855 HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 3852 HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
3856 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); | 3853 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3916 | 3913 |
3917 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 3914 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
3918 ASSERT(!HasStackOverflow()); | 3915 ASSERT(!HasStackOverflow()); |
3919 ASSERT(current_block() != NULL); | 3916 ASSERT(current_block() != NULL); |
3920 ASSERT(current_block()->HasPredecessor()); | 3917 ASSERT(current_block()->HasPredecessor()); |
3921 Variable* variable = expr->var(); | 3918 Variable* variable = expr->var(); |
3922 switch (variable->location()) { | 3919 switch (variable->location()) { |
3923 case Variable::UNALLOCATED: { | 3920 case Variable::UNALLOCATED: { |
3924 if (IsLexicalVariableMode(variable->mode())) { | 3921 if (IsLexicalVariableMode(variable->mode())) { |
3925 // TODO(rossberg): should this be an ASSERT? | 3922 // TODO(rossberg): should this be an ASSERT? |
3926 return Bailout("reference to global lexical variable"); | 3923 return Bailout(kReferenceToGlobalLexicalVariable); |
3927 } | 3924 } |
3928 // Handle known global constants like 'undefined' specially to avoid a | 3925 // Handle known global constants like 'undefined' specially to avoid a |
3929 // load from a global cell for them. | 3926 // load from a global cell for them. |
3930 Handle<Object> constant_value = | 3927 Handle<Object> constant_value = |
3931 isolate()->factory()->GlobalConstantFor(variable->name()); | 3928 isolate()->factory()->GlobalConstantFor(variable->name()); |
3932 if (!constant_value.is_null()) { | 3929 if (!constant_value.is_null()) { |
3933 HConstant* instr = New<HConstant>(constant_value); | 3930 HConstant* instr = New<HConstant>(constant_value); |
3934 return ast_context()->ReturnInstruction(instr, expr->id()); | 3931 return ast_context()->ReturnInstruction(instr, expr->id()); |
3935 } | 3932 } |
3936 | 3933 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3973 return ast_context()->ReturnInstruction(instr, expr->id()); | 3970 return ast_context()->ReturnInstruction(instr, expr->id()); |
3974 } | 3971 } |
3975 } | 3972 } |
3976 | 3973 |
3977 case Variable::PARAMETER: | 3974 case Variable::PARAMETER: |
3978 case Variable::LOCAL: { | 3975 case Variable::LOCAL: { |
3979 HValue* value = LookupAndMakeLive(variable); | 3976 HValue* value = LookupAndMakeLive(variable); |
3980 if (value == graph()->GetConstantHole()) { | 3977 if (value == graph()->GetConstantHole()) { |
3981 ASSERT(IsDeclaredVariableMode(variable->mode()) && | 3978 ASSERT(IsDeclaredVariableMode(variable->mode()) && |
3982 variable->mode() != VAR); | 3979 variable->mode() != VAR); |
3983 return Bailout("reference to uninitialized variable"); | 3980 return Bailout(kReferenceToUninitializedVariable); |
3984 } | 3981 } |
3985 return ast_context()->ReturnValue(value); | 3982 return ast_context()->ReturnValue(value); |
3986 } | 3983 } |
3987 | 3984 |
3988 case Variable::CONTEXT: { | 3985 case Variable::CONTEXT: { |
3989 HValue* context = BuildContextChainWalk(variable); | 3986 HValue* context = BuildContextChainWalk(variable); |
3990 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable); | 3987 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable); |
3991 return ast_context()->ReturnInstruction(instr, expr->id()); | 3988 return ast_context()->ReturnInstruction(instr, expr->id()); |
3992 } | 3989 } |
3993 | 3990 |
3994 case Variable::LOOKUP: | 3991 case Variable::LOOKUP: |
3995 return Bailout("reference to a variable which requires dynamic lookup"); | 3992 return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup); |
3996 } | 3993 } |
3997 } | 3994 } |
3998 | 3995 |
3999 | 3996 |
4000 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { | 3997 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { |
4001 ASSERT(!HasStackOverflow()); | 3998 ASSERT(!HasStackOverflow()); |
4002 ASSERT(current_block() != NULL); | 3999 ASSERT(current_block() != NULL); |
4003 ASSERT(current_block()->HasPredecessor()); | 4000 ASSERT(current_block()->HasPredecessor()); |
4004 HConstant* instr = New<HConstant>(expr->value()); | 4001 HConstant* instr = New<HConstant>(expr->value()); |
4005 return ast_context()->ReturnInstruction(instr, expr->id()); | 4002 return ast_context()->ReturnInstruction(instr, expr->id()); |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4284 } | 4281 } |
4285 } else { | 4282 } else { |
4286 CHECK_ALIVE(VisitForEffect(value)); | 4283 CHECK_ALIVE(VisitForEffect(value)); |
4287 } | 4284 } |
4288 break; | 4285 break; |
4289 } | 4286 } |
4290 // Fall through. | 4287 // Fall through. |
4291 case ObjectLiteral::Property::PROTOTYPE: | 4288 case ObjectLiteral::Property::PROTOTYPE: |
4292 case ObjectLiteral::Property::SETTER: | 4289 case ObjectLiteral::Property::SETTER: |
4293 case ObjectLiteral::Property::GETTER: | 4290 case ObjectLiteral::Property::GETTER: |
4294 return Bailout("Object literal with complex property"); | 4291 return Bailout(kObjectLiteralWithComplexProperty); |
4295 default: UNREACHABLE(); | 4292 default: UNREACHABLE(); |
4296 } | 4293 } |
4297 } | 4294 } |
4298 | 4295 |
4299 if (expr->has_function()) { | 4296 if (expr->has_function()) { |
4300 // Return the result of the transformation to fast properties | 4297 // Return the result of the transformation to fast properties |
4301 // instead of the original since this operation changes the map | 4298 // instead of the original since this operation changes the map |
4302 // of the object. This makes sure that the original object won't | 4299 // of the object. This makes sure that the original object won't |
4303 // be used by other optimized code before it is transformed | 4300 // be used by other optimized code before it is transformed |
4304 // (e.g. because of code motion). | 4301 // (e.g. because of code motion). |
(...skipping 18 matching lines...) Expand all Loading... |
4323 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); | 4320 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); |
4324 bool uninitialized = false; | 4321 bool uninitialized = false; |
4325 Handle<Object> literals_cell(literals->get(expr->literal_index()), | 4322 Handle<Object> literals_cell(literals->get(expr->literal_index()), |
4326 isolate()); | 4323 isolate()); |
4327 Handle<Object> raw_boilerplate; | 4324 Handle<Object> raw_boilerplate; |
4328 if (literals_cell->IsUndefined()) { | 4325 if (literals_cell->IsUndefined()) { |
4329 uninitialized = true; | 4326 uninitialized = true; |
4330 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( | 4327 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( |
4331 isolate(), literals, expr->constant_elements()); | 4328 isolate(), literals, expr->constant_elements()); |
4332 if (raw_boilerplate.is_null()) { | 4329 if (raw_boilerplate.is_null()) { |
4333 return Bailout("array boilerplate creation failed"); | 4330 return Bailout(kArrayBoilerplateCreationFailed); |
4334 } | 4331 } |
4335 | 4332 |
4336 site = isolate()->factory()->NewAllocationSite(); | 4333 site = isolate()->factory()->NewAllocationSite(); |
4337 site->set_transition_info(*raw_boilerplate); | 4334 site->set_transition_info(*raw_boilerplate); |
4338 literals->set(expr->literal_index(), *site); | 4335 literals->set(expr->literal_index(), *site); |
4339 | 4336 |
4340 if (JSObject::cast(*raw_boilerplate)->elements()->map() == | 4337 if (JSObject::cast(*raw_boilerplate)->elements()->map() == |
4341 isolate()->heap()->fixed_cow_array_map()) { | 4338 isolate()->heap()->fixed_cow_array_map()) { |
4342 isolate()->counters()->cow_arrays_created_runtime()->Increment(); | 4339 isolate()->counters()->cow_arrays_created_runtime()->Increment(); |
4343 } | 4340 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4414 HInstruction* elements = NULL; | 4411 HInstruction* elements = NULL; |
4415 | 4412 |
4416 for (int i = 0; i < length; i++) { | 4413 for (int i = 0; i < length; i++) { |
4417 Expression* subexpr = subexprs->at(i); | 4414 Expression* subexpr = subexprs->at(i); |
4418 // If the subexpression is a literal or a simple materialized literal it | 4415 // If the subexpression is a literal or a simple materialized literal it |
4419 // is already set in the cloned array. | 4416 // is already set in the cloned array. |
4420 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 4417 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
4421 | 4418 |
4422 CHECK_ALIVE(VisitForValue(subexpr)); | 4419 CHECK_ALIVE(VisitForValue(subexpr)); |
4423 HValue* value = Pop(); | 4420 HValue* value = Pop(); |
4424 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); | 4421 if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral); |
4425 | 4422 |
4426 elements = AddLoadElements(literal); | 4423 elements = AddLoadElements(literal); |
4427 | 4424 |
4428 HValue* key = Add<HConstant>(i); | 4425 HValue* key = Add<HConstant>(i); |
4429 | 4426 |
4430 switch (boilerplate_elements_kind) { | 4427 switch (boilerplate_elements_kind) { |
4431 case FAST_SMI_ELEMENTS: | 4428 case FAST_SMI_ELEMENTS: |
4432 case FAST_HOLEY_SMI_ELEMENTS: | 4429 case FAST_HOLEY_SMI_ELEMENTS: |
4433 case FAST_ELEMENTS: | 4430 case FAST_ELEMENTS: |
4434 case FAST_HOLEY_ELEMENTS: | 4431 case FAST_HOLEY_ELEMENTS: |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4494 // readonly or turned into a setter by some meanwhile modifications on the | 4491 // readonly or turned into a setter by some meanwhile modifications on the |
4495 // prototype chain. | 4492 // prototype chain. |
4496 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { | 4493 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { |
4497 Object* proto = map->prototype(); | 4494 Object* proto = map->prototype(); |
4498 // First check that the prototype chain isn't affected already. | 4495 // First check that the prototype chain isn't affected already. |
4499 LookupResult proto_result(isolate()); | 4496 LookupResult proto_result(isolate()); |
4500 proto->Lookup(*name, &proto_result); | 4497 proto->Lookup(*name, &proto_result); |
4501 if (proto_result.IsProperty()) { | 4498 if (proto_result.IsProperty()) { |
4502 // If the inherited property could induce readonly-ness, bail out. | 4499 // If the inherited property could induce readonly-ness, bail out. |
4503 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) { | 4500 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) { |
4504 Bailout("improper object on prototype chain for store"); | 4501 Bailout(kImproperObjectOnPrototypeChainForStore); |
4505 return NULL; | 4502 return NULL; |
4506 } | 4503 } |
4507 // We only need to check up to the preexisting property. | 4504 // We only need to check up to the preexisting property. |
4508 proto = proto_result.holder(); | 4505 proto = proto_result.holder(); |
4509 } else { | 4506 } else { |
4510 // Otherwise, find the top prototype. | 4507 // Otherwise, find the top prototype. |
4511 while (proto->GetPrototype(isolate())->IsJSObject()) { | 4508 while (proto->GetPrototype(isolate())->IsJSObject()) { |
4512 proto = proto->GetPrototype(isolate()); | 4509 proto = proto->GetPrototype(isolate()); |
4513 } | 4510 } |
4514 ASSERT(proto->GetPrototype(isolate())->IsNull()); | 4511 ASSERT(proto->GetPrototype(isolate())->IsNull()); |
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4998 Property* prop = target->AsProperty(); | 4995 Property* prop = target->AsProperty(); |
4999 ASSERT(proxy == NULL || prop == NULL); | 4996 ASSERT(proxy == NULL || prop == NULL); |
5000 | 4997 |
5001 // We have a second position recorded in the FullCodeGenerator to have | 4998 // We have a second position recorded in the FullCodeGenerator to have |
5002 // type feedback for the binary operation. | 4999 // type feedback for the binary operation. |
5003 BinaryOperation* operation = expr->binary_operation(); | 5000 BinaryOperation* operation = expr->binary_operation(); |
5004 | 5001 |
5005 if (proxy != NULL) { | 5002 if (proxy != NULL) { |
5006 Variable* var = proxy->var(); | 5003 Variable* var = proxy->var(); |
5007 if (var->mode() == LET) { | 5004 if (var->mode() == LET) { |
5008 return Bailout("unsupported let compound assignment"); | 5005 return Bailout(kUnsupportedLetCompoundAssignment); |
5009 } | 5006 } |
5010 | 5007 |
5011 CHECK_ALIVE(VisitForValue(operation)); | 5008 CHECK_ALIVE(VisitForValue(operation)); |
5012 | 5009 |
5013 switch (var->location()) { | 5010 switch (var->location()) { |
5014 case Variable::UNALLOCATED: | 5011 case Variable::UNALLOCATED: |
5015 HandleGlobalVariableAssignment(var, | 5012 HandleGlobalVariableAssignment(var, |
5016 Top(), | 5013 Top(), |
5017 expr->position(), | 5014 expr->position(), |
5018 expr->AssignmentId()); | 5015 expr->AssignmentId()); |
5019 break; | 5016 break; |
5020 | 5017 |
5021 case Variable::PARAMETER: | 5018 case Variable::PARAMETER: |
5022 case Variable::LOCAL: | 5019 case Variable::LOCAL: |
5023 if (var->mode() == CONST) { | 5020 if (var->mode() == CONST) { |
5024 return Bailout("unsupported const compound assignment"); | 5021 return Bailout(kUnsupportedConstCompoundAssignment); |
5025 } | 5022 } |
5026 BindIfLive(var, Top()); | 5023 BindIfLive(var, Top()); |
5027 break; | 5024 break; |
5028 | 5025 |
5029 case Variable::CONTEXT: { | 5026 case Variable::CONTEXT: { |
5030 // Bail out if we try to mutate a parameter value in a function | 5027 // Bail out if we try to mutate a parameter value in a function |
5031 // using the arguments object. We do not (yet) correctly handle the | 5028 // using the arguments object. We do not (yet) correctly handle the |
5032 // arguments property of the function. | 5029 // arguments property of the function. |
5033 if (current_info()->scope()->arguments() != NULL) { | 5030 if (current_info()->scope()->arguments() != NULL) { |
5034 // Parameters will be allocated to context slots. We have no | 5031 // Parameters will be allocated to context slots. We have no |
5035 // direct way to detect that the variable is a parameter so we do | 5032 // direct way to detect that the variable is a parameter so we do |
5036 // a linear search of the parameter variables. | 5033 // a linear search of the parameter variables. |
5037 int count = current_info()->scope()->num_parameters(); | 5034 int count = current_info()->scope()->num_parameters(); |
5038 for (int i = 0; i < count; ++i) { | 5035 for (int i = 0; i < count; ++i) { |
5039 if (var == current_info()->scope()->parameter(i)) { | 5036 if (var == current_info()->scope()->parameter(i)) { |
5040 Bailout( | 5037 Bailout(kAssignmentToParameterFunctionUsesArgumentsObject); |
5041 "assignment to parameter, function uses arguments object"); | |
5042 } | 5038 } |
5043 } | 5039 } |
5044 } | 5040 } |
5045 | 5041 |
5046 HStoreContextSlot::Mode mode; | 5042 HStoreContextSlot::Mode mode; |
5047 | 5043 |
5048 switch (var->mode()) { | 5044 switch (var->mode()) { |
5049 case LET: | 5045 case LET: |
5050 mode = HStoreContextSlot::kCheckDeoptimize; | 5046 mode = HStoreContextSlot::kCheckDeoptimize; |
5051 break; | 5047 break; |
(...skipping 10 matching lines...) Expand all Loading... |
5062 HValue* context = BuildContextChainWalk(var); | 5058 HValue* context = BuildContextChainWalk(var); |
5063 HStoreContextSlot* instr = Add<HStoreContextSlot>( | 5059 HStoreContextSlot* instr = Add<HStoreContextSlot>( |
5064 context, var->index(), mode, Top()); | 5060 context, var->index(), mode, Top()); |
5065 if (instr->HasObservableSideEffects()) { | 5061 if (instr->HasObservableSideEffects()) { |
5066 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5062 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5067 } | 5063 } |
5068 break; | 5064 break; |
5069 } | 5065 } |
5070 | 5066 |
5071 case Variable::LOOKUP: | 5067 case Variable::LOOKUP: |
5072 return Bailout("compound assignment to lookup slot"); | 5068 return Bailout(kCompoundAssignmentToLookupSlot); |
5073 } | 5069 } |
5074 return ast_context()->ReturnValue(Pop()); | 5070 return ast_context()->ReturnValue(Pop()); |
5075 | 5071 |
5076 } else if (prop != NULL) { | 5072 } else if (prop != NULL) { |
5077 if (prop->key()->IsPropertyName()) { | 5073 if (prop->key()->IsPropertyName()) { |
5078 // Named property. | 5074 // Named property. |
5079 CHECK_ALIVE(VisitForValue(prop->obj())); | 5075 CHECK_ALIVE(VisitForValue(prop->obj())); |
5080 HValue* object = Top(); | 5076 HValue* object = Top(); |
5081 | 5077 |
5082 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 5078 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5151 | 5147 |
5152 // Drop the simulated receiver, key, and value. Return the value. | 5148 // Drop the simulated receiver, key, and value. Return the value. |
5153 Drop(3); | 5149 Drop(3); |
5154 Push(instr); | 5150 Push(instr); |
5155 ASSERT(has_side_effects); // Stores always have side effects. | 5151 ASSERT(has_side_effects); // Stores always have side effects. |
5156 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5152 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5157 return ast_context()->ReturnValue(Pop()); | 5153 return ast_context()->ReturnValue(Pop()); |
5158 } | 5154 } |
5159 | 5155 |
5160 } else { | 5156 } else { |
5161 return Bailout("invalid lhs in compound assignment"); | 5157 return Bailout(kInvalidLhsInCompoundAssignment); |
5162 } | 5158 } |
5163 } | 5159 } |
5164 | 5160 |
5165 | 5161 |
5166 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { | 5162 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { |
5167 ASSERT(!HasStackOverflow()); | 5163 ASSERT(!HasStackOverflow()); |
5168 ASSERT(current_block() != NULL); | 5164 ASSERT(current_block() != NULL); |
5169 ASSERT(current_block()->HasPredecessor()); | 5165 ASSERT(current_block()->HasPredecessor()); |
5170 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 5166 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
5171 Property* prop = expr->target()->AsProperty(); | 5167 Property* prop = expr->target()->AsProperty(); |
(...skipping 16 matching lines...) Expand all Loading... |
5188 } | 5184 } |
5189 | 5185 |
5190 if (var->IsStackAllocated()) { | 5186 if (var->IsStackAllocated()) { |
5191 // We insert a use of the old value to detect unsupported uses of const | 5187 // We insert a use of the old value to detect unsupported uses of const |
5192 // variables (e.g. initialization inside a loop). | 5188 // variables (e.g. initialization inside a loop). |
5193 HValue* old_value = environment()->Lookup(var); | 5189 HValue* old_value = environment()->Lookup(var); |
5194 Add<HUseConst>(old_value); | 5190 Add<HUseConst>(old_value); |
5195 } | 5191 } |
5196 } else if (var->mode() == CONST_HARMONY) { | 5192 } else if (var->mode() == CONST_HARMONY) { |
5197 if (expr->op() != Token::INIT_CONST_HARMONY) { | 5193 if (expr->op() != Token::INIT_CONST_HARMONY) { |
5198 return Bailout("non-initializer assignment to const"); | 5194 return Bailout(kNonInitializerAssignmentToConst); |
5199 } | 5195 } |
5200 } | 5196 } |
5201 | 5197 |
5202 if (proxy->IsArguments()) return Bailout("assignment to arguments"); | 5198 if (proxy->IsArguments()) return Bailout(kAssignmentToArguments); |
5203 | 5199 |
5204 // Handle the assignment. | 5200 // Handle the assignment. |
5205 switch (var->location()) { | 5201 switch (var->location()) { |
5206 case Variable::UNALLOCATED: | 5202 case Variable::UNALLOCATED: |
5207 CHECK_ALIVE(VisitForValue(expr->value())); | 5203 CHECK_ALIVE(VisitForValue(expr->value())); |
5208 HandleGlobalVariableAssignment(var, | 5204 HandleGlobalVariableAssignment(var, |
5209 Top(), | 5205 Top(), |
5210 expr->position(), | 5206 expr->position(), |
5211 expr->AssignmentId()); | 5207 expr->AssignmentId()); |
5212 return ast_context()->ReturnValue(Pop()); | 5208 return ast_context()->ReturnValue(Pop()); |
5213 | 5209 |
5214 case Variable::PARAMETER: | 5210 case Variable::PARAMETER: |
5215 case Variable::LOCAL: { | 5211 case Variable::LOCAL: { |
5216 // Perform an initialization check for let declared variables | 5212 // Perform an initialization check for let declared variables |
5217 // or parameters. | 5213 // or parameters. |
5218 if (var->mode() == LET && expr->op() == Token::ASSIGN) { | 5214 if (var->mode() == LET && expr->op() == Token::ASSIGN) { |
5219 HValue* env_value = environment()->Lookup(var); | 5215 HValue* env_value = environment()->Lookup(var); |
5220 if (env_value == graph()->GetConstantHole()) { | 5216 if (env_value == graph()->GetConstantHole()) { |
5221 return Bailout("assignment to let variable before initialization"); | 5217 return Bailout(kAssignmentToLetVariableBeforeInitialization); |
5222 } | 5218 } |
5223 } | 5219 } |
5224 // We do not allow the arguments object to occur in a context where it | 5220 // We do not allow the arguments object to occur in a context where it |
5225 // may escape, but assignments to stack-allocated locals are | 5221 // may escape, but assignments to stack-allocated locals are |
5226 // permitted. | 5222 // permitted. |
5227 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); | 5223 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); |
5228 HValue* value = Pop(); | 5224 HValue* value = Pop(); |
5229 BindIfLive(var, value); | 5225 BindIfLive(var, value); |
5230 return ast_context()->ReturnValue(value); | 5226 return ast_context()->ReturnValue(value); |
5231 } | 5227 } |
5232 | 5228 |
5233 case Variable::CONTEXT: { | 5229 case Variable::CONTEXT: { |
5234 // Bail out if we try to mutate a parameter value in a function using | 5230 // Bail out if we try to mutate a parameter value in a function using |
5235 // the arguments object. We do not (yet) correctly handle the | 5231 // the arguments object. We do not (yet) correctly handle the |
5236 // arguments property of the function. | 5232 // arguments property of the function. |
5237 if (current_info()->scope()->arguments() != NULL) { | 5233 if (current_info()->scope()->arguments() != NULL) { |
5238 // Parameters will rewrite to context slots. We have no direct way | 5234 // Parameters will rewrite to context slots. We have no direct way |
5239 // to detect that the variable is a parameter. | 5235 // to detect that the variable is a parameter. |
5240 int count = current_info()->scope()->num_parameters(); | 5236 int count = current_info()->scope()->num_parameters(); |
5241 for (int i = 0; i < count; ++i) { | 5237 for (int i = 0; i < count; ++i) { |
5242 if (var == current_info()->scope()->parameter(i)) { | 5238 if (var == current_info()->scope()->parameter(i)) { |
5243 return Bailout("assignment to parameter in arguments object"); | 5239 return Bailout(kAssignmentToParameterInArgumentsObject); |
5244 } | 5240 } |
5245 } | 5241 } |
5246 } | 5242 } |
5247 | 5243 |
5248 CHECK_ALIVE(VisitForValue(expr->value())); | 5244 CHECK_ALIVE(VisitForValue(expr->value())); |
5249 HStoreContextSlot::Mode mode; | 5245 HStoreContextSlot::Mode mode; |
5250 if (expr->op() == Token::ASSIGN) { | 5246 if (expr->op() == Token::ASSIGN) { |
5251 switch (var->mode()) { | 5247 switch (var->mode()) { |
5252 case LET: | 5248 case LET: |
5253 mode = HStoreContextSlot::kCheckDeoptimize; | 5249 mode = HStoreContextSlot::kCheckDeoptimize; |
(...skipping 20 matching lines...) Expand all Loading... |
5274 HValue* context = BuildContextChainWalk(var); | 5270 HValue* context = BuildContextChainWalk(var); |
5275 HStoreContextSlot* instr = Add<HStoreContextSlot>( | 5271 HStoreContextSlot* instr = Add<HStoreContextSlot>( |
5276 context, var->index(), mode, Top()); | 5272 context, var->index(), mode, Top()); |
5277 if (instr->HasObservableSideEffects()) { | 5273 if (instr->HasObservableSideEffects()) { |
5278 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5274 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5279 } | 5275 } |
5280 return ast_context()->ReturnValue(Pop()); | 5276 return ast_context()->ReturnValue(Pop()); |
5281 } | 5277 } |
5282 | 5278 |
5283 case Variable::LOOKUP: | 5279 case Variable::LOOKUP: |
5284 return Bailout("assignment to LOOKUP variable"); | 5280 return Bailout(kAssignmentToLOOKUPVariable); |
5285 } | 5281 } |
5286 } else { | 5282 } else { |
5287 return Bailout("invalid left-hand side in assignment"); | 5283 return Bailout(kInvalidLeftHandSideInAssignment); |
5288 } | 5284 } |
5289 } | 5285 } |
5290 | 5286 |
5291 | 5287 |
5292 void HOptimizedGraphBuilder::VisitYield(Yield* expr) { | 5288 void HOptimizedGraphBuilder::VisitYield(Yield* expr) { |
5293 // Generators are not optimized, so we should never get here. | 5289 // Generators are not optimized, so we should never get here. |
5294 UNREACHABLE(); | 5290 UNREACHABLE(); |
5295 } | 5291 } |
5296 | 5292 |
5297 | 5293 |
(...skipping 971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6269 return false; | 6265 return false; |
6270 } | 6266 } |
6271 | 6267 |
6272 // Parse and allocate variables. | 6268 // Parse and allocate variables. |
6273 CompilationInfo target_info(target, zone()); | 6269 CompilationInfo target_info(target, zone()); |
6274 Handle<SharedFunctionInfo> target_shared(target->shared()); | 6270 Handle<SharedFunctionInfo> target_shared(target->shared()); |
6275 if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info)) { | 6271 if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info)) { |
6276 if (target_info.isolate()->has_pending_exception()) { | 6272 if (target_info.isolate()->has_pending_exception()) { |
6277 // Parse or scope error, never optimize this function. | 6273 // Parse or scope error, never optimize this function. |
6278 SetStackOverflow(); | 6274 SetStackOverflow(); |
6279 target_shared->DisableOptimization("parse/scope error"); | 6275 target_shared->DisableOptimization(kParseScopeError); |
6280 } | 6276 } |
6281 TraceInline(target, caller, "parse failure"); | 6277 TraceInline(target, caller, "parse failure"); |
6282 return false; | 6278 return false; |
6283 } | 6279 } |
6284 | 6280 |
6285 if (target_info.scope()->num_heap_slots() > 0) { | 6281 if (target_info.scope()->num_heap_slots() > 0) { |
6286 TraceInline(target, caller, "target has context-allocated variables"); | 6282 TraceInline(target, caller, "target has context-allocated variables"); |
6287 return false; | 6283 return false; |
6288 } | 6284 } |
6289 FunctionLiteral* function = target_info.function(); | 6285 FunctionLiteral* function = target_info.function(); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6408 function->scope()->arguments(), | 6404 function->scope()->arguments(), |
6409 arguments_object, undefined_receiver); | 6405 arguments_object, undefined_receiver); |
6410 function_state()->set_entry(enter_inlined); | 6406 function_state()->set_entry(enter_inlined); |
6411 | 6407 |
6412 VisitDeclarations(target_info.scope()->declarations()); | 6408 VisitDeclarations(target_info.scope()->declarations()); |
6413 VisitStatements(function->body()); | 6409 VisitStatements(function->body()); |
6414 if (HasStackOverflow()) { | 6410 if (HasStackOverflow()) { |
6415 // Bail out if the inline function did, as we cannot residualize a call | 6411 // Bail out if the inline function did, as we cannot residualize a call |
6416 // instead. | 6412 // instead. |
6417 TraceInline(target, caller, "inline graph construction failed"); | 6413 TraceInline(target, caller, "inline graph construction failed"); |
6418 target_shared->DisableOptimization("inlining bailed out"); | 6414 target_shared->DisableOptimization(kInliningBailedOut); |
6419 inline_bailout_ = true; | 6415 inline_bailout_ = true; |
6420 delete target_state; | 6416 delete target_state; |
6421 return true; | 6417 return true; |
6422 } | 6418 } |
6423 | 6419 |
6424 // Update inlined nodes count. | 6420 // Update inlined nodes count. |
6425 inlined_count_ += nodes_added; | 6421 inlined_count_ += nodes_added; |
6426 | 6422 |
6427 Handle<Code> unoptimized_code(target_shared->code()); | 6423 Handle<Code> unoptimized_code(target_shared->code()); |
6428 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 6424 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6953 | 6949 |
6954 } else { | 6950 } else { |
6955 HValue* context = environment()->context(); | 6951 HValue* context = environment()->context(); |
6956 call = PreProcessCall( | 6952 call = PreProcessCall( |
6957 new(zone()) HCallNamed(context, name, argument_count)); | 6953 new(zone()) HCallNamed(context, name, argument_count)); |
6958 } | 6954 } |
6959 | 6955 |
6960 } else { | 6956 } else { |
6961 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 6957 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
6962 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 6958 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
6963 return Bailout("possible direct call to eval"); | 6959 return Bailout(kPossibleDirectCallToEval); |
6964 } | 6960 } |
6965 | 6961 |
6966 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); | 6962 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); |
6967 if (global_call) { | 6963 if (global_call) { |
6968 Variable* var = proxy->var(); | 6964 Variable* var = proxy->var(); |
6969 bool known_global_function = false; | 6965 bool known_global_function = false; |
6970 // If there is a global property cell for the name at compile time and | 6966 // If there is a global property cell for the name at compile time and |
6971 // access check is not enabled we assume that the function will not change | 6967 // access check is not enabled we assume that the function will not change |
6972 // and generate optimized code for calling the function. | 6968 // and generate optimized code for calling the function. |
6973 LookupResult lookup(isolate()); | 6969 LookupResult lookup(isolate()); |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7221 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 7217 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
7222 }; | 7218 }; |
7223 #undef INLINE_FUNCTION_GENERATOR_ADDRESS | 7219 #undef INLINE_FUNCTION_GENERATOR_ADDRESS |
7224 | 7220 |
7225 | 7221 |
7226 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 7222 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
7227 ASSERT(!HasStackOverflow()); | 7223 ASSERT(!HasStackOverflow()); |
7228 ASSERT(current_block() != NULL); | 7224 ASSERT(current_block() != NULL); |
7229 ASSERT(current_block()->HasPredecessor()); | 7225 ASSERT(current_block()->HasPredecessor()); |
7230 if (expr->is_jsruntime()) { | 7226 if (expr->is_jsruntime()) { |
7231 return Bailout("call to a JavaScript runtime function"); | 7227 return Bailout(kCallToAJavaScriptRuntimeFunction); |
7232 } | 7228 } |
7233 | 7229 |
7234 const Runtime::Function* function = expr->function(); | 7230 const Runtime::Function* function = expr->function(); |
7235 ASSERT(function != NULL); | 7231 ASSERT(function != NULL); |
7236 if (function->intrinsic_type == Runtime::INLINE) { | 7232 if (function->intrinsic_type == Runtime::INLINE) { |
7237 ASSERT(expr->name()->length() > 0); | 7233 ASSERT(expr->name()->length() > 0); |
7238 ASSERT(expr->name()->Get(0) == '_'); | 7234 ASSERT(expr->name()->Get(0) == '_'); |
7239 // Call to an inline function. | 7235 // Call to an inline function. |
7240 int lookup_index = static_cast<int>(function->function_id) - | 7236 int lookup_index = static_cast<int>(function->function_id) - |
7241 static_cast<int>(Runtime::kFirstInlineFunction); | 7237 static_cast<int>(Runtime::kFirstInlineFunction); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7288 Add<HPushArgument>(obj); | 7284 Add<HPushArgument>(obj); |
7289 Add<HPushArgument>(key); | 7285 Add<HPushArgument>(key); |
7290 Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag())); | 7286 Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag())); |
7291 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 7287 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
7292 // even though we are certain to pass the correct number of arguments here. | 7288 // even though we are certain to pass the correct number of arguments here. |
7293 HInstruction* instr = New<HInvokeFunction>(function, 3); | 7289 HInstruction* instr = New<HInvokeFunction>(function, 3); |
7294 return ast_context()->ReturnInstruction(instr, expr->id()); | 7290 return ast_context()->ReturnInstruction(instr, expr->id()); |
7295 } else if (proxy != NULL) { | 7291 } else if (proxy != NULL) { |
7296 Variable* var = proxy->var(); | 7292 Variable* var = proxy->var(); |
7297 if (var->IsUnallocated()) { | 7293 if (var->IsUnallocated()) { |
7298 Bailout("delete with global variable"); | 7294 Bailout(kDeleteWithGlobalVariable); |
7299 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 7295 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
7300 // Result of deleting non-global variables is false. 'this' is not | 7296 // Result of deleting non-global variables is false. 'this' is not |
7301 // really a variable, though we implement it as one. The | 7297 // really a variable, though we implement it as one. The |
7302 // subexpression does not have side effects. | 7298 // subexpression does not have side effects. |
7303 HValue* value = var->is_this() | 7299 HValue* value = var->is_this() |
7304 ? graph()->GetConstantTrue() | 7300 ? graph()->GetConstantTrue() |
7305 : graph()->GetConstantFalse(); | 7301 : graph()->GetConstantFalse(); |
7306 return ast_context()->ReturnValue(value); | 7302 return ast_context()->ReturnValue(value); |
7307 } else { | 7303 } else { |
7308 Bailout("delete with non-global variable"); | 7304 Bailout(kDeleteWithNonGlobalVariable); |
7309 } | 7305 } |
7310 } else { | 7306 } else { |
7311 // Result of deleting non-property, non-variable reference is true. | 7307 // Result of deleting non-property, non-variable reference is true. |
7312 // Evaluate the subexpression for side effects. | 7308 // Evaluate the subexpression for side effects. |
7313 CHECK_ALIVE(VisitForEffect(expr->expression())); | 7309 CHECK_ALIVE(VisitForEffect(expr->expression())); |
7314 return ast_context()->ReturnValue(graph()->GetConstantTrue()); | 7310 return ast_context()->ReturnValue(graph()->GetConstantTrue()); |
7315 } | 7311 } |
7316 } | 7312 } |
7317 | 7313 |
7318 | 7314 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7430 | 7426 |
7431 | 7427 |
7432 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { | 7428 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { |
7433 ASSERT(!HasStackOverflow()); | 7429 ASSERT(!HasStackOverflow()); |
7434 ASSERT(current_block() != NULL); | 7430 ASSERT(current_block() != NULL); |
7435 ASSERT(current_block()->HasPredecessor()); | 7431 ASSERT(current_block()->HasPredecessor()); |
7436 Expression* target = expr->expression(); | 7432 Expression* target = expr->expression(); |
7437 VariableProxy* proxy = target->AsVariableProxy(); | 7433 VariableProxy* proxy = target->AsVariableProxy(); |
7438 Property* prop = target->AsProperty(); | 7434 Property* prop = target->AsProperty(); |
7439 if (proxy == NULL && prop == NULL) { | 7435 if (proxy == NULL && prop == NULL) { |
7440 return Bailout("invalid lhs in count operation"); | 7436 return Bailout(kInvalidLhsInCountOperation); |
7441 } | 7437 } |
7442 | 7438 |
7443 // Match the full code generator stack by simulating an extra stack | 7439 // Match the full code generator stack by simulating an extra stack |
7444 // element for postfix operations in a non-effect context. The return | 7440 // element for postfix operations in a non-effect context. The return |
7445 // value is ToNumber(input). | 7441 // value is ToNumber(input). |
7446 bool returns_original_input = | 7442 bool returns_original_input = |
7447 expr->is_postfix() && !ast_context()->IsEffect(); | 7443 expr->is_postfix() && !ast_context()->IsEffect(); |
7448 HValue* input = NULL; // ToNumber(original_input). | 7444 HValue* input = NULL; // ToNumber(original_input). |
7449 HValue* after = NULL; // The result after incrementing or decrementing. | 7445 HValue* after = NULL; // The result after incrementing or decrementing. |
7450 | 7446 |
7451 if (proxy != NULL) { | 7447 if (proxy != NULL) { |
7452 Variable* var = proxy->var(); | 7448 Variable* var = proxy->var(); |
7453 if (var->mode() == CONST) { | 7449 if (var->mode() == CONST) { |
7454 return Bailout("unsupported count operation with const"); | 7450 return Bailout(kUnsupportedCountOperationWithConst); |
7455 } | 7451 } |
7456 // Argument of the count operation is a variable, not a property. | 7452 // Argument of the count operation is a variable, not a property. |
7457 ASSERT(prop == NULL); | 7453 ASSERT(prop == NULL); |
7458 CHECK_ALIVE(VisitForValue(target)); | 7454 CHECK_ALIVE(VisitForValue(target)); |
7459 | 7455 |
7460 after = BuildIncrement(returns_original_input, expr); | 7456 after = BuildIncrement(returns_original_input, expr); |
7461 input = returns_original_input ? Top() : Pop(); | 7457 input = returns_original_input ? Top() : Pop(); |
7462 Push(after); | 7458 Push(after); |
7463 | 7459 |
7464 switch (var->location()) { | 7460 switch (var->location()) { |
(...skipping 13 matching lines...) Expand all Loading... |
7478 // Bail out if we try to mutate a parameter value in a function | 7474 // Bail out if we try to mutate a parameter value in a function |
7479 // using the arguments object. We do not (yet) correctly handle the | 7475 // using the arguments object. We do not (yet) correctly handle the |
7480 // arguments property of the function. | 7476 // arguments property of the function. |
7481 if (current_info()->scope()->arguments() != NULL) { | 7477 if (current_info()->scope()->arguments() != NULL) { |
7482 // Parameters will rewrite to context slots. We have no direct | 7478 // Parameters will rewrite to context slots. We have no direct |
7483 // way to detect that the variable is a parameter so we use a | 7479 // way to detect that the variable is a parameter so we use a |
7484 // linear search of the parameter list. | 7480 // linear search of the parameter list. |
7485 int count = current_info()->scope()->num_parameters(); | 7481 int count = current_info()->scope()->num_parameters(); |
7486 for (int i = 0; i < count; ++i) { | 7482 for (int i = 0; i < count; ++i) { |
7487 if (var == current_info()->scope()->parameter(i)) { | 7483 if (var == current_info()->scope()->parameter(i)) { |
7488 return Bailout("assignment to parameter in arguments object"); | 7484 return Bailout(kAssignmentToParameterInArgumentsObject); |
7489 } | 7485 } |
7490 } | 7486 } |
7491 } | 7487 } |
7492 | 7488 |
7493 HValue* context = BuildContextChainWalk(var); | 7489 HValue* context = BuildContextChainWalk(var); |
7494 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) | 7490 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) |
7495 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; | 7491 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; |
7496 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 7492 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), |
7497 mode, after); | 7493 mode, after); |
7498 if (instr->HasObservableSideEffects()) { | 7494 if (instr->HasObservableSideEffects()) { |
7499 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7495 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
7500 } | 7496 } |
7501 break; | 7497 break; |
7502 } | 7498 } |
7503 | 7499 |
7504 case Variable::LOOKUP: | 7500 case Variable::LOOKUP: |
7505 return Bailout("lookup variable in count operation"); | 7501 return Bailout(kLookupVariableInCountOperation); |
7506 } | 7502 } |
7507 | 7503 |
7508 } else { | 7504 } else { |
7509 // Argument of the count operation is a property. | 7505 // Argument of the count operation is a property. |
7510 ASSERT(prop != NULL); | 7506 ASSERT(prop != NULL); |
7511 | 7507 |
7512 if (prop->key()->IsPropertyName()) { | 7508 if (prop->key()->IsPropertyName()) { |
7513 // Named property. | 7509 // Named property. |
7514 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 7510 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
7515 | 7511 |
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8104 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 8100 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
8105 BuildCheckHeapObject(right); | 8101 BuildCheckHeapObject(right); |
8106 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 8102 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
8107 HCompareObjectEqAndBranch* result = | 8103 HCompareObjectEqAndBranch* result = |
8108 new(zone()) HCompareObjectEqAndBranch(left, right); | 8104 new(zone()) HCompareObjectEqAndBranch(left, right); |
8109 result->set_position(expr->position()); | 8105 result->set_position(expr->position()); |
8110 return ast_context()->ReturnControl(result, expr->id()); | 8106 return ast_context()->ReturnControl(result, expr->id()); |
8111 } | 8107 } |
8112 } | 8108 } |
8113 default: | 8109 default: |
8114 return Bailout("Unsupported non-primitive compare"); | 8110 return Bailout(kUnsupportedNonPrimitiveCompare); |
8115 } | 8111 } |
8116 } else if (combined_type->Is(Type::InternalizedString()) && | 8112 } else if (combined_type->Is(Type::InternalizedString()) && |
8117 Token::IsEqualityOp(op)) { | 8113 Token::IsEqualityOp(op)) { |
8118 BuildCheckHeapObject(left); | 8114 BuildCheckHeapObject(left); |
8119 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); | 8115 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); |
8120 BuildCheckHeapObject(right); | 8116 BuildCheckHeapObject(right); |
8121 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); | 8117 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); |
8122 HCompareObjectEqAndBranch* result = | 8118 HCompareObjectEqAndBranch* result = |
8123 new(zone()) HCompareObjectEqAndBranch(left, right); | 8119 new(zone()) HCompareObjectEqAndBranch(left, right); |
8124 result->set_position(expr->position()); | 8120 result->set_position(expr->position()); |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8571 HValue* value = graph()->GetConstantHole(); | 8567 HValue* value = graph()->GetConstantHole(); |
8572 HValue* context = environment()->context(); | 8568 HValue* context = environment()->context(); |
8573 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8569 HStoreContextSlot* store = Add<HStoreContextSlot>( |
8574 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8570 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
8575 if (store->HasObservableSideEffects()) { | 8571 if (store->HasObservableSideEffects()) { |
8576 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); | 8572 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
8577 } | 8573 } |
8578 } | 8574 } |
8579 break; | 8575 break; |
8580 case Variable::LOOKUP: | 8576 case Variable::LOOKUP: |
8581 return Bailout("unsupported lookup slot in declaration"); | 8577 return Bailout(kUnsupportedLookupSlotInDeclaration); |
8582 } | 8578 } |
8583 } | 8579 } |
8584 | 8580 |
8585 | 8581 |
8586 void HOptimizedGraphBuilder::VisitFunctionDeclaration( | 8582 void HOptimizedGraphBuilder::VisitFunctionDeclaration( |
8587 FunctionDeclaration* declaration) { | 8583 FunctionDeclaration* declaration) { |
8588 VariableProxy* proxy = declaration->proxy(); | 8584 VariableProxy* proxy = declaration->proxy(); |
8589 Variable* variable = proxy->var(); | 8585 Variable* variable = proxy->var(); |
8590 switch (variable->location()) { | 8586 switch (variable->location()) { |
8591 case Variable::UNALLOCATED: { | 8587 case Variable::UNALLOCATED: { |
(...skipping 17 matching lines...) Expand all Loading... |
8609 HValue* value = Pop(); | 8605 HValue* value = Pop(); |
8610 HValue* context = environment()->context(); | 8606 HValue* context = environment()->context(); |
8611 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8607 HStoreContextSlot* store = Add<HStoreContextSlot>( |
8612 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8608 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
8613 if (store->HasObservableSideEffects()) { | 8609 if (store->HasObservableSideEffects()) { |
8614 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); | 8610 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
8615 } | 8611 } |
8616 break; | 8612 break; |
8617 } | 8613 } |
8618 case Variable::LOOKUP: | 8614 case Variable::LOOKUP: |
8619 return Bailout("unsupported lookup slot in declaration"); | 8615 return Bailout(kUnsupportedLookupSlotInDeclaration); |
8620 } | 8616 } |
8621 } | 8617 } |
8622 | 8618 |
8623 | 8619 |
8624 void HOptimizedGraphBuilder::VisitModuleDeclaration( | 8620 void HOptimizedGraphBuilder::VisitModuleDeclaration( |
8625 ModuleDeclaration* declaration) { | 8621 ModuleDeclaration* declaration) { |
8626 UNREACHABLE(); | 8622 UNREACHABLE(); |
8627 } | 8623 } |
8628 | 8624 |
8629 | 8625 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8730 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) { | 8726 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) { |
8731 ASSERT(call->arguments()->length() == 1); | 8727 ASSERT(call->arguments()->length() == 1); |
8732 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8728 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8733 HValue* value = Pop(); | 8729 HValue* value = Pop(); |
8734 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); | 8730 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); |
8735 return ast_context()->ReturnControl(result, call->id()); | 8731 return ast_context()->ReturnControl(result, call->id()); |
8736 } | 8732 } |
8737 | 8733 |
8738 | 8734 |
8739 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { | 8735 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { |
8740 return Bailout("inlined runtime function: IsNonNegativeSmi"); | 8736 return Bailout(kInlinedRuntimeFunctionIsNonNegativeSmi); |
8741 } | 8737 } |
8742 | 8738 |
8743 | 8739 |
8744 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { | 8740 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { |
8745 ASSERT(call->arguments()->length() == 1); | 8741 ASSERT(call->arguments()->length() == 1); |
8746 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8742 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8747 HValue* value = Pop(); | 8743 HValue* value = Pop(); |
8748 HIsUndetectableAndBranch* result = | 8744 HIsUndetectableAndBranch* result = |
8749 new(zone()) HIsUndetectableAndBranch(value); | 8745 new(zone()) HIsUndetectableAndBranch(value); |
8750 return ast_context()->ReturnControl(result, call->id()); | 8746 return ast_context()->ReturnControl(result, call->id()); |
8751 } | 8747 } |
8752 | 8748 |
8753 | 8749 |
8754 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( | 8750 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( |
8755 CallRuntime* call) { | 8751 CallRuntime* call) { |
8756 return Bailout( | 8752 return Bailout(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf); |
8757 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); | |
8758 } | 8753 } |
8759 | 8754 |
8760 | 8755 |
8761 // Support for construct call checks. | 8756 // Support for construct call checks. |
8762 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { | 8757 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { |
8763 ASSERT(call->arguments()->length() == 0); | 8758 ASSERT(call->arguments()->length() == 0); |
8764 if (function_state()->outer() != NULL) { | 8759 if (function_state()->outer() != NULL) { |
8765 // We are generating graph for inlined function. | 8760 // We are generating graph for inlined function. |
8766 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN | 8761 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN |
8767 ? graph()->GetConstantTrue() | 8762 ? graph()->GetConstantTrue() |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8801 HAccessArgumentsAt* result = | 8796 HAccessArgumentsAt* result = |
8802 new(zone()) HAccessArgumentsAt(elements, length, checked_index); | 8797 new(zone()) HAccessArgumentsAt(elements, length, checked_index); |
8803 return ast_context()->ReturnInstruction(result, call->id()); | 8798 return ast_context()->ReturnInstruction(result, call->id()); |
8804 } | 8799 } |
8805 | 8800 |
8806 | 8801 |
8807 // Support for accessing the class and value fields of an object. | 8802 // Support for accessing the class and value fields of an object. |
8808 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { | 8803 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { |
8809 // The special form detected by IsClassOfTest is detected before we get here | 8804 // The special form detected by IsClassOfTest is detected before we get here |
8810 // and does not cause a bailout. | 8805 // and does not cause a bailout. |
8811 return Bailout("inlined runtime function: ClassOf"); | 8806 return Bailout(kInlinedRuntimeFunctionClassOf); |
8812 } | 8807 } |
8813 | 8808 |
8814 | 8809 |
8815 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) { | 8810 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) { |
8816 ASSERT(call->arguments()->length() == 1); | 8811 ASSERT(call->arguments()->length() == 1); |
8817 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8812 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8818 HValue* value = Pop(); | 8813 HValue* value = Pop(); |
8819 HValueOf* result = new(zone()) HValueOf(value); | 8814 HValueOf* result = new(zone()) HValueOf(value); |
8820 return ast_context()->ReturnInstruction(result, call->id()); | 8815 return ast_context()->ReturnInstruction(result, call->id()); |
8821 } | 8816 } |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9018 HValue* context = environment()->context(); | 9013 HValue* context = environment()->context(); |
9019 HCallStub* result = | 9014 HCallStub* result = |
9020 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); | 9015 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); |
9021 Drop(3); | 9016 Drop(3); |
9022 return ast_context()->ReturnInstruction(result, call->id()); | 9017 return ast_context()->ReturnInstruction(result, call->id()); |
9023 } | 9018 } |
9024 | 9019 |
9025 | 9020 |
9026 // Support for fast native caches. | 9021 // Support for fast native caches. |
9027 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 9022 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
9028 return Bailout("inlined runtime function: GetFromCache"); | 9023 return Bailout(kInlinedRuntimeFunctionGetFromCache); |
9029 } | 9024 } |
9030 | 9025 |
9031 | 9026 |
9032 // Fast support for number to string. | 9027 // Fast support for number to string. |
9033 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 9028 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
9034 ASSERT_EQ(1, call->arguments()->length()); | 9029 ASSERT_EQ(1, call->arguments()->length()); |
9035 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9030 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9036 HValue* context = environment()->context(); | 9031 HValue* context = environment()->context(); |
9037 HCallStub* result = | 9032 HCallStub* result = |
9038 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); | 9033 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9148 HValue* value = Pop(); | 9143 HValue* value = Pop(); |
9149 HValue* context = environment()->context(); | 9144 HValue* context = environment()->context(); |
9150 HInstruction* result = | 9145 HInstruction* result = |
9151 HUnaryMathOperation::New(zone(), context, value, kMathSqrt); | 9146 HUnaryMathOperation::New(zone(), context, value, kMathSqrt); |
9152 return ast_context()->ReturnInstruction(result, call->id()); | 9147 return ast_context()->ReturnInstruction(result, call->id()); |
9153 } | 9148 } |
9154 | 9149 |
9155 | 9150 |
9156 // Check whether two RegExps are equivalent | 9151 // Check whether two RegExps are equivalent |
9157 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { | 9152 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
9158 return Bailout("inlined runtime function: IsRegExpEquivalent"); | 9153 return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent); |
9159 } | 9154 } |
9160 | 9155 |
9161 | 9156 |
9162 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { | 9157 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { |
9163 ASSERT(call->arguments()->length() == 1); | 9158 ASSERT(call->arguments()->length() == 1); |
9164 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9159 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9165 HValue* value = Pop(); | 9160 HValue* value = Pop(); |
9166 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); | 9161 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); |
9167 return ast_context()->ReturnInstruction(result, call->id()); | 9162 return ast_context()->ReturnInstruction(result, call->id()); |
9168 } | 9163 } |
9169 | 9164 |
9170 | 9165 |
9171 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { | 9166 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { |
9172 return Bailout("inlined runtime function: FastAsciiArrayJoin"); | 9167 return Bailout(kInlinedRuntimeFunctionFastAsciiArrayJoin); |
9173 } | 9168 } |
9174 | 9169 |
9175 | 9170 |
9176 // Support for generators. | 9171 // Support for generators. |
9177 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) { | 9172 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) { |
9178 return Bailout("inlined runtime function: GeneratorNext"); | 9173 return Bailout(kInlinedRuntimeFunctionGeneratorNext); |
9179 } | 9174 } |
9180 | 9175 |
9181 | 9176 |
9182 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) { | 9177 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) { |
9183 return Bailout("inlined runtime function: GeneratorThrow"); | 9178 return Bailout(kInlinedRuntimeFunctionGeneratorThrow); |
9184 } | 9179 } |
9185 | 9180 |
9186 | 9181 |
9187 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode( | 9182 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode( |
9188 CallRuntime* call) { | 9183 CallRuntime* call) { |
9189 AddInstruction(new(zone()) HDebugBreak()); | 9184 AddInstruction(new(zone()) HDebugBreak()); |
9190 return ast_context()->ReturnValue(graph()->GetConstant0()); | 9185 return ast_context()->ReturnValue(graph()->GetConstant0()); |
9191 } | 9186 } |
9192 | 9187 |
9193 | 9188 |
(...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9799 if (ShouldProduceTraceOutput()) { | 9794 if (ShouldProduceTraceOutput()) { |
9800 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9795 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9801 } | 9796 } |
9802 | 9797 |
9803 #ifdef DEBUG | 9798 #ifdef DEBUG |
9804 graph_->Verify(false); // No full verify. | 9799 graph_->Verify(false); // No full verify. |
9805 #endif | 9800 #endif |
9806 } | 9801 } |
9807 | 9802 |
9808 } } // namespace v8::internal | 9803 } } // namespace v8::internal |
OLD | NEW |