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

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

Issue 2167763003: [Interpreter] Avoid allocating pairs array in VisitDeclarations. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@int_merge_binary
Patch Set: Rebase Created 4 years, 5 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/constant-array-builder.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/scopes.h" 7 #include "src/ast/scopes.h"
8 #include "src/code-stubs.h" 8 #include "src/code-stubs.h"
9 #include "src/compiler.h" 9 #include "src/compiler.h"
10 #include "src/interpreter/bytecode-flags.h" 10 #include "src/interpreter/bytecode-flags.h"
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 if (generator()->HasStackOverflow() && !result_identified()) { 525 if (generator()->HasStackOverflow() && !result_identified()) {
526 SetResultInAccumulator(); 526 SetResultInAccumulator();
527 } 527 }
528 return result_register_; 528 return result_register_;
529 } 529 }
530 530
531 private: 531 private:
532 Register result_register_; 532 Register result_register_;
533 }; 533 };
534 534
535 // Used to build a list of global declaration initial value pairs.
536 class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject {
537 public:
538 GlobalDeclarationsBuilder(Isolate* isolate, Zone* zone)
539 : isolate_(isolate),
540 declaration_pairs_(0, zone),
541 constant_pool_entry_(0),
542 has_constant_pool_entry_(false) {}
543
544 void AddDeclaration(FeedbackVectorSlot slot, Handle<Object> initial_value) {
545 DCHECK(!slot.IsInvalid());
546 declaration_pairs_.push_back(handle(Smi::FromInt(slot.ToInt()), isolate_));
547 declaration_pairs_.push_back(initial_value);
548 }
549
550 Handle<FixedArray> AllocateDeclarationPairs() {
551 DCHECK(has_constant_pool_entry_);
552 int array_index = 0;
553 Handle<FixedArray> data = isolate_->factory()->NewFixedArray(
554 static_cast<int>(declaration_pairs_.size()), TENURED);
555 for (Handle<Object> obj : declaration_pairs_) {
556 data->set(array_index++, *obj);
557 }
558 return data;
559 }
560
561 size_t constant_pool_entry() {
562 DCHECK(has_constant_pool_entry_);
563 return constant_pool_entry_;
564 }
565
566 void set_constant_pool_entry(size_t constant_pool_entry) {
567 DCHECK(!empty());
568 DCHECK(!has_constant_pool_entry_);
569 constant_pool_entry_ = constant_pool_entry;
570 has_constant_pool_entry_ = true;
571 }
572
573 bool empty() { return declaration_pairs_.empty(); }
574
575 private:
576 Isolate* isolate_;
577 ZoneVector<Handle<Object>> declaration_pairs_;
578 size_t constant_pool_entry_;
579 bool has_constant_pool_entry_;
580 };
581
535 BytecodeGenerator::BytecodeGenerator(CompilationInfo* info) 582 BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
536 : isolate_(info->isolate()), 583 : isolate_(info->isolate()),
537 zone_(info->zone()), 584 zone_(info->zone()),
538 builder_(new (zone()) BytecodeArrayBuilder( 585 builder_(new (zone()) BytecodeArrayBuilder(
539 info->isolate(), info->zone(), info->num_parameters_including_this(), 586 info->isolate(), info->zone(), info->num_parameters_including_this(),
540 info->scope()->MaxNestedContextChainLength(), 587 info->scope()->MaxNestedContextChainLength(),
541 info->scope()->num_stack_slots(), info->literal(), 588 info->scope()->num_stack_slots(), info->literal(),
542 info->SourcePositionRecordingMode())), 589 info->SourcePositionRecordingMode())),
543 info_(info), 590 info_(info),
544 scope_(info->scope()), 591 scope_(info->scope()),
545 globals_(0, info->zone()), 592 globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->isolate(),
593 info->zone())),
594 global_declarations_(0, info->zone()),
546 execution_control_(nullptr), 595 execution_control_(nullptr),
547 execution_context_(nullptr), 596 execution_context_(nullptr),
548 execution_result_(nullptr), 597 execution_result_(nullptr),
549 register_allocator_(nullptr), 598 register_allocator_(nullptr),
550 generator_resume_points_(info->literal()->yield_count(), info->zone()), 599 generator_resume_points_(info->literal()->yield_count(), info->zone()),
551 generator_state_() { 600 generator_state_() {
552 InitializeAstVisitor(isolate()->stack_guard()->real_climit()); 601 InitializeAstVisitor(isolate()->stack_guard()->real_climit());
553 } 602 }
554 603
555 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() { 604 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() {
605 GenerateBytecode();
606
607 // Build global declaration pair arrays.
608 for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) {
609 Handle<FixedArray> declarations =
610 globals_builder->AllocateDeclarationPairs();
611 builder()->InsertConstantPoolEntryAt(globals_builder->constant_pool_entry(),
612 declarations);
613 }
614
615 return builder()->ToBytecodeArray();
616 }
617
618 void BytecodeGenerator::GenerateBytecode() {
556 // Initialize the incoming context. 619 // Initialize the incoming context.
557 ContextScope incoming_context(this, scope(), false); 620 ContextScope incoming_context(this, scope(), false);
558 621
559 // Initialize control scope. 622 // Initialize control scope.
560 ControlScopeForTopLevel control(this); 623 ControlScopeForTopLevel control(this);
561 624
562 RegisterAllocationScope register_scope(this); 625 RegisterAllocationScope register_scope(this);
563 626
564 if (IsResumableFunction(info()->literal()->kind())) { 627 if (IsResumableFunction(info()->literal()->kind())) {
565 generator_state_ = register_allocator()->NewRegister(); 628 generator_state_ = register_allocator()->NewRegister();
566 VisitGeneratorPrologue(); 629 VisitGeneratorPrologue();
567 } 630 }
568 631
569 // Build function context only if there are context allocated variables. 632 // Build function context only if there are context allocated variables.
570 if (scope()->NeedsContext()) { 633 if (scope()->NeedsContext()) {
571 // Push a new inner context scope for the function. 634 // Push a new inner context scope for the function.
572 VisitNewLocalFunctionContext(); 635 VisitNewLocalFunctionContext();
573 ContextScope local_function_context(this, scope(), false); 636 ContextScope local_function_context(this, scope(), false);
574 VisitBuildLocalActivationContext(); 637 VisitBuildLocalActivationContext();
575 MakeBytecodeBody(); 638 GenerateBytecodeBody();
576 } else { 639 } else {
577 MakeBytecodeBody(); 640 GenerateBytecodeBody();
578 } 641 }
579 642
580 // In generator functions, we may not have visited every yield in the AST 643 // In generator functions, we may not have visited every yield in the AST
581 // since we skip some obviously dead code. Hence the generated bytecode may 644 // since we skip some obviously dead code. Hence the generated bytecode may
582 // contain jumps to unbound labels (resume points that will never be used). 645 // contain jumps to unbound labels (resume points that will never be used).
583 // We bind these now. 646 // We bind these now.
584 for (auto& label : generator_resume_points_) { 647 for (auto& label : generator_resume_points_) {
585 if (!label.is_bound()) builder()->Bind(&label); 648 if (!label.is_bound()) builder()->Bind(&label);
586 } 649 }
587 650
588 builder()->EnsureReturn(); 651 builder()->EnsureReturn();
589 return builder()->ToBytecodeArray();
590 } 652 }
591 653
592 void BytecodeGenerator::MakeBytecodeBody() { 654 void BytecodeGenerator::GenerateBytecodeBody() {
593 // Build the arguments object if it is used. 655 // Build the arguments object if it is used.
594 VisitArgumentsObject(scope()->arguments()); 656 VisitArgumentsObject(scope()->arguments());
595 657
596 // Build rest arguments array if it is used. 658 // Build rest arguments array if it is used.
597 int rest_index; 659 int rest_index;
598 Variable* rest_parameter = scope()->rest_parameter(&rest_index); 660 Variable* rest_parameter = scope()->rest_parameter(&rest_index);
599 VisitRestArgumentsArray(rest_parameter); 661 VisitRestArgumentsArray(rest_parameter);
600 662
601 // Build assignment to {.this_function} variable if it is used. 663 // Build assignment to {.this_function} variable if it is used.
602 VisitThisFunctionVariable(scope()->this_function_var()); 664 VisitThisFunctionVariable(scope()->this_function_var());
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
716 Variable* variable = decl->proxy()->var(); 778 Variable* variable = decl->proxy()->var();
717 VariableMode mode = decl->mode(); 779 VariableMode mode = decl->mode();
718 // Const and let variables are initialized with the hole so that we can 780 // Const and let variables are initialized with the hole so that we can
719 // check that they are only assigned once. 781 // check that they are only assigned once.
720 bool hole_init = mode == CONST || mode == LET; 782 bool hole_init = mode == CONST || mode == LET;
721 switch (variable->location()) { 783 switch (variable->location()) {
722 case VariableLocation::GLOBAL: 784 case VariableLocation::GLOBAL:
723 case VariableLocation::UNALLOCATED: { 785 case VariableLocation::UNALLOCATED: {
724 DCHECK(!variable->binding_needs_init()); 786 DCHECK(!variable->binding_needs_init());
725 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); 787 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
726 DCHECK(!slot.IsInvalid()); 788 globals_builder()->AddDeclaration(
727 globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate())); 789 slot, isolate()->factory()->undefined_value());
728 globals()->push_back(isolate()->factory()->undefined_value());
729 break; 790 break;
730 } 791 }
731 case VariableLocation::LOCAL: 792 case VariableLocation::LOCAL:
732 if (hole_init) { 793 if (hole_init) {
733 Register destination(variable->index()); 794 Register destination(variable->index());
734 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); 795 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
735 } 796 }
736 break; 797 break;
737 case VariableLocation::PARAMETER: 798 case VariableLocation::PARAMETER:
738 if (hole_init) { 799 if (hole_init) {
(...skipping 27 matching lines...) Expand all
766 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { 827 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
767 Variable* variable = decl->proxy()->var(); 828 Variable* variable = decl->proxy()->var();
768 switch (variable->location()) { 829 switch (variable->location()) {
769 case VariableLocation::GLOBAL: 830 case VariableLocation::GLOBAL:
770 case VariableLocation::UNALLOCATED: { 831 case VariableLocation::UNALLOCATED: {
771 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo( 832 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
772 decl->fun(), info()->script(), info()); 833 decl->fun(), info()->script(), info());
773 // Check for stack-overflow exception. 834 // Check for stack-overflow exception.
774 if (function.is_null()) return SetStackOverflow(); 835 if (function.is_null()) return SetStackOverflow();
775 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); 836 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
776 DCHECK(!slot.IsInvalid()); 837 globals_builder()->AddDeclaration(slot, function);
777 globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
778 globals()->push_back(function);
779 break; 838 break;
780 } 839 }
781 case VariableLocation::PARAMETER: 840 case VariableLocation::PARAMETER:
782 case VariableLocation::LOCAL: { 841 case VariableLocation::LOCAL: {
783 VisitForAccumulatorValue(decl->fun()); 842 VisitForAccumulatorValue(decl->fun());
784 DCHECK(variable->mode() == LET || variable->mode() == VAR || 843 DCHECK(variable->mode() == LET || variable->mode() == VAR ||
785 variable->mode() == CONST); 844 variable->mode() == CONST);
786 VisitVariableAssignment(variable, Token::INIT, 845 VisitVariableAssignment(variable, Token::INIT,
787 FeedbackVectorSlot::Invalid()); 846 FeedbackVectorSlot::Invalid());
788 break; 847 break;
(...skipping 14 matching lines...) Expand all
803 VisitForAccumulatorValue(decl->fun()); 862 VisitForAccumulatorValue(decl->fun());
804 builder()->StoreAccumulatorInRegister(literal).CallRuntime( 863 builder()->StoreAccumulatorInRegister(literal).CallRuntime(
805 Runtime::kDeclareEvalFunction, name, 2); 864 Runtime::kDeclareEvalFunction, name, 2);
806 } 865 }
807 } 866 }
808 } 867 }
809 868
810 void BytecodeGenerator::VisitDeclarations( 869 void BytecodeGenerator::VisitDeclarations(
811 ZoneList<Declaration*>* declarations) { 870 ZoneList<Declaration*>* declarations) {
812 RegisterAllocationScope register_scope(this); 871 RegisterAllocationScope register_scope(this);
813 DCHECK(globals()->empty()); 872 DCHECK(globals_builder()->empty());
814 for (int i = 0; i < declarations->length(); i++) { 873 for (int i = 0; i < declarations->length(); i++) {
815 RegisterAllocationScope register_scope(this); 874 RegisterAllocationScope register_scope(this);
816 Visit(declarations->at(i)); 875 Visit(declarations->at(i));
817 } 876 }
818 if (globals()->empty()) return; 877 if (globals_builder()->empty()) return;
819 int array_index = 0; 878
820 Handle<FixedArray> data = isolate()->factory()->NewFixedArray( 879 globals_builder()->set_constant_pool_entry(
821 static_cast<int>(globals()->size()), TENURED); 880 builder()->AllocateConstantPoolEntry());
822 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
823 int encoded_flags = info()->GetDeclareGlobalsFlags(); 881 int encoded_flags = info()->GetDeclareGlobalsFlags();
824 882
825 register_allocator()->PrepareForConsecutiveAllocations(3); 883 register_allocator()->PrepareForConsecutiveAllocations(3);
826 884
827 Register pairs = register_allocator()->NextConsecutiveRegister(); 885 Register pairs = register_allocator()->NextConsecutiveRegister();
828 builder()->LoadLiteral(data); 886 Register flags = register_allocator()->NextConsecutiveRegister();
829 builder()->StoreAccumulatorInRegister(pairs); 887 Register function = register_allocator()->NextConsecutiveRegister();
830 888
831 Register flags = register_allocator()->NextConsecutiveRegister(); 889 // Emit code to declare globals.
832 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); 890 builder()
833 builder()->StoreAccumulatorInRegister(flags); 891 ->LoadConstantPoolEntry(globals_builder()->constant_pool_entry())
834 DCHECK(flags.index() == pairs.index() + 1); 892 .StoreAccumulatorInRegister(pairs)
893 .LoadLiteral(Smi::FromInt(encoded_flags))
894 .StoreAccumulatorInRegister(flags)
895 .MoveRegister(Register::function_closure(), function)
896 .CallRuntime(Runtime::kDeclareGlobalsForInterpreter, pairs, 3);
835 897
836 Register function = register_allocator()->NextConsecutiveRegister(); 898 // Push and reset globals builder.
837 builder()->MoveRegister(Register::function_closure(), function); 899 global_declarations_.push_back(globals_builder());
838 900 globals_builder_ = new (zone()) GlobalDeclarationsBuilder(isolate(), zone());
839 builder()->CallRuntime(Runtime::kDeclareGlobalsForInterpreter, pairs, 3);
840 globals()->clear();
841 } 901 }
842 902
843 void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { 903 void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
844 for (int i = 0; i < statements->length(); i++) { 904 for (int i = 0; i < statements->length(); i++) {
845 // Allocate an outer register allocations scope for the statement. 905 // Allocate an outer register allocations scope for the statement.
846 RegisterAllocationScope allocation_scope(this); 906 RegisterAllocationScope allocation_scope(this);
847 Statement* stmt = statements->at(i); 907 Statement* stmt = statements->at(i);
848 Visit(stmt); 908 Visit(stmt);
849 if (stmt->IsJump()) break; 909 if (stmt->IsJump()) break;
850 } 910 }
(...skipping 2328 matching lines...) Expand 10 before | Expand all | Expand 10 after
3179 return execution_context()->scope()->language_mode(); 3239 return execution_context()->scope()->language_mode();
3180 } 3240 }
3181 3241
3182 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 3242 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
3183 return TypeFeedbackVector::GetIndex(slot); 3243 return TypeFeedbackVector::GetIndex(slot);
3184 } 3244 }
3185 3245
3186 } // namespace interpreter 3246 } // namespace interpreter
3187 } // namespace internal 3247 } // namespace internal
3188 } // namespace v8 3248 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/constant-array-builder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698