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 1683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2223 if (possibly_eval && args->length() > 0) { | 2217 if (possibly_eval && args->length() > 0) { |
2224 int arg_count = args->length(); | 2218 int arg_count = args->length(); |
2225 | 2219 |
2226 // Extract callee and source string from the environment. | 2220 // Extract callee and source string from the environment. |
2227 Node* callee = environment()->Peek(arg_count + 1); | 2221 Node* callee = environment()->Peek(arg_count + 1); |
2228 Node* source = environment()->Peek(arg_count - 1); | 2222 Node* source = environment()->Peek(arg_count - 1); |
2229 | 2223 |
2230 // Create node to ask for help resolving potential eval call. This will | 2224 // Create node to ask for help resolving potential eval call. This will |
2231 // provide a fully resolved callee and the corresponding receiver. | 2225 // provide a fully resolved callee and the corresponding receiver. |
2232 Node* function = GetFunctionClosure(); | 2226 Node* function = GetFunctionClosure(); |
2233 // TODO(wingo): ResolvePossibleDirectEval doesn't really need a receiver, | 2227 Node* receiver = environment()->Lookup(info()->scope()->receiver()); |
2234 // now that eval scopes don't have "this" declarations. Remove this hack | |
2235 // once ResolvePossibleDirectEval changes. | |
2236 Node* receiver; | |
2237 { | |
2238 Variable* variable = info()->scope()->LookupThis(); | |
2239 if (variable->IsStackAllocated()) { | |
2240 receiver = environment()->Lookup(variable); | |
2241 } else { | |
2242 DCHECK(variable->IsContextSlot()); | |
2243 int depth = current_scope()->ContextChainLength(variable->scope()); | |
2244 bool immutable = variable->maybe_assigned() == kNotAssigned; | |
2245 const Operator* op = | |
2246 javascript()->LoadContext(depth, variable->index(), immutable); | |
2247 receiver = NewNode(op, current_context()); | |
2248 } | |
2249 } | |
2250 Node* language = jsgraph()->Constant(language_mode()); | 2228 Node* language = jsgraph()->Constant(language_mode()); |
2251 Node* position = jsgraph()->Constant(info()->scope()->start_position()); | 2229 Node* position = jsgraph()->Constant(info()->scope()->start_position()); |
2252 const Operator* op = | 2230 const Operator* op = |
2253 javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval, 6); | 2231 javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval, 6); |
2254 Node* pair = | 2232 Node* pair = |
2255 NewNode(op, callee, source, function, receiver, language, position); | 2233 NewNode(op, callee, source, function, receiver, language, position); |
2256 PrepareFrameState(pair, expr->EvalOrLookupId(), | 2234 PrepareFrameState(pair, expr->EvalOrLookupId(), |
2257 OutputFrameStateCombine::PokeAt(arg_count + 1)); | 2235 OutputFrameStateCombine::PokeAt(arg_count + 1)); |
2258 Node* new_callee = NewNode(common()->Projection(0), pair); | 2236 Node* new_callee = NewNode(common()->Projection(0), pair); |
2259 Node* new_receiver = NewNode(common()->Projection(1), pair); | 2237 Node* new_receiver = NewNode(common()->Projection(1), pair); |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2712 return value; | 2690 return value; |
2713 } | 2691 } |
2714 | 2692 |
2715 | 2693 |
2716 Node* AstGraphBuilder::BuildPatchReceiverToGlobalProxy(Node* receiver) { | 2694 Node* AstGraphBuilder::BuildPatchReceiverToGlobalProxy(Node* receiver) { |
2717 // Sloppy mode functions and builtins need to replace the receiver with the | 2695 // Sloppy mode functions and builtins need to replace the receiver with the |
2718 // global proxy when called as functions (without an explicit receiver | 2696 // global proxy when called as functions (without an explicit receiver |
2719 // object). Otherwise there is nothing left to do here. | 2697 // object). Otherwise there is nothing left to do here. |
2720 if (is_strict(language_mode()) || info()->is_native()) return receiver; | 2698 if (is_strict(language_mode()) || info()->is_native()) return receiver; |
2721 | 2699 |
2722 // There is no need to perform patching if the receiver will never be used. | 2700 // There is no need to perform patching if the receiver is never used. Note |
| 2701 // that scope predicates are purely syntactical, a call to eval might still |
| 2702 // inspect the receiver value. |
2723 if (!info()->MayUseThis()) return receiver; | 2703 if (!info()->MayUseThis()) return receiver; |
2724 | 2704 |
2725 IfBuilder receiver_check(this); | 2705 IfBuilder receiver_check(this); |
2726 Node* undefined = jsgraph()->UndefinedConstant(); | 2706 Node* undefined = jsgraph()->UndefinedConstant(); |
2727 Node* check = NewNode(javascript()->StrictEqual(), receiver, undefined); | 2707 Node* check = NewNode(javascript()->StrictEqual(), receiver, undefined); |
2728 receiver_check.If(check); | 2708 receiver_check.If(check); |
2729 receiver_check.Then(); | 2709 receiver_check.Then(); |
2730 Node* proxy = BuildLoadGlobalProxy(); | 2710 Node* proxy = BuildLoadGlobalProxy(); |
2731 environment()->Push(proxy); | 2711 environment()->Push(proxy); |
2732 receiver_check.Else(); | 2712 receiver_check.Else(); |
2733 environment()->Push(receiver); | 2713 environment()->Push(receiver); |
2734 receiver_check.End(); | 2714 receiver_check.End(); |
2735 return environment()->Pop(); | 2715 return environment()->Pop(); |
2736 } | 2716 } |
2737 | 2717 |
2738 | 2718 |
2739 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, | 2719 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context) { |
2740 Node* patched_receiver) { | |
2741 Scope* scope = info()->scope(); | |
2742 Node* closure = GetFunctionClosure(); | 2720 Node* closure = GetFunctionClosure(); |
2743 | 2721 |
2744 // Allocate a new local context. | 2722 // Allocate a new local context. |
2745 Node* local_context = | 2723 Node* local_context = |
2746 scope->is_script_scope() | 2724 info()->scope()->is_script_scope() |
2747 ? BuildLocalScriptContext(scope) | 2725 ? BuildLocalScriptContext(info()->scope()) |
2748 : NewNode(javascript()->CreateFunctionContext(), closure); | 2726 : NewNode(javascript()->CreateFunctionContext(), closure); |
2749 | 2727 |
2750 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { | |
2751 DCHECK_NOT_NULL(patched_receiver); | |
2752 // Context variable (at bottom of the context chain). | |
2753 Variable* variable = scope->receiver(); | |
2754 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | |
2755 const Operator* op = javascript()->StoreContext(0, variable->index()); | |
2756 NewNode(op, local_context, patched_receiver); | |
2757 } | |
2758 | |
2759 // Copy parameters into context if necessary. | 2728 // Copy parameters into context if necessary. |
2760 int num_parameters = scope->num_parameters(); | 2729 int num_parameters = info()->scope()->num_parameters(); |
2761 for (int i = 0; i < num_parameters; i++) { | 2730 for (int i = 0; i < num_parameters; i++) { |
2762 Variable* variable = scope->parameter(i); | 2731 Variable* variable = info()->scope()->parameter(i); |
2763 if (!variable->IsContextSlot()) continue; | 2732 if (!variable->IsContextSlot()) continue; |
2764 // Temporary parameter node. The parameter indices are shifted by 1 | 2733 // Temporary parameter node. The parameter indices are shifted by 1 |
2765 // (receiver is parameter index -1 but environment index 0). | 2734 // (receiver is parameter index -1 but environment index 0). |
2766 Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start()); | 2735 Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start()); |
2767 // Context variable (at bottom of the context chain). | 2736 // Context variable (at bottom of the context chain). |
2768 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 2737 DCHECK_EQ(0, info()->scope()->ContextChainLength(variable->scope())); |
2769 const Operator* op = javascript()->StoreContext(0, variable->index()); | 2738 const Operator* op = javascript()->StoreContext(0, variable->index()); |
2770 NewNode(op, local_context, parameter); | 2739 NewNode(op, local_context, parameter); |
2771 } | 2740 } |
2772 | 2741 |
2773 return local_context; | 2742 return local_context; |
2774 } | 2743 } |
2775 | 2744 |
2776 | 2745 |
2777 Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) { | 2746 Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) { |
2778 Node* closure = GetFunctionClosure(); | 2747 Node* closure = GetFunctionClosure(); |
(...skipping 860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3639 // Phi does not exist yet, introduce one. | 3608 // Phi does not exist yet, introduce one. |
3640 value = NewPhi(inputs, value, control); | 3609 value = NewPhi(inputs, value, control); |
3641 value->ReplaceInput(inputs - 1, other); | 3610 value->ReplaceInput(inputs - 1, other); |
3642 } | 3611 } |
3643 return value; | 3612 return value; |
3644 } | 3613 } |
3645 | 3614 |
3646 } // namespace compiler | 3615 } // namespace compiler |
3647 } // namespace internal | 3616 } // namespace internal |
3648 } // namespace v8 | 3617 } // namespace v8 |
OLD | NEW |