| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/ast-graph-builder.h" | 5 #include "src/compiler/ast-graph-builder.h" |
| 6 | 6 |
| 7 #include "src/ast/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/compilation-info.h" | 9 #include "src/compilation-info.h" |
| 10 #include "src/compiler.h" | 10 #include "src/compiler.h" |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 if (closure_scope->is_script_scope() || | 298 if (closure_scope->is_script_scope() || |
| 299 closure_scope->is_module_scope()) { | 299 closure_scope->is_module_scope()) { |
| 300 // Contexts nested in the native context have a canonical empty function as | 300 // Contexts nested in the native context have a canonical empty function as |
| 301 // their closure, not the anonymous closure containing the global code. | 301 // their closure, not the anonymous closure containing the global code. |
| 302 return BuildLoadNativeContextField(Context::CLOSURE_INDEX); | 302 return BuildLoadNativeContextField(Context::CLOSURE_INDEX); |
| 303 } else if (closure_scope->is_eval_scope()) { | 303 } else if (closure_scope->is_eval_scope()) { |
| 304 // Contexts nested inside eval code have the same closure as the context | 304 // Contexts nested inside eval code have the same closure as the context |
| 305 // calling eval, not the anonymous closure containing the eval code. | 305 // calling eval, not the anonymous closure containing the eval code. |
| 306 const Operator* op = | 306 const Operator* op = |
| 307 javascript()->LoadContext(0, Context::CLOSURE_INDEX, false); | 307 javascript()->LoadContext(0, Context::CLOSURE_INDEX, false); |
| 308 return NewNode(op, current_context()); | 308 return NewNode(op); |
| 309 } else { | 309 } else { |
| 310 DCHECK(closure_scope->is_function_scope()); | 310 DCHECK(closure_scope->is_function_scope()); |
| 311 return GetFunctionClosure(); | 311 return GetFunctionClosure(); |
| 312 } | 312 } |
| 313 } | 313 } |
| 314 | 314 |
| 315 | 315 |
| 316 Node* AstGraphBuilder::GetFunctionClosure() { | 316 Node* AstGraphBuilder::GetFunctionClosure() { |
| 317 if (!function_closure_.is_set()) { | 317 if (!function_closure_.is_set()) { |
| 318 int index = Linkage::kJSCallClosureParamIndex; | 318 int index = Linkage::kJSCallClosureParamIndex; |
| (...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 case VariableLocation::LOCAL: | 938 case VariableLocation::LOCAL: |
| 939 if (variable->binding_needs_init()) { | 939 if (variable->binding_needs_init()) { |
| 940 Node* value = jsgraph()->TheHoleConstant(); | 940 Node* value = jsgraph()->TheHoleConstant(); |
| 941 environment()->Bind(variable, value); | 941 environment()->Bind(variable, value); |
| 942 } | 942 } |
| 943 break; | 943 break; |
| 944 case VariableLocation::CONTEXT: | 944 case VariableLocation::CONTEXT: |
| 945 if (variable->binding_needs_init()) { | 945 if (variable->binding_needs_init()) { |
| 946 Node* value = jsgraph()->TheHoleConstant(); | 946 Node* value = jsgraph()->TheHoleConstant(); |
| 947 const Operator* op = javascript()->StoreContext(0, variable->index()); | 947 const Operator* op = javascript()->StoreContext(0, variable->index()); |
| 948 NewNode(op, current_context(), value); | 948 NewNode(op, value); |
| 949 } | 949 } |
| 950 break; | 950 break; |
| 951 case VariableLocation::LOOKUP: | 951 case VariableLocation::LOOKUP: |
| 952 case VariableLocation::MODULE: | 952 case VariableLocation::MODULE: |
| 953 UNREACHABLE(); | 953 UNREACHABLE(); |
| 954 } | 954 } |
| 955 } | 955 } |
| 956 | 956 |
| 957 | 957 |
| 958 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 958 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 974 case VariableLocation::LOCAL: { | 974 case VariableLocation::LOCAL: { |
| 975 VisitForValue(decl->fun()); | 975 VisitForValue(decl->fun()); |
| 976 Node* value = environment()->Pop(); | 976 Node* value = environment()->Pop(); |
| 977 environment()->Bind(variable, value); | 977 environment()->Bind(variable, value); |
| 978 break; | 978 break; |
| 979 } | 979 } |
| 980 case VariableLocation::CONTEXT: { | 980 case VariableLocation::CONTEXT: { |
| 981 VisitForValue(decl->fun()); | 981 VisitForValue(decl->fun()); |
| 982 Node* value = environment()->Pop(); | 982 Node* value = environment()->Pop(); |
| 983 const Operator* op = javascript()->StoreContext(0, variable->index()); | 983 const Operator* op = javascript()->StoreContext(0, variable->index()); |
| 984 NewNode(op, current_context(), value); | 984 NewNode(op, value); |
| 985 break; | 985 break; |
| 986 } | 986 } |
| 987 case VariableLocation::LOOKUP: | 987 case VariableLocation::LOOKUP: |
| 988 case VariableLocation::MODULE: | 988 case VariableLocation::MODULE: |
| 989 UNREACHABLE(); | 989 UNREACHABLE(); |
| 990 } | 990 } |
| 991 } | 991 } |
| 992 | 992 |
| 993 | 993 |
| 994 void AstGraphBuilder::VisitBlock(Block* stmt) { | 994 void AstGraphBuilder::VisitBlock(Block* stmt) { |
| (...skipping 1648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2643 Node* local_context = scope->is_script_scope() | 2643 Node* local_context = scope->is_script_scope() |
| 2644 ? BuildLocalScriptContext(scope) | 2644 ? BuildLocalScriptContext(scope) |
| 2645 : BuildLocalFunctionContext(scope); | 2645 : BuildLocalFunctionContext(scope); |
| 2646 | 2646 |
| 2647 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { | 2647 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { |
| 2648 Node* receiver = environment()->RawParameterLookup(0); | 2648 Node* receiver = environment()->RawParameterLookup(0); |
| 2649 // Context variable (at bottom of the context chain). | 2649 // Context variable (at bottom of the context chain). |
| 2650 Variable* variable = scope->receiver(); | 2650 Variable* variable = scope->receiver(); |
| 2651 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 2651 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); |
| 2652 const Operator* op = javascript()->StoreContext(0, variable->index()); | 2652 const Operator* op = javascript()->StoreContext(0, variable->index()); |
| 2653 NewNode(op, local_context, receiver); | 2653 Node* node = NewNode(op, receiver); |
| 2654 NodeProperties::ReplaceContextInput(node, local_context); |
| 2654 } | 2655 } |
| 2655 | 2656 |
| 2656 // Copy parameters into context if necessary. | 2657 // Copy parameters into context if necessary. |
| 2657 int num_parameters = scope->num_parameters(); | 2658 int num_parameters = scope->num_parameters(); |
| 2658 for (int i = 0; i < num_parameters; i++) { | 2659 for (int i = 0; i < num_parameters; i++) { |
| 2659 Variable* variable = scope->parameter(i); | 2660 Variable* variable = scope->parameter(i); |
| 2660 if (!variable->IsContextSlot()) continue; | 2661 if (!variable->IsContextSlot()) continue; |
| 2661 Node* parameter = environment()->RawParameterLookup(i + 1); | 2662 Node* parameter = environment()->RawParameterLookup(i + 1); |
| 2662 // Context variable (at bottom of the context chain). | 2663 // Context variable (at bottom of the context chain). |
| 2663 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 2664 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); |
| 2664 const Operator* op = javascript()->StoreContext(0, variable->index()); | 2665 const Operator* op = javascript()->StoreContext(0, variable->index()); |
| 2665 NewNode(op, local_context, parameter); | 2666 Node* node = NewNode(op, parameter); |
| 2667 NodeProperties::ReplaceContextInput(node, local_context); |
| 2666 } | 2668 } |
| 2667 | 2669 |
| 2668 return local_context; | 2670 return local_context; |
| 2669 } | 2671 } |
| 2670 | 2672 |
| 2671 | 2673 |
| 2672 Node* AstGraphBuilder::BuildLocalFunctionContext(Scope* scope) { | 2674 Node* AstGraphBuilder::BuildLocalFunctionContext(Scope* scope) { |
| 2673 DCHECK(scope->is_function_scope() || scope->is_eval_scope()); | 2675 DCHECK(scope->is_function_scope() || scope->is_eval_scope()); |
| 2674 | 2676 |
| 2675 // Allocate a new local context. | 2677 // Allocate a new local context. |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2794 case VariableLocation::CONTEXT: { | 2796 case VariableLocation::CONTEXT: { |
| 2795 // Context variable (potentially up the context chain). | 2797 // Context variable (potentially up the context chain). |
| 2796 int depth = current_scope()->ContextChainLength(variable->scope()); | 2798 int depth = current_scope()->ContextChainLength(variable->scope()); |
| 2797 // TODO(mstarzinger): The {maybe_assigned} flag computed during variable | 2799 // TODO(mstarzinger): The {maybe_assigned} flag computed during variable |
| 2798 // resolution is highly inaccurate and cannot be trusted. We are only | 2800 // resolution is highly inaccurate and cannot be trusted. We are only |
| 2799 // taking this information into account when asm.js compilation is used. | 2801 // taking this information into account when asm.js compilation is used. |
| 2800 bool immutable = variable->maybe_assigned() == kNotAssigned && | 2802 bool immutable = variable->maybe_assigned() == kNotAssigned && |
| 2801 info()->is_function_context_specializing(); | 2803 info()->is_function_context_specializing(); |
| 2802 const Operator* op = | 2804 const Operator* op = |
| 2803 javascript()->LoadContext(depth, variable->index(), immutable); | 2805 javascript()->LoadContext(depth, variable->index(), immutable); |
| 2804 Node* value = NewNode(op, current_context()); | 2806 Node* value = NewNode(op); |
| 2805 // TODO(titzer): initialization checks are redundant for already | 2807 // TODO(titzer): initialization checks are redundant for already |
| 2806 // initialized immutable context loads, but only specialization knows. | 2808 // initialized immutable context loads, but only specialization knows. |
| 2807 // Maybe specializer should be a parameter to the graph builder? | 2809 // Maybe specializer should be a parameter to the graph builder? |
| 2808 if (variable->binding_needs_init()) { | 2810 if (variable->binding_needs_init()) { |
| 2809 // Perform check for uninitialized let/const variables. | 2811 // Perform check for uninitialized let/const variables. |
| 2810 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id); | 2812 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id); |
| 2811 } | 2813 } |
| 2812 return value; | 2814 return value; |
| 2813 } | 2815 } |
| 2814 case VariableLocation::LOOKUP: | 2816 case VariableLocation::LOOKUP: |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2911 } | 2913 } |
| 2912 environment()->Bind(variable, value); | 2914 environment()->Bind(variable, value); |
| 2913 return value; | 2915 return value; |
| 2914 case VariableLocation::CONTEXT: { | 2916 case VariableLocation::CONTEXT: { |
| 2915 // Context variable (potentially up the context chain). | 2917 // Context variable (potentially up the context chain). |
| 2916 int depth = current_scope()->ContextChainLength(variable->scope()); | 2918 int depth = current_scope()->ContextChainLength(variable->scope()); |
| 2917 if (mode == LET && op != Token::INIT && variable->binding_needs_init()) { | 2919 if (mode == LET && op != Token::INIT && variable->binding_needs_init()) { |
| 2918 // Perform an initialization check for let declared variables. | 2920 // Perform an initialization check for let declared variables. |
| 2919 const Operator* op = | 2921 const Operator* op = |
| 2920 javascript()->LoadContext(depth, variable->index(), false); | 2922 javascript()->LoadContext(depth, variable->index(), false); |
| 2921 Node* current = NewNode(op, current_context()); | 2923 Node* current = NewNode(op); |
| 2922 value = BuildHoleCheckThenThrow(current, variable, value, bailout_id); | 2924 value = BuildHoleCheckThenThrow(current, variable, value, bailout_id); |
| 2923 } else if (mode == CONST && op == Token::INIT) { | 2925 } else if (mode == CONST && op == Token::INIT) { |
| 2924 // Perform an initialization check for const {this} variables. | 2926 // Perform an initialization check for const {this} variables. |
| 2925 // Note that the {this} variable is the only const variable being able | 2927 // Note that the {this} variable is the only const variable being able |
| 2926 // to trigger bind operations outside the TDZ, via {super} calls. | 2928 // to trigger bind operations outside the TDZ, via {super} calls. |
| 2927 if (variable->is_this()) { | 2929 if (variable->is_this()) { |
| 2928 const Operator* op = | 2930 const Operator* op = |
| 2929 javascript()->LoadContext(depth, variable->index(), false); | 2931 javascript()->LoadContext(depth, variable->index(), false); |
| 2930 Node* current = NewNode(op, current_context()); | 2932 Node* current = NewNode(op); |
| 2931 value = BuildHoleCheckElseThrow(current, variable, value, bailout_id); | 2933 value = BuildHoleCheckElseThrow(current, variable, value, bailout_id); |
| 2932 } | 2934 } |
| 2933 } else if (mode == CONST && op != Token::INIT && | 2935 } else if (mode == CONST && op != Token::INIT && |
| 2934 variable->is_sloppy_function_name()) { | 2936 variable->is_sloppy_function_name()) { |
| 2935 // Non-initializing assignment to sloppy function names is | 2937 // Non-initializing assignment to sloppy function names is |
| 2936 // - exception in strict mode. | 2938 // - exception in strict mode. |
| 2937 // - ignored in sloppy mode. | 2939 // - ignored in sloppy mode. |
| 2938 DCHECK(!variable->binding_needs_init()); | 2940 DCHECK(!variable->binding_needs_init()); |
| 2939 if (variable->throw_on_const_assignment(language_mode())) { | 2941 if (variable->throw_on_const_assignment(language_mode())) { |
| 2940 return BuildThrowConstAssignError(bailout_id); | 2942 return BuildThrowConstAssignError(bailout_id); |
| 2941 } | 2943 } |
| 2942 return value; | 2944 return value; |
| 2943 } else if (mode == CONST && op != Token::INIT) { | 2945 } else if (mode == CONST && op != Token::INIT) { |
| 2944 if (variable->binding_needs_init()) { | 2946 if (variable->binding_needs_init()) { |
| 2945 const Operator* op = | 2947 const Operator* op = |
| 2946 javascript()->LoadContext(depth, variable->index(), false); | 2948 javascript()->LoadContext(depth, variable->index(), false); |
| 2947 Node* current = NewNode(op, current_context()); | 2949 Node* current = NewNode(op); |
| 2948 BuildHoleCheckThenThrow(current, variable, value, bailout_id); | 2950 BuildHoleCheckThenThrow(current, variable, value, bailout_id); |
| 2949 } | 2951 } |
| 2950 // Assignment to const is exception in all modes. | 2952 // Assignment to const is exception in all modes. |
| 2951 return BuildThrowConstAssignError(bailout_id); | 2953 return BuildThrowConstAssignError(bailout_id); |
| 2952 } | 2954 } |
| 2953 const Operator* op = javascript()->StoreContext(depth, variable->index()); | 2955 const Operator* op = javascript()->StoreContext(depth, variable->index()); |
| 2954 return NewNode(op, current_context(), value); | 2956 return NewNode(op, value); |
| 2955 } | 2957 } |
| 2956 case VariableLocation::LOOKUP: | 2958 case VariableLocation::LOOKUP: |
| 2957 case VariableLocation::MODULE: | 2959 case VariableLocation::MODULE: |
| 2958 UNREACHABLE(); | 2960 UNREACHABLE(); |
| 2959 } | 2961 } |
| 2960 UNREACHABLE(); | 2962 UNREACHABLE(); |
| 2961 return nullptr; | 2963 return nullptr; |
| 2962 } | 2964 } |
| 2963 | 2965 |
| 2964 | 2966 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3056 } | 3058 } |
| 3057 | 3059 |
| 3058 Node* AstGraphBuilder::BuildLoadGlobalObject() { | 3060 Node* AstGraphBuilder::BuildLoadGlobalObject() { |
| 3059 return BuildLoadNativeContextField(Context::EXTENSION_INDEX); | 3061 return BuildLoadNativeContextField(Context::EXTENSION_INDEX); |
| 3060 } | 3062 } |
| 3061 | 3063 |
| 3062 | 3064 |
| 3063 Node* AstGraphBuilder::BuildLoadNativeContextField(int index) { | 3065 Node* AstGraphBuilder::BuildLoadNativeContextField(int index) { |
| 3064 const Operator* op = | 3066 const Operator* op = |
| 3065 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true); | 3067 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true); |
| 3066 Node* native_context = NewNode(op, current_context()); | 3068 Node* native_context = NewNode(op); |
| 3067 return NewNode(javascript()->LoadContext(0, index, true), native_context); | 3069 Node* result = NewNode(javascript()->LoadContext(0, index, true)); |
| 3070 NodeProperties::ReplaceContextInput(result, native_context); |
| 3071 return result; |
| 3068 } | 3072 } |
| 3069 | 3073 |
| 3070 | 3074 |
| 3071 Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) { | 3075 Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) { |
| 3072 if (Node* node = TryFastToBoolean(input)) return node; | 3076 if (Node* node = TryFastToBoolean(input)) return node; |
| 3073 ToBooleanHints hints = ToBooleanHint::kAny; | 3077 ToBooleanHints hints = ToBooleanHint::kAny; |
| 3074 return NewNode(javascript()->ToBoolean(hints), input); | 3078 return NewNode(javascript()->ToBoolean(hints), input); |
| 3075 } | 3079 } |
| 3076 | 3080 |
| 3077 | 3081 |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3492 contexts()->back() = effect = | 3496 contexts()->back() = effect = |
| 3493 graph->NewNode(guard_op, contexts()->back(), effect, osr_loop_entry); | 3497 graph->NewNode(guard_op, contexts()->back(), effect, osr_loop_entry); |
| 3494 | 3498 |
| 3495 // The innermost context is the OSR value, and the outer contexts are | 3499 // The innermost context is the OSR value, and the outer contexts are |
| 3496 // reconstructed by dynamically walking up the context chain. | 3500 // reconstructed by dynamically walking up the context chain. |
| 3497 const Operator* load_op = | 3501 const Operator* load_op = |
| 3498 builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true); | 3502 builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true); |
| 3499 Node* osr_context = effect = contexts()->back(); | 3503 Node* osr_context = effect = contexts()->back(); |
| 3500 int last = static_cast<int>(contexts()->size() - 1); | 3504 int last = static_cast<int>(contexts()->size() - 1); |
| 3501 for (int i = last - 1; i >= 0; i--) { | 3505 for (int i = last - 1; i >= 0; i--) { |
| 3502 osr_context = effect = | 3506 osr_context = effect = graph->NewNode(load_op, osr_context, effect); |
| 3503 graph->NewNode(load_op, osr_context, osr_context, effect); | |
| 3504 contexts()->at(i) = osr_context; | 3507 contexts()->at(i) = osr_context; |
| 3505 } | 3508 } |
| 3506 UpdateEffectDependency(effect); | 3509 UpdateEffectDependency(effect); |
| 3507 } | 3510 } |
| 3508 | 3511 |
| 3509 void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned) { | 3512 void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned) { |
| 3510 int size = static_cast<int>(values()->size()); | 3513 int size = static_cast<int>(values()->size()); |
| 3511 | 3514 |
| 3512 Node* control = builder_->NewLoop(); | 3515 Node* control = builder_->NewLoop(); |
| 3513 if (assigned == nullptr) { | 3516 if (assigned == nullptr) { |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3621 float invocation_frequency, LoopAssignmentAnalysis* loop_assignment, | 3624 float invocation_frequency, LoopAssignmentAnalysis* loop_assignment, |
| 3622 SourcePositionTable* source_positions, int inlining_id) | 3625 SourcePositionTable* source_positions, int inlining_id) |
| 3623 : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency, | 3626 : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency, |
| 3624 loop_assignment), | 3627 loop_assignment), |
| 3625 source_positions_(source_positions), | 3628 source_positions_(source_positions), |
| 3626 start_position_(info->shared_info()->start_position(), inlining_id) {} | 3629 start_position_(info->shared_info()->start_position(), inlining_id) {} |
| 3627 | 3630 |
| 3628 } // namespace compiler | 3631 } // namespace compiler |
| 3629 } // namespace internal | 3632 } // namespace internal |
| 3630 } // namespace v8 | 3633 } // namespace v8 |
| OLD | NEW |