Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: src/hydrogen.cc

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

Powered by Google App Engine
This is Rietveld 408576698