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 |