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

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

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

Powered by Google App Engine
This is Rietveld 408576698