| 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 |