| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
| 6 | 6 |
| 7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
| 9 #include "src/interpreter/bytecode-register-allocator.h" | 9 #include "src/interpreter/bytecode-register-allocator.h" |
| 10 #include "src/interpreter/control-flow-builders.h" | 10 #include "src/interpreter/control-flow-builders.h" |
| (...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 | 602 |
| 603 // Visit illegal re-declaration and bail out if it exists. | 603 // Visit illegal re-declaration and bail out if it exists. |
| 604 if (scope()->HasIllegalRedeclaration()) { | 604 if (scope()->HasIllegalRedeclaration()) { |
| 605 VisitForEffect(scope()->GetIllegalRedeclaration()); | 605 VisitForEffect(scope()->GetIllegalRedeclaration()); |
| 606 return; | 606 return; |
| 607 } | 607 } |
| 608 | 608 |
| 609 // Visit declarations within the function scope. | 609 // Visit declarations within the function scope. |
| 610 VisitDeclarations(scope()->declarations()); | 610 VisitDeclarations(scope()->declarations()); |
| 611 | 611 |
| 612 // Perform a stack-check before the body. |
| 613 builder()->StackCheck(); |
| 614 |
| 612 // Visit statements in the function body. | 615 // Visit statements in the function body. |
| 613 VisitStatements(info()->literal()->body()); | 616 VisitStatements(info()->literal()->body()); |
| 614 } | 617 } |
| 615 | 618 |
| 616 | 619 |
| 617 void BytecodeGenerator::VisitBlock(Block* stmt) { | 620 void BytecodeGenerator::VisitBlock(Block* stmt) { |
| 618 // Visit declarations and statements. | 621 // Visit declarations and statements. |
| 619 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) { | 622 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) { |
| 620 VisitNewLocalBlockContext(stmt->scope()); | 623 VisitNewLocalBlockContext(stmt->scope()); |
| 621 ContextScope scope(this, stmt->scope()); | 624 ContextScope scope(this, stmt->scope()); |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 914 | 917 |
| 915 switch_builder.SetBreakTarget(done_label); | 918 switch_builder.SetBreakTarget(done_label); |
| 916 } | 919 } |
| 917 | 920 |
| 918 | 921 |
| 919 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { | 922 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { |
| 920 // Handled entirely in VisitSwitchStatement. | 923 // Handled entirely in VisitSwitchStatement. |
| 921 UNREACHABLE(); | 924 UNREACHABLE(); |
| 922 } | 925 } |
| 923 | 926 |
| 927 void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt, |
| 928 LoopBuilder* loop_builder) { |
| 929 ControlScopeForIteration execution_control(this, stmt, loop_builder); |
| 930 builder()->StackCheck(); |
| 931 Visit(stmt->body()); |
| 932 } |
| 924 | 933 |
| 925 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 934 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 926 LoopBuilder loop_builder(builder()); | 935 LoopBuilder loop_builder(builder()); |
| 927 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | |
| 928 loop_builder.LoopHeader(); | 936 loop_builder.LoopHeader(); |
| 929 if (stmt->cond()->ToBooleanIsFalse()) { | 937 if (stmt->cond()->ToBooleanIsFalse()) { |
| 930 Visit(stmt->body()); | 938 VisitIterationBody(stmt, &loop_builder); |
| 931 loop_builder.Condition(); | 939 loop_builder.Condition(); |
| 932 } else if (stmt->cond()->ToBooleanIsTrue()) { | 940 } else if (stmt->cond()->ToBooleanIsTrue()) { |
| 933 loop_builder.Condition(); | 941 loop_builder.Condition(); |
| 934 Visit(stmt->body()); | 942 VisitIterationBody(stmt, &loop_builder); |
| 935 loop_builder.JumpToHeader(); | 943 loop_builder.JumpToHeader(); |
| 936 } else { | 944 } else { |
| 937 Visit(stmt->body()); | 945 VisitIterationBody(stmt, &loop_builder); |
| 938 loop_builder.Condition(); | 946 loop_builder.Condition(); |
| 939 VisitForAccumulatorValue(stmt->cond()); | 947 VisitForAccumulatorValue(stmt->cond()); |
| 940 loop_builder.JumpToHeaderIfTrue(); | 948 loop_builder.JumpToHeaderIfTrue(); |
| 941 } | 949 } |
| 942 loop_builder.EndLoop(); | 950 loop_builder.EndLoop(); |
| 943 } | 951 } |
| 944 | 952 |
| 945 | |
| 946 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 953 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
| 947 if (stmt->cond()->ToBooleanIsFalse()) { | 954 if (stmt->cond()->ToBooleanIsFalse()) { |
| 948 // If the condition is false there is no need to generate the loop. | 955 // If the condition is false there is no need to generate the loop. |
| 949 return; | 956 return; |
| 950 } | 957 } |
| 951 | 958 |
| 952 LoopBuilder loop_builder(builder()); | 959 LoopBuilder loop_builder(builder()); |
| 953 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | |
| 954 loop_builder.LoopHeader(); | 960 loop_builder.LoopHeader(); |
| 955 loop_builder.Condition(); | 961 loop_builder.Condition(); |
| 956 if (!stmt->cond()->ToBooleanIsTrue()) { | 962 if (!stmt->cond()->ToBooleanIsTrue()) { |
| 957 VisitForAccumulatorValue(stmt->cond()); | 963 VisitForAccumulatorValue(stmt->cond()); |
| 958 loop_builder.BreakIfFalse(); | 964 loop_builder.BreakIfFalse(); |
| 959 } | 965 } |
| 960 Visit(stmt->body()); | 966 VisitIterationBody(stmt, &loop_builder); |
| 961 loop_builder.JumpToHeader(); | 967 loop_builder.JumpToHeader(); |
| 962 loop_builder.EndLoop(); | 968 loop_builder.EndLoop(); |
| 963 } | 969 } |
| 964 | 970 |
| 965 | 971 |
| 966 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 972 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { |
| 967 if (stmt->init() != nullptr) { | 973 if (stmt->init() != nullptr) { |
| 968 Visit(stmt->init()); | 974 Visit(stmt->init()); |
| 969 } | 975 } |
| 970 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { | 976 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { |
| 971 // If the condition is known to be false there is no need to generate | 977 // If the condition is known to be false there is no need to generate |
| 972 // body, next or condition blocks. Init block should be generated. | 978 // body, next or condition blocks. Init block should be generated. |
| 973 return; | 979 return; |
| 974 } | 980 } |
| 975 | 981 |
| 976 LoopBuilder loop_builder(builder()); | 982 LoopBuilder loop_builder(builder()); |
| 977 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | |
| 978 | |
| 979 loop_builder.LoopHeader(); | 983 loop_builder.LoopHeader(); |
| 980 loop_builder.Condition(); | 984 loop_builder.Condition(); |
| 981 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { | 985 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { |
| 982 VisitForAccumulatorValue(stmt->cond()); | 986 VisitForAccumulatorValue(stmt->cond()); |
| 983 loop_builder.BreakIfFalse(); | 987 loop_builder.BreakIfFalse(); |
| 984 } | 988 } |
| 985 Visit(stmt->body()); | 989 VisitIterationBody(stmt, &loop_builder); |
| 986 if (stmt->next() != nullptr) { | 990 if (stmt->next() != nullptr) { |
| 987 loop_builder.Next(); | 991 loop_builder.Next(); |
| 988 Visit(stmt->next()); | 992 Visit(stmt->next()); |
| 989 } | 993 } |
| 990 loop_builder.JumpToHeader(); | 994 loop_builder.JumpToHeader(); |
| 991 loop_builder.EndLoop(); | 995 loop_builder.EndLoop(); |
| 992 } | 996 } |
| 993 | 997 |
| 994 | 998 |
| 995 void BytecodeGenerator::VisitForInAssignment(Expression* expr, | 999 void BytecodeGenerator::VisitForInAssignment(Expression* expr, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1036 | 1040 |
| 1037 | 1041 |
| 1038 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { | 1042 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
| 1039 if (stmt->subject()->IsNullLiteral() || | 1043 if (stmt->subject()->IsNullLiteral() || |
| 1040 stmt->subject()->IsUndefinedLiteral(isolate())) { | 1044 stmt->subject()->IsUndefinedLiteral(isolate())) { |
| 1041 // ForIn generates lots of code, skip if it wouldn't produce any effects. | 1045 // ForIn generates lots of code, skip if it wouldn't produce any effects. |
| 1042 return; | 1046 return; |
| 1043 } | 1047 } |
| 1044 | 1048 |
| 1045 LoopBuilder loop_builder(builder()); | 1049 LoopBuilder loop_builder(builder()); |
| 1046 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | |
| 1047 BytecodeLabel subject_null_label, subject_undefined_label, not_object_label; | 1050 BytecodeLabel subject_null_label, subject_undefined_label, not_object_label; |
| 1048 | 1051 |
| 1049 // Prepare the state for executing ForIn. | 1052 // Prepare the state for executing ForIn. |
| 1050 VisitForAccumulatorValue(stmt->subject()); | 1053 VisitForAccumulatorValue(stmt->subject()); |
| 1051 builder()->JumpIfUndefined(&subject_undefined_label); | 1054 builder()->JumpIfUndefined(&subject_undefined_label); |
| 1052 builder()->JumpIfNull(&subject_null_label); | 1055 builder()->JumpIfNull(&subject_null_label); |
| 1053 Register receiver = register_allocator()->NewRegister(); | 1056 Register receiver = register_allocator()->NewRegister(); |
| 1054 builder()->CastAccumulatorToJSObject(); | 1057 builder()->CastAccumulatorToJSObject(); |
| 1055 builder()->JumpIfNull(¬_object_label); | 1058 builder()->JumpIfNull(¬_object_label); |
| 1056 builder()->StoreAccumulatorInRegister(receiver); | 1059 builder()->StoreAccumulatorInRegister(receiver); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1070 | 1073 |
| 1071 // The loop | 1074 // The loop |
| 1072 loop_builder.LoopHeader(); | 1075 loop_builder.LoopHeader(); |
| 1073 loop_builder.Condition(); | 1076 loop_builder.Condition(); |
| 1074 builder()->ForInDone(index, cache_length); | 1077 builder()->ForInDone(index, cache_length); |
| 1075 loop_builder.BreakIfTrue(); | 1078 loop_builder.BreakIfTrue(); |
| 1076 DCHECK(Register::AreContiguous(cache_type, cache_array)); | 1079 DCHECK(Register::AreContiguous(cache_type, cache_array)); |
| 1077 builder()->ForInNext(receiver, index, cache_type); | 1080 builder()->ForInNext(receiver, index, cache_type); |
| 1078 loop_builder.ContinueIfUndefined(); | 1081 loop_builder.ContinueIfUndefined(); |
| 1079 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); | 1082 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); |
| 1080 Visit(stmt->body()); | 1083 VisitIterationBody(stmt, &loop_builder); |
| 1081 loop_builder.Next(); | 1084 loop_builder.Next(); |
| 1082 builder()->ForInStep(index); | 1085 builder()->ForInStep(index); |
| 1083 builder()->StoreAccumulatorInRegister(index); | 1086 builder()->StoreAccumulatorInRegister(index); |
| 1084 loop_builder.JumpToHeader(); | 1087 loop_builder.JumpToHeader(); |
| 1085 loop_builder.EndLoop(); | 1088 loop_builder.EndLoop(); |
| 1086 builder()->Bind(¬_object_label); | 1089 builder()->Bind(¬_object_label); |
| 1087 builder()->Bind(&subject_null_label); | 1090 builder()->Bind(&subject_null_label); |
| 1088 builder()->Bind(&subject_undefined_label); | 1091 builder()->Bind(&subject_undefined_label); |
| 1089 } | 1092 } |
| 1090 | 1093 |
| 1091 | 1094 |
| 1092 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | 1095 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
| 1093 LoopBuilder loop_builder(builder()); | 1096 LoopBuilder loop_builder(builder()); |
| 1094 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | 1097 ControlScopeForIteration control_scope(this, stmt, &loop_builder); |
| 1095 | 1098 |
| 1096 VisitForEffect(stmt->assign_iterator()); | 1099 VisitForEffect(stmt->assign_iterator()); |
| 1097 | 1100 |
| 1098 loop_builder.LoopHeader(); | 1101 loop_builder.LoopHeader(); |
| 1099 loop_builder.Next(); | 1102 loop_builder.Next(); |
| 1100 VisitForEffect(stmt->next_result()); | 1103 VisitForEffect(stmt->next_result()); |
| 1101 VisitForAccumulatorValue(stmt->result_done()); | 1104 VisitForAccumulatorValue(stmt->result_done()); |
| 1102 loop_builder.BreakIfTrue(); | 1105 loop_builder.BreakIfTrue(); |
| 1103 | 1106 |
| 1104 VisitForEffect(stmt->assign_each()); | 1107 VisitForEffect(stmt->assign_each()); |
| 1105 Visit(stmt->body()); | 1108 VisitIterationBody(stmt, &loop_builder); |
| 1106 loop_builder.JumpToHeader(); | 1109 loop_builder.JumpToHeader(); |
| 1107 loop_builder.EndLoop(); | 1110 loop_builder.EndLoop(); |
| 1108 } | 1111 } |
| 1109 | 1112 |
| 1110 | 1113 |
| 1111 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 1114 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 1112 TryCatchBuilder try_control_builder(builder()); | 1115 TryCatchBuilder try_control_builder(builder()); |
| 1113 Register no_reg; | 1116 Register no_reg; |
| 1114 | 1117 |
| 1115 // Preserve the context in a dedicated register, so that it can be restored | 1118 // Preserve the context in a dedicated register, so that it can be restored |
| (...skipping 1433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2549 } | 2552 } |
| 2550 | 2553 |
| 2551 | 2554 |
| 2552 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2555 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 2553 return info()->feedback_vector()->GetIndex(slot); | 2556 return info()->feedback_vector()->GetIndex(slot); |
| 2554 } | 2557 } |
| 2555 | 2558 |
| 2556 } // namespace interpreter | 2559 } // namespace interpreter |
| 2557 } // namespace internal | 2560 } // namespace internal |
| 2558 } // namespace v8 | 2561 } // namespace v8 |
| OLD | NEW |