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

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 2882973002: [coverage] Block coverage with support for IfStatements (Closed)
Patch Set: Two fixes Created 3 years, 6 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
OLDNEW
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
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) {
rmcilroy 2017/06/02 09:35:59 nit - IncrementBlockCounter
jgruber 2017/06/02 11:38:49 Done. I assume you meant only this function and no
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
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) {
821 DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
822
785 AllocateDeferredConstants(isolate); 823 AllocateDeferredConstants(isolate);
824
825 if (info()->is_block_coverage_enabled()) {
826 info()->set_coverage_info(
827 isolate->factory()->NewCoverageInfo(block_coverage_builder_->slots()));
828 }
829
786 if (HasStackOverflow()) return Handle<BytecodeArray>(); 830 if (HasStackOverflow()) return Handle<BytecodeArray>();
787 return builder()->ToBytecodeArray(isolate); 831 return builder()->ToBytecodeArray(isolate);
788 } 832 }
789 833
790 void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate) { 834 void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate) {
791 // Build global declaration pair arrays. 835 // Build global declaration pair arrays.
792 for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) { 836 for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) {
793 Handle<FixedArray> declarations = 837 Handle<FixedArray> declarations =
794 globals_builder->AllocateDeclarations(info()); 838 globals_builder->AllocateDeclarations(info());
795 if (declarations.is_null()) return SetStackOverflow(); 839 if (declarations.is_null()) return SetStackOverflow();
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
1177 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { 1221 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
1178 builder()->SetStatementPosition(stmt); 1222 builder()->SetStatementPosition(stmt);
1179 VisitForEffect(stmt->expression()); 1223 VisitForEffect(stmt->expression());
1180 } 1224 }
1181 1225
1182 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { 1226 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
1183 } 1227 }
1184 1228
1185 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { 1229 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
1186 builder()->SetStatementPosition(stmt); 1230 builder()->SetStatementPosition(stmt);
1231
1232 int then_slot = AllocateBlockCoverageSlot(stmt->then_range());
1233 int else_slot = AllocateBlockCoverageSlot(stmt->else_range());
rmcilroy 2017/06/02 09:35:59 Any reason you need two seperate functions here? C
jgruber 2017/06/02 11:38:49 I originally had it like that, but this turned ou
rmcilroy 2017/06/02 12:52:49 Ahh I see. Can we not just infer that a block has
jgruber 2017/06/02 13:01:54 No, if the slot is not allocated then we do not kn
1234
1187 if (stmt->condition()->ToBooleanIsTrue()) { 1235 if (stmt->condition()->ToBooleanIsTrue()) {
1188 // Generate then block unconditionally as always true. 1236 // Generate then block unconditionally as always true.
1237 IncBlockCounter(then_slot);
1189 Visit(stmt->then_statement()); 1238 Visit(stmt->then_statement());
1190 } else if (stmt->condition()->ToBooleanIsFalse()) { 1239 } else if (stmt->condition()->ToBooleanIsFalse()) {
1191 // Generate else block unconditionally if it exists. 1240 // Generate else block unconditionally if it exists.
1192 if (stmt->HasElseStatement()) { 1241 if (stmt->HasElseStatement()) {
1242 IncBlockCounter(else_slot);
1193 Visit(stmt->else_statement()); 1243 Visit(stmt->else_statement());
1194 } 1244 }
1195 } else { 1245 } else {
1196 // TODO(oth): If then statement is BreakStatement or 1246 // TODO(oth): If then statement is BreakStatement or
1197 // ContinueStatement we can reduce number of generated 1247 // ContinueStatement we can reduce number of generated
1198 // jump/jump_ifs here. See BasicLoops test. 1248 // jump/jump_ifs here. See BasicLoops test.
1199 BytecodeLabel end_label; 1249 BytecodeLabel end_label;
1200 BytecodeLabels then_labels(zone()), else_labels(zone()); 1250 BytecodeLabels then_labels(zone()), else_labels(zone());
1201 VisitForTest(stmt->condition(), &then_labels, &else_labels, 1251 VisitForTest(stmt->condition(), &then_labels, &else_labels,
1202 TestFallthrough::kThen); 1252 TestFallthrough::kThen);
1203 1253
1204 then_labels.Bind(builder()); 1254 then_labels.Bind(builder());
1255 IncBlockCounter(then_slot);
1205 Visit(stmt->then_statement()); 1256 Visit(stmt->then_statement());
1206 1257
1207 if (stmt->HasElseStatement()) { 1258 if (stmt->HasElseStatement()) {
1208 builder()->Jump(&end_label); 1259 builder()->Jump(&end_label);
1209 else_labels.Bind(builder()); 1260 else_labels.Bind(builder());
1261 IncBlockCounter(else_slot);
1210 Visit(stmt->else_statement()); 1262 Visit(stmt->else_statement());
1211 } else { 1263 } else {
1212 else_labels.Bind(builder()); 1264 else_labels.Bind(builder());
1213 } 1265 }
1214 builder()->Bind(&end_label); 1266 builder()->Bind(&end_label);
1215 } 1267 }
1216 } 1268 }
1217 1269
1218 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( 1270 void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
1219 SloppyBlockFunctionStatement* stmt) { 1271 SloppyBlockFunctionStatement* stmt) {
(...skipping 2672 matching lines...) Expand 10 before | Expand all | Expand 10 after
3892 } 3944 }
3893 3945
3894 LanguageMode BytecodeGenerator::language_mode() const { 3946 LanguageMode BytecodeGenerator::language_mode() const {
3895 return current_scope()->language_mode(); 3947 return current_scope()->language_mode();
3896 } 3948 }
3897 3949
3898 int BytecodeGenerator::feedback_index(FeedbackSlot slot) const { 3950 int BytecodeGenerator::feedback_index(FeedbackSlot slot) const {
3899 return FeedbackVector::GetIndex(slot); 3951 return FeedbackVector::GetIndex(slot);
3900 } 3952 }
3901 3953
3954 int BytecodeGenerator::AllocateBlockCoverageSlot(SourceRange range) {
3955 return (block_coverage_builder_ == nullptr)
3956 ? BlockCoverageBuilder::kNoCoverageArraySlot
3957 : block_coverage_builder_->AllocateBlockCoverageSlot(range);
3958 }
3959
3960 void BytecodeGenerator::IncBlockCounter(int coverage_array_slot) {
rmcilroy 2017/06/02 09:35:59 nit - BuildIncrementBlockCoverageCounterIfEnabled.
jgruber 2017/06/02 11:38:49 Done. Also renamed AllocateBlockCoverageSlotIfEnab
3961 if (block_coverage_builder_ != nullptr) {
3962 block_coverage_builder_->IncBlockCounter(coverage_array_slot);
3963 }
3964 }
3965
3902 Runtime::FunctionId BytecodeGenerator::StoreToSuperRuntimeId() { 3966 Runtime::FunctionId BytecodeGenerator::StoreToSuperRuntimeId() {
3903 return is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict 3967 return is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict
3904 : Runtime::kStoreToSuper_Sloppy; 3968 : Runtime::kStoreToSuper_Sloppy;
3905 } 3969 }
3906 3970
3907 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { 3971 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() {
3908 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict 3972 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict
3909 : Runtime::kStoreKeyedToSuper_Sloppy; 3973 : Runtime::kStoreKeyedToSuper_Sloppy;
3910 } 3974 }
3911 3975
3912 } // namespace interpreter 3976 } // namespace interpreter
3913 } // namespace internal 3977 } // namespace internal
3914 } // namespace v8 3978 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698