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

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

Issue 2882973002: [coverage] Block coverage with support for IfStatements (Closed)
Patch Set: Address comments 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
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecodes.h » ('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 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 IncrementBlockCounter(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
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 = AllocateBlockCoverageSlotIfEnabled(stmt->then_range());
1233 int else_slot = AllocateBlockCoverageSlotIfEnabled(stmt->else_range());
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 BuildIncrementBlockCoverageCounterIfEnabled(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 BuildIncrementBlockCoverageCounterIfEnabled(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 BuildIncrementBlockCoverageCounterIfEnabled(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 BuildIncrementBlockCoverageCounterIfEnabled(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 2624 matching lines...) Expand 10 before | Expand all | Expand 10 after
3844 void BytecodeGenerator::BuildLoadPropertyKey(LiteralProperty* property, 3896 void BytecodeGenerator::BuildLoadPropertyKey(LiteralProperty* property,
3845 Register out_reg) { 3897 Register out_reg) {
3846 if (property->key()->IsStringLiteral()) { 3898 if (property->key()->IsStringLiteral()) {
3847 VisitForRegisterValue(property->key(), out_reg); 3899 VisitForRegisterValue(property->key(), out_reg);
3848 } else { 3900 } else {
3849 VisitForAccumulatorValue(property->key()); 3901 VisitForAccumulatorValue(property->key());
3850 builder()->ToName(out_reg); 3902 builder()->ToName(out_reg);
3851 } 3903 }
3852 } 3904 }
3853 3905
3906 int BytecodeGenerator::AllocateBlockCoverageSlotIfEnabled(SourceRange range) {
3907 return (block_coverage_builder_ == nullptr)
3908 ? BlockCoverageBuilder::kNoCoverageArraySlot
3909 : block_coverage_builder_->AllocateBlockCoverageSlot(range);
3910 }
3911
3912 void BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
3913 int coverage_array_slot) {
3914 if (block_coverage_builder_ != nullptr) {
3915 block_coverage_builder_->IncrementBlockCounter(coverage_array_slot);
3916 }
3917 }
3918
3854 // Visits the expression |expr| for testing its boolean value and jumping to the 3919 // Visits the expression |expr| for testing its boolean value and jumping to the
3855 // |then| or |other| label depending on value and short-circuit semantics 3920 // |then| or |other| label depending on value and short-circuit semantics
3856 void BytecodeGenerator::VisitForTest(Expression* expr, 3921 void BytecodeGenerator::VisitForTest(Expression* expr,
3857 BytecodeLabels* then_labels, 3922 BytecodeLabels* then_labels,
3858 BytecodeLabels* else_labels, 3923 BytecodeLabels* else_labels,
3859 TestFallthrough fallthrough) { 3924 TestFallthrough fallthrough) {
3860 bool result_consumed; 3925 bool result_consumed;
3861 TypeHint type_hint; 3926 TypeHint type_hint;
3862 { 3927 {
3863 // To make sure that all temporary registers are returned before generating 3928 // To make sure that all temporary registers are returned before generating
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
3905 } 3970 }
3906 3971
3907 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { 3972 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() {
3908 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict 3973 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict
3909 : Runtime::kStoreKeyedToSuper_Sloppy; 3974 : Runtime::kStoreKeyedToSuper_Sloppy;
3910 } 3975 }
3911 3976
3912 } // namespace interpreter 3977 } // namespace interpreter
3913 } // namespace internal 3978 } // namespace internal
3914 } // namespace v8 3979 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698