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/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/builtins/builtins-constructor.h" | 9 #include "src/builtins/builtins-constructor.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
730 const AstRawString* name; | 730 const AstRawString* name; |
731 FeedbackSlot slot; | 731 FeedbackSlot slot; |
732 FeedbackSlot literal_slot; | 732 FeedbackSlot literal_slot; |
733 FunctionLiteral* func; | 733 FunctionLiteral* func; |
734 }; | 734 }; |
735 ZoneVector<Declaration> declarations_; | 735 ZoneVector<Declaration> declarations_; |
736 size_t constant_pool_entry_; | 736 size_t constant_pool_entry_; |
737 bool has_constant_pool_entry_; | 737 bool has_constant_pool_entry_; |
738 }; | 738 }; |
739 | 739 |
740 // Used to generate IncBlockCounter bytecodes and the {source range, slot} | |
741 // mapping for block coverage. | |
742 class BytecodeGenerator::BlockCoverageBuilder final : public ZoneObject { | |
743 public: | |
744 explicit BlockCoverageBuilder(Zone* zone, BytecodeArrayBuilder* builder) | |
745 : slots_(0, zone), builder_(builder) {} | |
746 | |
747 static const int kNoCoverageArraySlot = -1; | |
748 | |
749 int AllocateBlockCoverageSlot(SourceRange range) { | |
750 if (range.IsEmpty()) return kNoCoverageArraySlot; | |
751 const int slot = static_cast<int>(slots_.size()); | |
752 slots_.emplace_back(range); | |
753 return slot; | |
754 } | |
755 | |
756 void IncBlockCounter(int coverage_array_slot) { | |
757 if (coverage_array_slot == kNoCoverageArraySlot) return; | |
758 builder_->IncBlockCounter(coverage_array_slot); | |
759 } | |
760 | |
761 const ZoneVector<SourceRange>& slots() const { return slots_; } | |
762 | |
763 private: | |
764 // Contains source range information for allocated block coverage counter | |
765 // slots. Slot i covers range slots_[i]. | |
766 ZoneVector<SourceRange> slots_; | |
767 BytecodeArrayBuilder* builder_; | |
768 }; | |
769 | |
740 class BytecodeGenerator::CurrentScope final { | 770 class BytecodeGenerator::CurrentScope final { |
741 public: | 771 public: |
742 CurrentScope(BytecodeGenerator* generator, Scope* scope) | 772 CurrentScope(BytecodeGenerator* generator, Scope* scope) |
743 : generator_(generator), outer_scope_(generator->current_scope()) { | 773 : generator_(generator), outer_scope_(generator->current_scope()) { |
744 if (scope != nullptr) { | 774 if (scope != nullptr) { |
745 generator_->set_current_scope(scope); | 775 generator_->set_current_scope(scope); |
746 } | 776 } |
747 } | 777 } |
748 ~CurrentScope() { | 778 ~CurrentScope() { |
749 if (outer_scope_ != generator_->current_scope()) { | 779 if (outer_scope_ != generator_->current_scope()) { |
(...skipping 10 matching lines...) Expand all Loading... | |
760 : zone_(info->zone()), | 790 : zone_(info->zone()), |
761 builder_(new (zone()) BytecodeArrayBuilder( | 791 builder_(new (zone()) BytecodeArrayBuilder( |
762 info->isolate(), info->zone(), info->num_parameters_including_this(), | 792 info->isolate(), info->zone(), info->num_parameters_including_this(), |
763 info->scope()->num_stack_slots(), info->literal(), | 793 info->scope()->num_stack_slots(), info->literal(), |
764 info->SourcePositionRecordingMode())), | 794 info->SourcePositionRecordingMode())), |
765 info_(info), | 795 info_(info), |
766 ast_string_constants_(info->isolate()->ast_string_constants()), | 796 ast_string_constants_(info->isolate()->ast_string_constants()), |
767 closure_scope_(info->scope()), | 797 closure_scope_(info->scope()), |
768 current_scope_(info->scope()), | 798 current_scope_(info->scope()), |
769 globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->zone())), | 799 globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->zone())), |
800 block_coverage_builder_(nullptr), | |
770 global_declarations_(0, info->zone()), | 801 global_declarations_(0, info->zone()), |
771 function_literals_(0, info->zone()), | 802 function_literals_(0, info->zone()), |
772 native_function_literals_(0, info->zone()), | 803 native_function_literals_(0, info->zone()), |
773 object_literals_(0, info->zone()), | 804 object_literals_(0, info->zone()), |
774 array_literals_(0, info->zone()), | 805 array_literals_(0, info->zone()), |
775 execution_control_(nullptr), | 806 execution_control_(nullptr), |
776 execution_context_(nullptr), | 807 execution_context_(nullptr), |
777 execution_result_(nullptr), | 808 execution_result_(nullptr), |
778 generator_jump_table_(nullptr), | 809 generator_jump_table_(nullptr), |
779 generator_state_(), | 810 generator_state_(), |
780 loop_depth_(0) { | 811 loop_depth_(0) { |
781 DCHECK_EQ(closure_scope(), closure_scope()->GetClosureScope()); | 812 DCHECK_EQ(closure_scope(), closure_scope()->GetClosureScope()); |
813 if (info->is_block_coverage_enabled()) { | |
814 DCHECK(FLAG_block_coverage); | |
815 block_coverage_builder_ = | |
816 new (zone()) BlockCoverageBuilder(zone(), builder()); | |
817 } | |
782 } | 818 } |
783 | 819 |
784 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { | 820 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { |
785 AllocateDeferredConstants(isolate); | 821 AllocateDeferredConstants(isolate); |
822 | |
marja
2017/06/02 07:01:23
Since you're touching this, can you add a DCHECK h
jgruber
2017/06/02 07:18:31
Done.
| |
823 if (info()->is_block_coverage_enabled()) { | |
824 info()->set_coverage_info( | |
825 isolate->factory()->NewCoverageInfo(block_coverage_builder_->slots())); | |
826 } | |
827 | |
786 if (HasStackOverflow()) return Handle<BytecodeArray>(); | 828 if (HasStackOverflow()) return Handle<BytecodeArray>(); |
787 return builder()->ToBytecodeArray(isolate); | 829 return builder()->ToBytecodeArray(isolate); |
788 } | 830 } |
789 | 831 |
790 void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate) { | 832 void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate) { |
791 // Build global declaration pair arrays. | 833 // Build global declaration pair arrays. |
792 for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) { | 834 for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) { |
793 Handle<FixedArray> declarations = | 835 Handle<FixedArray> declarations = |
794 globals_builder->AllocateDeclarations(info()); | 836 globals_builder->AllocateDeclarations(info()); |
795 if (declarations.is_null()) return SetStackOverflow(); | 837 if (declarations.is_null()) return SetStackOverflow(); |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1177 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | 1219 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
1178 builder()->SetStatementPosition(stmt); | 1220 builder()->SetStatementPosition(stmt); |
1179 VisitForEffect(stmt->expression()); | 1221 VisitForEffect(stmt->expression()); |
1180 } | 1222 } |
1181 | 1223 |
1182 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { | 1224 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { |
1183 } | 1225 } |
1184 | 1226 |
1185 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { | 1227 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { |
1186 builder()->SetStatementPosition(stmt); | 1228 builder()->SetStatementPosition(stmt); |
1229 | |
1230 int then_slot = AllocateBlockCoverageSlot(stmt->then_range()); | |
1231 int else_slot = AllocateBlockCoverageSlot(stmt->else_range()); | |
1232 | |
1187 if (stmt->condition()->ToBooleanIsTrue()) { | 1233 if (stmt->condition()->ToBooleanIsTrue()) { |
1188 // Generate then block unconditionally as always true. | 1234 // Generate then block unconditionally as always true. |
1235 IncBlockCounter(then_slot); | |
1189 Visit(stmt->then_statement()); | 1236 Visit(stmt->then_statement()); |
1190 } else if (stmt->condition()->ToBooleanIsFalse()) { | 1237 } else if (stmt->condition()->ToBooleanIsFalse()) { |
1191 // Generate else block unconditionally if it exists. | 1238 // Generate else block unconditionally if it exists. |
1192 if (stmt->HasElseStatement()) { | 1239 if (stmt->HasElseStatement()) { |
1240 IncBlockCounter(else_slot); | |
1193 Visit(stmt->else_statement()); | 1241 Visit(stmt->else_statement()); |
1194 } | 1242 } |
1195 } else { | 1243 } else { |
1196 // TODO(oth): If then statement is BreakStatement or | 1244 // TODO(oth): If then statement is BreakStatement or |
1197 // ContinueStatement we can reduce number of generated | 1245 // ContinueStatement we can reduce number of generated |
1198 // jump/jump_ifs here. See BasicLoops test. | 1246 // jump/jump_ifs here. See BasicLoops test. |
1199 BytecodeLabel end_label; | 1247 BytecodeLabel end_label; |
1200 BytecodeLabels then_labels(zone()), else_labels(zone()); | 1248 BytecodeLabels then_labels(zone()), else_labels(zone()); |
1201 VisitForTest(stmt->condition(), &then_labels, &else_labels, | 1249 VisitForTest(stmt->condition(), &then_labels, &else_labels, |
1202 TestFallthrough::kThen); | 1250 TestFallthrough::kThen); |
1203 | 1251 |
1204 then_labels.Bind(builder()); | 1252 then_labels.Bind(builder()); |
1253 IncBlockCounter(then_slot); | |
1205 Visit(stmt->then_statement()); | 1254 Visit(stmt->then_statement()); |
1206 | 1255 |
1207 if (stmt->HasElseStatement()) { | 1256 if (stmt->HasElseStatement()) { |
1208 builder()->Jump(&end_label); | 1257 builder()->Jump(&end_label); |
1209 else_labels.Bind(builder()); | 1258 else_labels.Bind(builder()); |
1259 IncBlockCounter(else_slot); | |
1210 Visit(stmt->else_statement()); | 1260 Visit(stmt->else_statement()); |
1211 } else { | 1261 } else { |
1212 else_labels.Bind(builder()); | 1262 else_labels.Bind(builder()); |
1213 } | 1263 } |
1214 builder()->Bind(&end_label); | 1264 builder()->Bind(&end_label); |
1215 } | 1265 } |
1216 } | 1266 } |
1217 | 1267 |
1218 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( | 1268 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( |
1219 SloppyBlockFunctionStatement* stmt) { | 1269 SloppyBlockFunctionStatement* stmt) { |
(...skipping 2672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3892 } | 3942 } |
3893 | 3943 |
3894 LanguageMode BytecodeGenerator::language_mode() const { | 3944 LanguageMode BytecodeGenerator::language_mode() const { |
3895 return current_scope()->language_mode(); | 3945 return current_scope()->language_mode(); |
3896 } | 3946 } |
3897 | 3947 |
3898 int BytecodeGenerator::feedback_index(FeedbackSlot slot) const { | 3948 int BytecodeGenerator::feedback_index(FeedbackSlot slot) const { |
3899 return FeedbackVector::GetIndex(slot); | 3949 return FeedbackVector::GetIndex(slot); |
3900 } | 3950 } |
3901 | 3951 |
3952 int BytecodeGenerator::AllocateBlockCoverageSlot(SourceRange range) { | |
3953 return (block_coverage_builder_ == nullptr) | |
3954 ? BlockCoverageBuilder::kNoCoverageArraySlot | |
3955 : block_coverage_builder_->AllocateBlockCoverageSlot(range); | |
3956 } | |
3957 | |
3958 void BytecodeGenerator::IncBlockCounter(int coverage_array_slot) { | |
3959 if (block_coverage_builder_ != nullptr) { | |
3960 block_coverage_builder_->IncBlockCounter(coverage_array_slot); | |
3961 } | |
3962 } | |
3963 | |
3902 Runtime::FunctionId BytecodeGenerator::StoreToSuperRuntimeId() { | 3964 Runtime::FunctionId BytecodeGenerator::StoreToSuperRuntimeId() { |
3903 return is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict | 3965 return is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict |
3904 : Runtime::kStoreToSuper_Sloppy; | 3966 : Runtime::kStoreToSuper_Sloppy; |
3905 } | 3967 } |
3906 | 3968 |
3907 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3969 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
3908 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3970 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
3909 : Runtime::kStoreKeyedToSuper_Sloppy; | 3971 : Runtime::kStoreKeyedToSuper_Sloppy; |
3910 } | 3972 } |
3911 | 3973 |
3912 } // namespace interpreter | 3974 } // namespace interpreter |
3913 } // namespace internal | 3975 } // namespace internal |
3914 } // namespace v8 | 3976 } // namespace v8 |
OLD | NEW |