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

Side by Side Diff: src/compiler/ast-graph-builder.cc

Issue 2615033002: [fullcodegen] Remove dead hole check logic (Closed)
Patch Set: x87 Created 3 years, 11 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
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | src/full-codegen/arm/full-codegen-arm.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 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 906 matching lines...) Expand 10 before | Expand all | Expand 10 after
917 if (!CheckStackOverflow()) { 917 if (!CheckStackOverflow()) {
918 VisitNoStackOverflowCheck(expr); 918 VisitNoStackOverflowCheck(expr);
919 } else { 919 } else {
920 ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant()); 920 ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
921 } 921 }
922 } 922 }
923 923
924 924
925 void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) { 925 void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
926 Variable* variable = decl->proxy()->var(); 926 Variable* variable = decl->proxy()->var();
927 DCHECK(!variable->binding_needs_init());
927 switch (variable->location()) { 928 switch (variable->location()) {
928 case VariableLocation::UNALLOCATED: { 929 case VariableLocation::UNALLOCATED: {
929 DCHECK(!variable->binding_needs_init());
930 globals()->push_back(variable->name()); 930 globals()->push_back(variable->name());
931 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); 931 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
932 DCHECK(!slot.IsInvalid()); 932 DCHECK(!slot.IsInvalid());
933 globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate())); 933 globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
934 globals()->push_back(isolate()->factory()->undefined_value()); 934 globals()->push_back(isolate()->factory()->undefined_value());
935 break; 935 break;
936 } 936 }
937 case VariableLocation::PARAMETER: 937 case VariableLocation::PARAMETER:
938 case VariableLocation::LOCAL: 938 case VariableLocation::LOCAL:
939 if (variable->binding_needs_init()) {
940 Node* value = jsgraph()->TheHoleConstant();
941 environment()->Bind(variable, value);
942 }
943 break;
944 case VariableLocation::CONTEXT: 939 case VariableLocation::CONTEXT:
945 if (variable->binding_needs_init()) {
946 Node* value = jsgraph()->TheHoleConstant();
947 const Operator* op = javascript()->StoreContext(0, variable->index());
948 NewNode(op, value);
949 }
950 break; 940 break;
951 case VariableLocation::LOOKUP: 941 case VariableLocation::LOOKUP:
952 case VariableLocation::MODULE: 942 case VariableLocation::MODULE:
953 UNREACHABLE(); 943 UNREACHABLE();
954 } 944 }
955 } 945 }
956 946
957 947
958 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) { 948 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
959 Variable* variable = decl->proxy()->var(); 949 Variable* variable = decl->proxy()->var();
(...skipping 1514 matching lines...) Expand 10 before | Expand all | Expand 10 after
2474 PrepareFrameState(object, BailoutId::None()); 2464 PrepareFrameState(object, BailoutId::None());
2475 2465
2476 // Assign the object to the {arguments} variable. This should never lazy 2466 // Assign the object to the {arguments} variable. This should never lazy
2477 // deopt, so it is fine to send invalid bailout id. 2467 // deopt, so it is fine to send invalid bailout id.
2478 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); 2468 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
2479 BuildVariableAssignment(arguments, object, Token::ASSIGN, VectorSlotPair(), 2469 BuildVariableAssignment(arguments, object, Token::ASSIGN, VectorSlotPair(),
2480 BailoutId::None()); 2470 BailoutId::None());
2481 return object; 2471 return object;
2482 } 2472 }
2483 2473
2484 Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
2485 Node* not_hole,
2486 BailoutId bailout_id) {
2487 IfBuilder hole_check(this);
2488 Node* the_hole = jsgraph()->TheHoleConstant();
2489 Node* check = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
2490 value, the_hole);
2491 hole_check.If(check);
2492 hole_check.Then();
2493 Node* error = BuildThrowReferenceError(variable, bailout_id);
2494 environment()->Push(error);
2495 hole_check.Else();
2496 environment()->Push(not_hole);
2497 hole_check.End();
2498 return environment()->Pop();
2499 }
2500
2501
2502 Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable,
2503 Node* for_hole,
2504 BailoutId bailout_id) {
2505 IfBuilder hole_check(this);
2506 Node* the_hole = jsgraph()->TheHoleConstant();
2507 Node* check = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
2508 value, the_hole);
2509 hole_check.If(check);
2510 hole_check.Then();
2511 environment()->Push(for_hole);
2512 hole_check.Else();
2513 Node* error = BuildThrowReferenceError(variable, bailout_id);
2514 environment()->Push(error);
2515 hole_check.End();
2516 return environment()->Pop();
2517 }
2518
2519 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, 2474 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
2520 BailoutId bailout_id, 2475 BailoutId bailout_id,
2521 const VectorSlotPair& feedback, 2476 const VectorSlotPair& feedback,
2522 OutputFrameStateCombine combine, 2477 OutputFrameStateCombine combine,
2523 TypeofMode typeof_mode) { 2478 TypeofMode typeof_mode) {
2524 Node* the_hole = jsgraph()->TheHoleConstant(); 2479 DCHECK(!variable->binding_needs_init());
2525 switch (variable->location()) { 2480 switch (variable->location()) {
2526 case VariableLocation::UNALLOCATED: { 2481 case VariableLocation::UNALLOCATED: {
2527 // Global var, const, or let variable. 2482 // Global var, const, or let variable.
2528 Handle<Name> name = variable->name(); 2483 Handle<Name> name = variable->name();
2529 if (Node* node = TryLoadGlobalConstant(name)) return node; 2484 if (Node* node = TryLoadGlobalConstant(name)) return node;
2530 Node* value = BuildGlobalLoad(name, feedback, typeof_mode); 2485 Node* value = BuildGlobalLoad(name, feedback, typeof_mode);
2531 PrepareFrameState(value, bailout_id, combine); 2486 PrepareFrameState(value, bailout_id, combine);
2532 return value; 2487 return value;
2533 } 2488 }
2534 case VariableLocation::PARAMETER: 2489 case VariableLocation::PARAMETER:
2535 case VariableLocation::LOCAL: { 2490 case VariableLocation::LOCAL:
2536 // Local var, const, or let variable. 2491 // Local variable.
2537 Node* value = environment()->Lookup(variable); 2492 return environment()->Lookup(variable);
2538 if (variable->binding_needs_init()) {
2539 // Perform check for uninitialized let/const variables.
2540 if (value->op() == the_hole->op()) {
2541 value = BuildThrowReferenceError(variable, bailout_id);
2542 } else if (value->opcode() == IrOpcode::kPhi) {
2543 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
2544 }
2545 }
2546 return value;
2547 }
2548 case VariableLocation::CONTEXT: { 2493 case VariableLocation::CONTEXT: {
2549 // Context variable (potentially up the context chain). 2494 // Context variable (potentially up the context chain).
2550 int depth = current_scope()->ContextChainLength(variable->scope()); 2495 int depth = current_scope()->ContextChainLength(variable->scope());
2551 // TODO(mstarzinger): The {maybe_assigned} flag computed during variable 2496 // TODO(mstarzinger): The {maybe_assigned} flag computed during variable
2552 // resolution is highly inaccurate and cannot be trusted. We are only 2497 // resolution is highly inaccurate and cannot be trusted. We are only
2553 // taking this information into account when asm.js compilation is used. 2498 // taking this information into account when asm.js compilation is used.
2554 bool immutable = variable->maybe_assigned() == kNotAssigned && 2499 bool immutable = variable->maybe_assigned() == kNotAssigned &&
2555 info()->is_function_context_specializing(); 2500 info()->is_function_context_specializing();
2556 const Operator* op = 2501 const Operator* op =
2557 javascript()->LoadContext(depth, variable->index(), immutable); 2502 javascript()->LoadContext(depth, variable->index(), immutable);
2558 Node* value = NewNode(op); 2503 return NewNode(op);
2559 // TODO(titzer): initialization checks are redundant for already
2560 // initialized immutable context loads, but only specialization knows.
2561 // Maybe specializer should be a parameter to the graph builder?
2562 if (variable->binding_needs_init()) {
2563 // Perform check for uninitialized let/const variables.
2564 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
2565 }
2566 return value;
2567 } 2504 }
2568 case VariableLocation::LOOKUP: 2505 case VariableLocation::LOOKUP:
2569 case VariableLocation::MODULE: 2506 case VariableLocation::MODULE:
2570 UNREACHABLE(); 2507 UNREACHABLE();
2571 } 2508 }
2572 UNREACHABLE(); 2509 UNREACHABLE();
2573 return nullptr; 2510 return nullptr;
2574 } 2511 }
2575 2512
2576 2513
(...skipping 21 matching lines...) Expand all
2598 UNREACHABLE(); 2535 UNREACHABLE();
2599 } 2536 }
2600 UNREACHABLE(); 2537 UNREACHABLE();
2601 return nullptr; 2538 return nullptr;
2602 } 2539 }
2603 2540
2604 Node* AstGraphBuilder::BuildVariableAssignment( 2541 Node* AstGraphBuilder::BuildVariableAssignment(
2605 Variable* variable, Node* value, Token::Value op, 2542 Variable* variable, Node* value, Token::Value op,
2606 const VectorSlotPair& feedback, BailoutId bailout_id, 2543 const VectorSlotPair& feedback, BailoutId bailout_id,
2607 OutputFrameStateCombine combine) { 2544 OutputFrameStateCombine combine) {
2608 Node* the_hole = jsgraph()->TheHoleConstant(); 2545 DCHECK(!variable->binding_needs_init());
2609 VariableMode mode = variable->mode();
2610 switch (variable->location()) { 2546 switch (variable->location()) {
2611 case VariableLocation::UNALLOCATED: { 2547 case VariableLocation::UNALLOCATED: {
2612 // Global var, const, or let variable. 2548 // Global var, const, or let variable.
2613 Handle<Name> name = variable->name(); 2549 Handle<Name> name = variable->name();
2614 Node* store = BuildGlobalStore(name, value, feedback); 2550 Node* store = BuildGlobalStore(name, value, feedback);
2615 PrepareFrameState(store, bailout_id, combine); 2551 PrepareFrameState(store, bailout_id, combine);
2616 return store; 2552 return store;
2617 } 2553 }
2618 case VariableLocation::PARAMETER: 2554 case VariableLocation::PARAMETER:
2619 case VariableLocation::LOCAL: 2555 case VariableLocation::LOCAL:
2620 // Local var, const, or let variable. 2556 DCHECK(!variable->is_this());
2621 if (mode == LET && op == Token::INIT) { 2557 if (variable->mode() == CONST && op != Token::INIT) {
2622 // No initialization check needed because scoping guarantees it. Note
2623 // that we still perform a lookup to keep the variable live, because
2624 // baseline code might contain debug code that inspects the variable.
2625 Node* current = environment()->Lookup(variable);
2626 CHECK_NOT_NULL(current);
2627 } else if (mode == LET && op != Token::INIT &&
2628 variable->binding_needs_init()) {
2629 // Perform an initialization check for let declared variables.
2630 Node* current = environment()->Lookup(variable);
2631 if (current->op() == the_hole->op()) {
2632 return BuildThrowReferenceError(variable, bailout_id);
2633 } else if (current->opcode() == IrOpcode::kPhi) {
2634 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
2635 }
2636 } else if (mode == CONST && op == Token::INIT) {
2637 // Perform an initialization check for const {this} variables.
2638 // Note that the {this} variable is the only const variable being able
2639 // to trigger bind operations outside the TDZ, via {super} calls.
2640 Node* current = environment()->Lookup(variable);
2641 if (current->op() != the_hole->op() && variable->is_this()) {
2642 value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
2643 }
2644 } else if (mode == CONST && op != Token::INIT &&
2645 variable->is_sloppy_function_name()) {
2646 // Non-initializing assignment to sloppy function names is 2558 // Non-initializing assignment to sloppy function names is
2647 // - exception in strict mode. 2559 // - exception in strict mode.
2648 // - ignored in sloppy mode. 2560 // - ignored in sloppy mode.
2649 DCHECK(!variable->binding_needs_init()); 2561 DCHECK(variable->is_sloppy_function_name());
2650 if (variable->throw_on_const_assignment(language_mode())) { 2562 if (variable->throw_on_const_assignment(language_mode())) {
2651 return BuildThrowConstAssignError(bailout_id); 2563 return BuildThrowConstAssignError(bailout_id);
2652 } 2564 }
2653 return value; 2565 return value;
2654 } else if (mode == CONST && op != Token::INIT) {
2655 if (variable->binding_needs_init()) {
2656 Node* current = environment()->Lookup(variable);
2657 if (current->op() == the_hole->op()) {
2658 return BuildThrowReferenceError(variable, bailout_id);
2659 } else if (current->opcode() == IrOpcode::kPhi) {
2660 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
2661 }
2662 }
2663 // Assignment to const is exception in all modes.
2664 return BuildThrowConstAssignError(bailout_id);
2665 } 2566 }
2666 environment()->Bind(variable, value); 2567 environment()->Bind(variable, value);
2667 return value; 2568 return value;
2668 case VariableLocation::CONTEXT: { 2569 case VariableLocation::CONTEXT: {
2570 DCHECK(!variable->is_this());
2669 // Context variable (potentially up the context chain). 2571 // Context variable (potentially up the context chain).
2670 int depth = current_scope()->ContextChainLength(variable->scope()); 2572 if (variable->mode() == CONST && op != Token::INIT) {
2671 if (mode == LET && op != Token::INIT && variable->binding_needs_init()) {
2672 // Perform an initialization check for let declared variables.
2673 const Operator* op =
2674 javascript()->LoadContext(depth, variable->index(), false);
2675 Node* current = NewNode(op);
2676 value = BuildHoleCheckThenThrow(current, variable, value, bailout_id);
2677 } else if (mode == CONST && op == Token::INIT) {
2678 // Perform an initialization check for const {this} variables.
2679 // Note that the {this} variable is the only const variable being able
2680 // to trigger bind operations outside the TDZ, via {super} calls.
2681 if (variable->is_this()) {
2682 const Operator* op =
2683 javascript()->LoadContext(depth, variable->index(), false);
2684 Node* current = NewNode(op);
2685 value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
2686 }
2687 } else if (mode == CONST && op != Token::INIT &&
2688 variable->is_sloppy_function_name()) {
2689 // Non-initializing assignment to sloppy function names is 2573 // Non-initializing assignment to sloppy function names is
2690 // - exception in strict mode. 2574 // - exception in strict mode.
2691 // - ignored in sloppy mode. 2575 // - ignored in sloppy mode.
2692 DCHECK(!variable->binding_needs_init()); 2576 DCHECK(variable->is_sloppy_function_name());
2693 if (variable->throw_on_const_assignment(language_mode())) { 2577 if (variable->throw_on_const_assignment(language_mode())) {
2694 return BuildThrowConstAssignError(bailout_id); 2578 return BuildThrowConstAssignError(bailout_id);
2695 } 2579 }
2696 return value; 2580 return value;
2697 } else if (mode == CONST && op != Token::INIT) {
2698 if (variable->binding_needs_init()) {
2699 const Operator* op =
2700 javascript()->LoadContext(depth, variable->index(), false);
2701 Node* current = NewNode(op);
2702 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
2703 }
2704 // Assignment to const is exception in all modes.
2705 return BuildThrowConstAssignError(bailout_id);
2706 } 2581 }
2582 int depth = current_scope()->ContextChainLength(variable->scope());
2707 const Operator* op = javascript()->StoreContext(depth, variable->index()); 2583 const Operator* op = javascript()->StoreContext(depth, variable->index());
2708 return NewNode(op, value); 2584 return NewNode(op, value);
2709 } 2585 }
2710 case VariableLocation::LOOKUP: 2586 case VariableLocation::LOOKUP:
2711 case VariableLocation::MODULE: 2587 case VariableLocation::MODULE:
2712 UNREACHABLE(); 2588 UNREACHABLE();
2713 } 2589 }
2714 UNREACHABLE(); 2590 UNREACHABLE();
2715 return nullptr; 2591 return nullptr;
2716 } 2592 }
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2813 Node* AstGraphBuilder::BuildThrowError(Node* exception, BailoutId bailout_id) { 2689 Node* AstGraphBuilder::BuildThrowError(Node* exception, BailoutId bailout_id) {
2814 const Operator* op = javascript()->CallRuntime(Runtime::kThrow); 2690 const Operator* op = javascript()->CallRuntime(Runtime::kThrow);
2815 Node* call = NewNode(op, exception); 2691 Node* call = NewNode(op, exception);
2816 PrepareFrameState(call, bailout_id); 2692 PrepareFrameState(call, bailout_id);
2817 Node* control = NewNode(common()->Throw(), call); 2693 Node* control = NewNode(common()->Throw(), call);
2818 UpdateControlDependencyToLeaveFunction(control); 2694 UpdateControlDependencyToLeaveFunction(control);
2819 return call; 2695 return call;
2820 } 2696 }
2821 2697
2822 2698
2823 Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
2824 BailoutId bailout_id) {
2825 Node* variable_name = jsgraph()->Constant(variable->name());
2826 const Operator* op = javascript()->CallRuntime(Runtime::kThrowReferenceError);
2827 Node* call = NewNode(op, variable_name);
2828 PrepareFrameState(call, bailout_id);
2829 Node* control = NewNode(common()->Throw(), call);
2830 UpdateControlDependencyToLeaveFunction(control);
2831 return call;
2832 }
2833
2834
2835 Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) { 2699 Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
2836 const Operator* op = 2700 const Operator* op =
2837 javascript()->CallRuntime(Runtime::kThrowConstAssignError); 2701 javascript()->CallRuntime(Runtime::kThrowConstAssignError);
2838 Node* call = NewNode(op); 2702 Node* call = NewNode(op);
2839 PrepareFrameState(call, bailout_id); 2703 PrepareFrameState(call, bailout_id);
2840 Node* control = NewNode(common()->Throw(), call); 2704 Node* control = NewNode(common()->Throw(), call);
2841 UpdateControlDependencyToLeaveFunction(control); 2705 UpdateControlDependencyToLeaveFunction(control);
2842 return call; 2706 return call;
2843 } 2707 }
2844 2708
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after
3298 float invocation_frequency, LoopAssignmentAnalysis* loop_assignment, 3162 float invocation_frequency, LoopAssignmentAnalysis* loop_assignment,
3299 SourcePositionTable* source_positions, int inlining_id) 3163 SourcePositionTable* source_positions, int inlining_id)
3300 : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency, 3164 : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency,
3301 loop_assignment), 3165 loop_assignment),
3302 source_positions_(source_positions), 3166 source_positions_(source_positions),
3303 start_position_(info->shared_info()->start_position(), inlining_id) {} 3167 start_position_(info->shared_info()->start_position(), inlining_id) {}
3304 3168
3305 } // namespace compiler 3169 } // namespace compiler
3306 } // namespace internal 3170 } // namespace internal
3307 } // namespace v8 3171 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | src/full-codegen/arm/full-codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698