| 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/compiler.h" | 7 #include "src/compiler.h" |
| 8 #include "src/compiler/ast-loop-assignment-analyzer.h" | 8 #include "src/compiler/ast-loop-assignment-analyzer.h" |
| 9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
| 10 #include "src/compiler/js-type-feedback.h" | 10 #include "src/compiler/js-type-feedback.h" |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 505 | 505 |
| 506 // Initialize the incoming context. | 506 // Initialize the incoming context. |
| 507 CreateFunctionContext(constant_context); | 507 CreateFunctionContext(constant_context); |
| 508 ContextScope incoming(this, scope, function_context_.get()); | 508 ContextScope incoming(this, scope, function_context_.get()); |
| 509 | 509 |
| 510 // Initialize control scope. | 510 // Initialize control scope. |
| 511 ControlScope control(this); | 511 ControlScope control(this); |
| 512 | 512 |
| 513 // Build receiver check for sloppy mode if necessary. | 513 // Build receiver check for sloppy mode if necessary. |
| 514 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? | 514 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? |
| 515 Node* patched_receiver = nullptr; | 515 Node* original_receiver = env.Lookup(scope->receiver()); |
| 516 if (scope->has_this_declaration()) { | 516 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); |
| 517 Node* original_receiver = NewNode(common()->Parameter(0), graph()->start()); | 517 env.Bind(scope->receiver(), patched_receiver); |
| 518 patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); | |
| 519 if (scope->receiver()->IsStackAllocated()) { | |
| 520 env.Bind(scope->receiver(), patched_receiver); | |
| 521 } | |
| 522 } | |
| 523 | 518 |
| 524 // Build function context only if there are context allocated variables. | 519 // Build function context only if there are context allocated variables. |
| 525 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 520 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 526 if (heap_slots > 0) { | 521 if (heap_slots > 0) { |
| 527 // Push a new inner context scope for the function. | 522 // Push a new inner context scope for the function. |
| 528 Node* inner_context = | 523 Node* inner_context = BuildLocalFunctionContext(function_context_.get()); |
| 529 BuildLocalFunctionContext(function_context_.get(), patched_receiver); | |
| 530 ContextScope top_context(this, scope, inner_context); | 524 ContextScope top_context(this, scope, inner_context); |
| 531 CreateGraphBody(stack_check); | 525 CreateGraphBody(stack_check); |
| 532 } else { | 526 } else { |
| 533 // Simply use the outer function context in building the graph. | 527 // Simply use the outer function context in building the graph. |
| 534 CreateGraphBody(stack_check); | 528 CreateGraphBody(stack_check); |
| 535 } | 529 } |
| 536 | 530 |
| 537 // Finish the basic structure of the graph. | 531 // Finish the basic structure of the graph. |
| 538 graph()->SetEnd(graph()->NewNode(common()->End(), exit_control())); | 532 graph()->SetEnd(graph()->NewNode(common()->End(), exit_control())); |
| 539 | 533 |
| (...skipping 1710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2250 if (possibly_eval && args->length() > 0) { | 2244 if (possibly_eval && args->length() > 0) { |
| 2251 int arg_count = args->length(); | 2245 int arg_count = args->length(); |
| 2252 | 2246 |
| 2253 // Extract callee and source string from the environment. | 2247 // Extract callee and source string from the environment. |
| 2254 Node* callee = environment()->Peek(arg_count + 1); | 2248 Node* callee = environment()->Peek(arg_count + 1); |
| 2255 Node* source = environment()->Peek(arg_count - 1); | 2249 Node* source = environment()->Peek(arg_count - 1); |
| 2256 | 2250 |
| 2257 // Create node to ask for help resolving potential eval call. This will | 2251 // Create node to ask for help resolving potential eval call. This will |
| 2258 // provide a fully resolved callee and the corresponding receiver. | 2252 // provide a fully resolved callee and the corresponding receiver. |
| 2259 Node* function = GetFunctionClosure(); | 2253 Node* function = GetFunctionClosure(); |
| 2260 // TODO(wingo): ResolvePossibleDirectEval doesn't really need a receiver, | 2254 Node* receiver = environment()->Lookup(info()->scope()->receiver()); |
| 2261 // now that eval scopes don't have "this" declarations. Remove this hack | |
| 2262 // once ResolvePossibleDirectEval changes. | |
| 2263 Node* receiver; | |
| 2264 { | |
| 2265 Variable* variable = info()->scope()->LookupThis(); | |
| 2266 if (variable->IsStackAllocated()) { | |
| 2267 receiver = environment()->Lookup(variable); | |
| 2268 } else { | |
| 2269 DCHECK(variable->IsContextSlot()); | |
| 2270 int depth = current_scope()->ContextChainLength(variable->scope()); | |
| 2271 bool immutable = variable->maybe_assigned() == kNotAssigned; | |
| 2272 const Operator* op = | |
| 2273 javascript()->LoadContext(depth, variable->index(), immutable); | |
| 2274 receiver = NewNode(op, current_context()); | |
| 2275 } | |
| 2276 } | |
| 2277 Node* language = jsgraph()->Constant(language_mode()); | 2255 Node* language = jsgraph()->Constant(language_mode()); |
| 2278 Node* position = jsgraph()->Constant(info()->scope()->start_position()); | 2256 Node* position = jsgraph()->Constant(info()->scope()->start_position()); |
| 2279 const Operator* op = | 2257 const Operator* op = |
| 2280 javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval, 6); | 2258 javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval, 6); |
| 2281 Node* pair = | 2259 Node* pair = |
| 2282 NewNode(op, callee, source, function, receiver, language, position); | 2260 NewNode(op, callee, source, function, receiver, language, position); |
| 2283 PrepareFrameState(pair, expr->EvalOrLookupId(), | 2261 PrepareFrameState(pair, expr->EvalOrLookupId(), |
| 2284 OutputFrameStateCombine::PokeAt(arg_count + 1)); | 2262 OutputFrameStateCombine::PokeAt(arg_count + 1)); |
| 2285 Node* new_callee = NewNode(common()->Projection(0), pair); | 2263 Node* new_callee = NewNode(common()->Projection(0), pair); |
| 2286 Node* new_receiver = NewNode(common()->Projection(1), pair); | 2264 Node* new_receiver = NewNode(common()->Projection(1), pair); |
| (...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2746 return value; | 2724 return value; |
| 2747 } | 2725 } |
| 2748 | 2726 |
| 2749 | 2727 |
| 2750 Node* AstGraphBuilder::BuildPatchReceiverToGlobalProxy(Node* receiver) { | 2728 Node* AstGraphBuilder::BuildPatchReceiverToGlobalProxy(Node* receiver) { |
| 2751 // Sloppy mode functions and builtins need to replace the receiver with the | 2729 // Sloppy mode functions and builtins need to replace the receiver with the |
| 2752 // global proxy when called as functions (without an explicit receiver | 2730 // global proxy when called as functions (without an explicit receiver |
| 2753 // object). Otherwise there is nothing left to do here. | 2731 // object). Otherwise there is nothing left to do here. |
| 2754 if (is_strict(language_mode()) || info()->is_native()) return receiver; | 2732 if (is_strict(language_mode()) || info()->is_native()) return receiver; |
| 2755 | 2733 |
| 2756 // There is no need to perform patching if the receiver will never be used. | 2734 // There is no need to perform patching if the receiver is never used. Note |
| 2735 // that scope predicates are purely syntactical, a call to eval might still |
| 2736 // inspect the receiver value. |
| 2757 if (!info()->MayUseThis()) return receiver; | 2737 if (!info()->MayUseThis()) return receiver; |
| 2758 | 2738 |
| 2759 IfBuilder receiver_check(this); | 2739 IfBuilder receiver_check(this); |
| 2760 Node* undefined = jsgraph()->UndefinedConstant(); | 2740 Node* undefined = jsgraph()->UndefinedConstant(); |
| 2761 Node* check = NewNode(javascript()->StrictEqual(), receiver, undefined); | 2741 Node* check = NewNode(javascript()->StrictEqual(), receiver, undefined); |
| 2762 receiver_check.If(check); | 2742 receiver_check.If(check); |
| 2763 receiver_check.Then(); | 2743 receiver_check.Then(); |
| 2764 Node* proxy = BuildLoadGlobalProxy(); | 2744 Node* proxy = BuildLoadGlobalProxy(); |
| 2765 environment()->Push(proxy); | 2745 environment()->Push(proxy); |
| 2766 receiver_check.Else(); | 2746 receiver_check.Else(); |
| 2767 environment()->Push(receiver); | 2747 environment()->Push(receiver); |
| 2768 receiver_check.End(); | 2748 receiver_check.End(); |
| 2769 return environment()->Pop(); | 2749 return environment()->Pop(); |
| 2770 } | 2750 } |
| 2771 | 2751 |
| 2772 | 2752 |
| 2773 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, | 2753 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context) { |
| 2774 Node* patched_receiver) { | |
| 2775 Scope* scope = info()->scope(); | |
| 2776 Node* closure = GetFunctionClosure(); | 2754 Node* closure = GetFunctionClosure(); |
| 2777 | 2755 |
| 2778 // Allocate a new local context. | 2756 // Allocate a new local context. |
| 2779 Node* local_context = | 2757 Node* local_context = |
| 2780 scope->is_script_scope() | 2758 info()->scope()->is_script_scope() |
| 2781 ? BuildLocalScriptContext(scope) | 2759 ? BuildLocalScriptContext(info()->scope()) |
| 2782 : NewNode(javascript()->CreateFunctionContext(), closure); | 2760 : NewNode(javascript()->CreateFunctionContext(), closure); |
| 2783 | 2761 |
| 2784 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { | |
| 2785 DCHECK_NOT_NULL(patched_receiver); | |
| 2786 // Context variable (at bottom of the context chain). | |
| 2787 Variable* variable = scope->receiver(); | |
| 2788 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | |
| 2789 const Operator* op = javascript()->StoreContext(0, variable->index()); | |
| 2790 NewNode(op, local_context, patched_receiver); | |
| 2791 } | |
| 2792 | |
| 2793 // Copy parameters into context if necessary. | 2762 // Copy parameters into context if necessary. |
| 2794 int num_parameters = scope->num_parameters(); | 2763 int num_parameters = info()->scope()->num_parameters(); |
| 2795 for (int i = 0; i < num_parameters; i++) { | 2764 for (int i = 0; i < num_parameters; i++) { |
| 2796 Variable* variable = scope->parameter(i); | 2765 Variable* variable = info()->scope()->parameter(i); |
| 2797 if (!variable->IsContextSlot()) continue; | 2766 if (!variable->IsContextSlot()) continue; |
| 2798 // Temporary parameter node. The parameter indices are shifted by 1 | 2767 // Temporary parameter node. The parameter indices are shifted by 1 |
| 2799 // (receiver is parameter index -1 but environment index 0). | 2768 // (receiver is parameter index -1 but environment index 0). |
| 2800 Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start()); | 2769 Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start()); |
| 2801 // Context variable (at bottom of the context chain). | 2770 // Context variable (at bottom of the context chain). |
| 2802 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 2771 DCHECK_EQ(0, info()->scope()->ContextChainLength(variable->scope())); |
| 2803 const Operator* op = javascript()->StoreContext(0, variable->index()); | 2772 const Operator* op = javascript()->StoreContext(0, variable->index()); |
| 2804 NewNode(op, local_context, parameter); | 2773 NewNode(op, local_context, parameter); |
| 2805 } | 2774 } |
| 2806 | 2775 |
| 2807 return local_context; | 2776 return local_context; |
| 2808 } | 2777 } |
| 2809 | 2778 |
| 2810 | 2779 |
| 2811 Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) { | 2780 Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) { |
| 2812 Node* closure = GetFunctionClosure(); | 2781 Node* closure = GetFunctionClosure(); |
| (...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3680 // Phi does not exist yet, introduce one. | 3649 // Phi does not exist yet, introduce one. |
| 3681 value = NewPhi(inputs, value, control); | 3650 value = NewPhi(inputs, value, control); |
| 3682 value->ReplaceInput(inputs - 1, other); | 3651 value->ReplaceInput(inputs - 1, other); |
| 3683 } | 3652 } |
| 3684 return value; | 3653 return value; |
| 3685 } | 3654 } |
| 3686 | 3655 |
| 3687 } // namespace compiler | 3656 } // namespace compiler |
| 3688 } // namespace internal | 3657 } // namespace internal |
| 3689 } // namespace v8 | 3658 } // namespace v8 |
| OLD | NEW |