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 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 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 = 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 Loading... |
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 Loading... |
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 |
OLD | NEW |