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) { | |
| 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 |