Chromium Code Reviews| 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) { | |
|
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 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) { |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |