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 <stack> | 7 #include <stack> |
8 | 8 |
9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
10 #include "src/interpreter/control-flow-builders.h" | 10 #include "src/interpreter/control-flow-builders.h" |
11 #include "src/objects.h" | 11 #include "src/objects.h" |
12 #include "src/scopes.h" | 12 #include "src/scopes.h" |
13 #include "src/token.h" | 13 #include "src/token.h" |
14 | 14 |
15 namespace v8 { | 15 namespace v8 { |
16 namespace internal { | 16 namespace internal { |
17 namespace interpreter { | 17 namespace interpreter { |
18 | 18 |
19 | 19 |
| 20 // Scoped class tracking context objects created by the visitor. Represents |
| 21 // mutations of the context chain within the function body, allowing pushing and |
| 22 // popping of the current {context_register} during visitation. |
| 23 class BytecodeGenerator::ContextScope BASE_EMBEDDED { |
| 24 public: |
| 25 explicit ContextScope(BytecodeGenerator* generator, |
| 26 bool is_function_context = false) |
| 27 : generator_(generator), |
| 28 outer_(generator_->current_context()), |
| 29 is_function_context_(is_function_context) { |
| 30 DCHECK(!is_function_context || |
| 31 outer_.index() == Register::function_context().index()); |
| 32 Register new_context_reg = NewContextRegister(); |
| 33 generator_->builder()->PushContext(new_context_reg); |
| 34 generator_->set_current_context(new_context_reg); |
| 35 } |
| 36 |
| 37 ~ContextScope() { |
| 38 if (!is_function_context_) { |
| 39 generator_->builder()->PopContext(outer_); |
| 40 } |
| 41 generator_->set_current_context(outer_); |
| 42 } |
| 43 |
| 44 private: |
| 45 Register NewContextRegister() const { |
| 46 if (outer_.index() == Register::function_context().index()) { |
| 47 return generator_->builder()->first_context_register(); |
| 48 } else { |
| 49 DCHECK_LT(outer_.index(), |
| 50 generator_->builder()->last_context_register().index()); |
| 51 return Register(outer_.index() + 1); |
| 52 } |
| 53 } |
| 54 |
| 55 BytecodeGenerator* generator_; |
| 56 Register outer_; |
| 57 bool is_function_context_; |
| 58 }; |
| 59 |
| 60 |
20 // Scoped class for tracking control statements entered by the | 61 // Scoped class for tracking control statements entered by the |
21 // visitor. The pattern derives AstGraphBuilder::ControlScope. | 62 // visitor. The pattern derives AstGraphBuilder::ControlScope. |
22 class BytecodeGenerator::ControlScope BASE_EMBEDDED { | 63 class BytecodeGenerator::ControlScope BASE_EMBEDDED { |
23 public: | 64 public: |
24 explicit ControlScope(BytecodeGenerator* generator) | 65 explicit ControlScope(BytecodeGenerator* generator) |
25 : generator_(generator), outer_(generator->control_scope()) { | 66 : generator_(generator), outer_(generator->control_scope()) { |
26 generator_->set_control_scope(this); | 67 generator_->set_control_scope(this); |
27 } | 68 } |
28 virtual ~ControlScope() { generator_->set_control_scope(outer()); } | 69 virtual ~ControlScope() { generator_->set_control_scope(outer()); } |
29 | 70 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 | 143 |
103 BytecodeGenerator::~BytecodeGenerator() {} | 144 BytecodeGenerator::~BytecodeGenerator() {} |
104 | 145 |
105 | 146 |
106 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { | 147 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { |
107 set_info(info); | 148 set_info(info); |
108 set_scope(info->scope()); | 149 set_scope(info->scope()); |
109 | 150 |
110 builder()->set_parameter_count(info->num_parameters_including_this()); | 151 builder()->set_parameter_count(info->num_parameters_including_this()); |
111 builder()->set_locals_count(scope()->num_stack_slots()); | 152 builder()->set_locals_count(scope()->num_stack_slots()); |
| 153 // TODO(rmcilroy): Set correct context count. |
| 154 builder()->set_context_count(info->num_heap_slots() > 0 ? 1 : 0); |
112 | 155 |
113 // Visit implicit declaration of the function name. | 156 // Build function context only if there are context allocated variables. |
114 if (scope()->is_function_scope() && scope()->function() != NULL) { | 157 if (info->num_heap_slots() > 0) { |
115 VisitVariableDeclaration(scope()->function()); | 158 // Push a new inner context scope for the function. |
| 159 VisitNewLocalFunctionContext(); |
| 160 ContextScope top_context(this, true); |
| 161 MakeBytecodeBody(); |
| 162 } else { |
| 163 MakeBytecodeBody(); |
116 } | 164 } |
117 | 165 |
118 // Visit declarations within the function scope. | |
119 VisitDeclarations(scope()->declarations()); | |
120 | |
121 // Visit statements in the function body. | |
122 VisitStatements(info->literal()->body()); | |
123 | |
124 set_scope(nullptr); | 166 set_scope(nullptr); |
125 set_info(nullptr); | 167 set_info(nullptr); |
126 return builder_.ToBytecodeArray(); | 168 return builder_.ToBytecodeArray(); |
127 } | 169 } |
128 | 170 |
129 | 171 |
| 172 void BytecodeGenerator::MakeBytecodeBody() { |
| 173 // Visit declarations within the function scope. |
| 174 VisitDeclarations(scope()->declarations()); |
| 175 |
| 176 // Visit statements in the function body. |
| 177 VisitStatements(info()->literal()->body()); |
| 178 } |
| 179 |
| 180 |
130 void BytecodeGenerator::VisitBlock(Block* node) { | 181 void BytecodeGenerator::VisitBlock(Block* node) { |
131 builder()->EnterBlock(); | 182 builder()->EnterBlock(); |
132 if (node->scope() == NULL) { | 183 if (node->scope() == NULL) { |
133 // Visit statements in the same scope, no declarations. | 184 // Visit statements in the same scope, no declarations. |
134 VisitStatements(node->statements()); | 185 VisitStatements(node->statements()); |
135 } else { | 186 } else { |
136 // Visit declarations and statements in a block scope. | 187 // Visit declarations and statements in a block scope. |
137 if (node->scope()->ContextLocalCount() > 0) { | 188 if (node->scope()->ContextLocalCount() > 0) { |
138 UNIMPLEMENTED(); | 189 UNIMPLEMENTED(); |
139 } else { | 190 } else { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 AstVisitor::VisitDeclarations(declarations); | 263 AstVisitor::VisitDeclarations(declarations); |
213 if (globals()->empty()) return; | 264 if (globals()->empty()) return; |
214 int array_index = 0; | 265 int array_index = 0; |
215 Handle<FixedArray> data = isolate()->factory()->NewFixedArray( | 266 Handle<FixedArray> data = isolate()->factory()->NewFixedArray( |
216 static_cast<int>(globals()->size()), TENURED); | 267 static_cast<int>(globals()->size()), TENURED); |
217 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj); | 268 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj); |
218 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | | 269 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | |
219 DeclareGlobalsNativeFlag::encode(info()->is_native()) | | 270 DeclareGlobalsNativeFlag::encode(info()->is_native()) | |
220 DeclareGlobalsLanguageMode::encode(language_mode()); | 271 DeclareGlobalsLanguageMode::encode(language_mode()); |
221 | 272 |
222 TemporaryRegisterScope temporary_register_scope(&builder_); | 273 TemporaryRegisterScope temporary_register_scope(builder()); |
223 Register pairs = temporary_register_scope.NewRegister(); | 274 Register pairs = temporary_register_scope.NewRegister(); |
224 builder()->LoadLiteral(data); | 275 builder()->LoadLiteral(data); |
225 builder()->StoreAccumulatorInRegister(pairs); | 276 builder()->StoreAccumulatorInRegister(pairs); |
226 | 277 |
227 Register flags = temporary_register_scope.NewRegister(); | 278 Register flags = temporary_register_scope.NewRegister(); |
228 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); | 279 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); |
229 builder()->StoreAccumulatorInRegister(flags); | 280 builder()->StoreAccumulatorInRegister(flags); |
230 DCHECK(flags.index() == pairs.index() + 1); | 281 DCHECK(flags.index() == pairs.index() + 1); |
231 | 282 |
232 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); | 283 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 case VariableLocation::GLOBAL: { | 528 case VariableLocation::GLOBAL: { |
478 // Global var, const, or let variable. | 529 // Global var, const, or let variable. |
479 // TODO(rmcilroy): If context chain depth is short enough, do this using | 530 // TODO(rmcilroy): If context chain depth is short enough, do this using |
480 // a generic version of LoadGlobalViaContextStub rather than calling the | 531 // a generic version of LoadGlobalViaContextStub rather than calling the |
481 // runtime. | 532 // runtime. |
482 DCHECK(variable->IsStaticGlobalObjectProperty()); | 533 DCHECK(variable->IsStaticGlobalObjectProperty()); |
483 builder()->LoadGlobal(variable->index()); | 534 builder()->LoadGlobal(variable->index()); |
484 break; | 535 break; |
485 } | 536 } |
486 case VariableLocation::UNALLOCATED: { | 537 case VariableLocation::UNALLOCATED: { |
487 TemporaryRegisterScope temporary_register_scope(&builder_); | 538 TemporaryRegisterScope temporary_register_scope(builder()); |
488 Register obj = temporary_register_scope.NewRegister(); | 539 Register obj = temporary_register_scope.NewRegister(); |
489 builder()->LoadContextSlot(current_context(), | 540 builder()->LoadContextSlot(current_context(), |
490 Context::GLOBAL_OBJECT_INDEX); | 541 Context::GLOBAL_OBJECT_INDEX); |
491 builder()->StoreAccumulatorInRegister(obj); | 542 builder()->StoreAccumulatorInRegister(obj); |
492 builder()->LoadLiteral(variable->name()); | 543 builder()->LoadLiteral(variable->name()); |
493 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); | 544 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); |
494 break; | 545 break; |
495 } | 546 } |
496 case VariableLocation::CONTEXT: | 547 case VariableLocation::CONTEXT: |
497 case VariableLocation::LOOKUP: | 548 case VariableLocation::LOOKUP: |
(...skipping 21 matching lines...) Expand all Loading... |
519 case VariableLocation::GLOBAL: { | 570 case VariableLocation::GLOBAL: { |
520 // Global var, const, or let variable. | 571 // Global var, const, or let variable. |
521 // TODO(rmcilroy): If context chain depth is short enough, do this using | 572 // TODO(rmcilroy): If context chain depth is short enough, do this using |
522 // a generic version of LoadGlobalViaContextStub rather than calling the | 573 // a generic version of LoadGlobalViaContextStub rather than calling the |
523 // runtime. | 574 // runtime. |
524 DCHECK(variable->IsStaticGlobalObjectProperty()); | 575 DCHECK(variable->IsStaticGlobalObjectProperty()); |
525 builder()->StoreGlobal(variable->index(), language_mode()); | 576 builder()->StoreGlobal(variable->index(), language_mode()); |
526 break; | 577 break; |
527 } | 578 } |
528 case VariableLocation::UNALLOCATED: { | 579 case VariableLocation::UNALLOCATED: { |
529 TemporaryRegisterScope temporary_register_scope(&builder_); | 580 TemporaryRegisterScope temporary_register_scope(builder()); |
530 Register value = temporary_register_scope.NewRegister(); | 581 Register value = temporary_register_scope.NewRegister(); |
531 Register obj = temporary_register_scope.NewRegister(); | 582 Register obj = temporary_register_scope.NewRegister(); |
532 Register name = temporary_register_scope.NewRegister(); | 583 Register name = temporary_register_scope.NewRegister(); |
533 // TODO(rmcilroy): Investigate whether we can avoid having to stash the | 584 // TODO(rmcilroy): Investigate whether we can avoid having to stash the |
534 // value in a register. | 585 // value in a register. |
535 builder()->StoreAccumulatorInRegister(value); | 586 builder()->StoreAccumulatorInRegister(value); |
536 builder()->LoadContextSlot(current_context(), | 587 builder()->LoadContextSlot(current_context(), |
537 Context::GLOBAL_OBJECT_INDEX); | 588 Context::GLOBAL_OBJECT_INDEX); |
538 builder()->StoreAccumulatorInRegister(obj); | 589 builder()->StoreAccumulatorInRegister(obj); |
539 builder()->LoadLiteral(variable->name()); | 590 builder()->LoadLiteral(variable->name()); |
540 builder()->StoreAccumulatorInRegister(name); | 591 builder()->StoreAccumulatorInRegister(name); |
541 builder()->LoadAccumulatorWithRegister(value); | 592 builder()->LoadAccumulatorWithRegister(value); |
542 builder()->StoreNamedProperty(obj, name, feedback_index(slot), | 593 builder()->StoreNamedProperty(obj, name, feedback_index(slot), |
543 language_mode()); | 594 language_mode()); |
544 break; | 595 break; |
545 } | 596 } |
546 case VariableLocation::CONTEXT: | 597 case VariableLocation::CONTEXT: |
547 case VariableLocation::LOOKUP: | 598 case VariableLocation::LOOKUP: |
548 UNIMPLEMENTED(); | 599 UNIMPLEMENTED(); |
549 } | 600 } |
550 } | 601 } |
551 | 602 |
552 | 603 |
553 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 604 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
554 DCHECK(expr->target()->IsValidReferenceExpression()); | 605 DCHECK(expr->target()->IsValidReferenceExpression()); |
555 TemporaryRegisterScope temporary_register_scope(&builder_); | 606 TemporaryRegisterScope temporary_register_scope(builder()); |
556 Register object, key; | 607 Register object, key; |
557 | 608 |
558 // Left-hand side can only be a property, a global or a variable slot. | 609 // Left-hand side can only be a property, a global or a variable slot. |
559 Property* property = expr->target()->AsProperty(); | 610 Property* property = expr->target()->AsProperty(); |
560 LhsKind assign_type = Property::GetAssignType(property); | 611 LhsKind assign_type = Property::GetAssignType(property); |
561 | 612 |
562 // Evaluate LHS expression. | 613 // Evaluate LHS expression. |
563 switch (assign_type) { | 614 switch (assign_type) { |
564 case VARIABLE: | 615 case VARIABLE: |
565 // Nothing to do to evaluate variable assignment LHS. | 616 // Nothing to do to evaluate variable assignment LHS. |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 break; | 690 break; |
640 } | 691 } |
641 case NAMED_SUPER_PROPERTY: | 692 case NAMED_SUPER_PROPERTY: |
642 case KEYED_SUPER_PROPERTY: | 693 case KEYED_SUPER_PROPERTY: |
643 UNIMPLEMENTED(); | 694 UNIMPLEMENTED(); |
644 } | 695 } |
645 } | 696 } |
646 | 697 |
647 | 698 |
648 void BytecodeGenerator::VisitProperty(Property* expr) { | 699 void BytecodeGenerator::VisitProperty(Property* expr) { |
649 TemporaryRegisterScope temporary_register_scope(&builder_); | 700 TemporaryRegisterScope temporary_register_scope(builder()); |
650 Register obj = temporary_register_scope.NewRegister(); | 701 Register obj = temporary_register_scope.NewRegister(); |
651 Visit(expr->obj()); | 702 Visit(expr->obj()); |
652 builder()->StoreAccumulatorInRegister(obj); | 703 builder()->StoreAccumulatorInRegister(obj); |
653 VisitPropertyLoad(obj, expr); | 704 VisitPropertyLoad(obj, expr); |
654 } | 705 } |
655 | 706 |
656 | 707 |
657 void BytecodeGenerator::VisitCall(Call* expr) { | 708 void BytecodeGenerator::VisitCall(Call* expr) { |
658 Expression* callee_expr = expr->expression(); | 709 Expression* callee_expr = expr->expression(); |
659 Call::CallType call_type = expr->GetCallType(isolate()); | 710 Call::CallType call_type = expr->GetCallType(isolate()); |
660 | 711 |
661 // Prepare the callee and the receiver to the function call. This depends on | 712 // Prepare the callee and the receiver to the function call. This depends on |
662 // the semantics of the underlying call type. | 713 // the semantics of the underlying call type. |
663 TemporaryRegisterScope temporary_register_scope(&builder_); | 714 TemporaryRegisterScope temporary_register_scope(builder()); |
664 Register callee = temporary_register_scope.NewRegister(); | 715 Register callee = temporary_register_scope.NewRegister(); |
665 Register receiver = temporary_register_scope.NewRegister(); | 716 Register receiver = temporary_register_scope.NewRegister(); |
666 | 717 |
667 switch (call_type) { | 718 switch (call_type) { |
668 case Call::PROPERTY_CALL: { | 719 case Call::PROPERTY_CALL: { |
669 Property* property = callee_expr->AsProperty(); | 720 Property* property = callee_expr->AsProperty(); |
670 if (property->IsSuperAccess()) { | 721 if (property->IsSuperAccess()) { |
671 UNIMPLEMENTED(); | 722 UNIMPLEMENTED(); |
672 } | 723 } |
673 Visit(property->obj()); | 724 Visit(property->obj()); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); } | 768 void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); } |
718 | 769 |
719 | 770 |
720 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 771 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
721 if (expr->is_jsruntime()) { | 772 if (expr->is_jsruntime()) { |
722 UNIMPLEMENTED(); | 773 UNIMPLEMENTED(); |
723 } | 774 } |
724 | 775 |
725 // Evaluate all arguments to the runtime call. | 776 // Evaluate all arguments to the runtime call. |
726 ZoneList<Expression*>* args = expr->arguments(); | 777 ZoneList<Expression*>* args = expr->arguments(); |
727 TemporaryRegisterScope temporary_register_scope(&builder_); | 778 TemporaryRegisterScope temporary_register_scope(builder()); |
728 // Ensure we always have a valid first_arg register even if there are no | 779 // Ensure we always have a valid first_arg register even if there are no |
729 // arguments to pass. | 780 // arguments to pass. |
730 Register first_arg = temporary_register_scope.NewRegister(); | 781 Register first_arg = temporary_register_scope.NewRegister(); |
731 for (int i = 0; i < args->length(); ++i) { | 782 for (int i = 0; i < args->length(); ++i) { |
732 Register arg = | 783 Register arg = |
733 (i == 0) ? first_arg : temporary_register_scope.NewRegister(); | 784 (i == 0) ? first_arg : temporary_register_scope.NewRegister(); |
734 Visit(args->at(i)); | 785 Visit(args->at(i)); |
735 DCHECK_EQ(arg.index() - i, first_arg.index()); | 786 DCHECK_EQ(arg.index() - i, first_arg.index()); |
736 builder()->StoreAccumulatorInRegister(arg); | 787 builder()->StoreAccumulatorInRegister(arg); |
737 } | 788 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
798 break; | 849 break; |
799 } | 850 } |
800 } | 851 } |
801 | 852 |
802 | 853 |
803 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 854 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
804 Token::Value op = expr->op(); | 855 Token::Value op = expr->op(); |
805 Expression* left = expr->left(); | 856 Expression* left = expr->left(); |
806 Expression* right = expr->right(); | 857 Expression* right = expr->right(); |
807 | 858 |
808 TemporaryRegisterScope temporary_register_scope(&builder_); | 859 TemporaryRegisterScope temporary_register_scope(builder()); |
809 Register temporary = temporary_register_scope.NewRegister(); | 860 Register temporary = temporary_register_scope.NewRegister(); |
810 | 861 |
811 Visit(left); | 862 Visit(left); |
812 builder()->StoreAccumulatorInRegister(temporary); | 863 builder()->StoreAccumulatorInRegister(temporary); |
813 Visit(right); | 864 Visit(right); |
814 builder()->CompareOperation(op, temporary, language_mode_strength()); | 865 builder()->CompareOperation(op, temporary, language_mode_strength()); |
815 } | 866 } |
816 | 867 |
817 | 868 |
818 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } | 869 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } |
(...skipping 13 matching lines...) Expand all Loading... |
832 UNIMPLEMENTED(); | 883 UNIMPLEMENTED(); |
833 } | 884 } |
834 | 885 |
835 | 886 |
836 void BytecodeGenerator::VisitSuperPropertyReference( | 887 void BytecodeGenerator::VisitSuperPropertyReference( |
837 SuperPropertyReference* expr) { | 888 SuperPropertyReference* expr) { |
838 UNIMPLEMENTED(); | 889 UNIMPLEMENTED(); |
839 } | 890 } |
840 | 891 |
841 | 892 |
| 893 void BytecodeGenerator::VisitNewLocalFunctionContext() { |
| 894 Scope* scope = this->scope(); |
| 895 |
| 896 // Allocate a new local context. |
| 897 if (scope->is_script_scope()) { |
| 898 TemporaryRegisterScope temporary_register_scope(builder()); |
| 899 Register closure = temporary_register_scope.NewRegister(); |
| 900 Register scope_info = temporary_register_scope.NewRegister(); |
| 901 DCHECK_EQ(closure.index() + 1, scope_info.index()); |
| 902 builder() |
| 903 ->LoadAccumulatorWithRegister(Register::function_closure()) |
| 904 .StoreAccumulatorInRegister(closure) |
| 905 .LoadLiteral(scope->GetScopeInfo(isolate())) |
| 906 .StoreAccumulatorInRegister(scope_info) |
| 907 .CallRuntime(Runtime::kNewScriptContext, closure, 2); |
| 908 } else { |
| 909 builder()->CallRuntime(Runtime::kNewFunctionContext, |
| 910 Register::function_closure(), 1); |
| 911 } |
| 912 |
| 913 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { |
| 914 UNIMPLEMENTED(); |
| 915 } |
| 916 |
| 917 // Copy parameters into context if necessary. |
| 918 int num_parameters = scope->num_parameters(); |
| 919 for (int i = 0; i < num_parameters; i++) { |
| 920 Variable* variable = scope->parameter(i); |
| 921 if (variable->IsContextSlot()) { |
| 922 UNIMPLEMENTED(); |
| 923 } |
| 924 } |
| 925 } |
| 926 |
| 927 |
842 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { | 928 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { |
843 Token::Value op = binop->op(); | 929 Token::Value op = binop->op(); |
844 Expression* left = binop->left(); | 930 Expression* left = binop->left(); |
845 Expression* right = binop->right(); | 931 Expression* right = binop->right(); |
846 | 932 |
847 TemporaryRegisterScope temporary_register_scope(&builder_); | 933 TemporaryRegisterScope temporary_register_scope(builder()); |
848 Register temporary = temporary_register_scope.NewRegister(); | 934 Register temporary = temporary_register_scope.NewRegister(); |
849 | 935 |
850 Visit(left); | 936 Visit(left); |
851 builder()->StoreAccumulatorInRegister(temporary); | 937 builder()->StoreAccumulatorInRegister(temporary); |
852 Visit(right); | 938 Visit(right); |
853 builder()->BinaryOperation(op, temporary, language_mode_strength()); | 939 builder()->BinaryOperation(op, temporary, language_mode_strength()); |
854 } | 940 } |
855 | 941 |
856 | 942 |
857 LanguageMode BytecodeGenerator::language_mode() const { | 943 LanguageMode BytecodeGenerator::language_mode() const { |
858 return info()->language_mode(); | 944 return info()->language_mode(); |
859 } | 945 } |
860 | 946 |
861 | 947 |
862 Strength BytecodeGenerator::language_mode_strength() const { | 948 Strength BytecodeGenerator::language_mode_strength() const { |
863 return strength(language_mode()); | 949 return strength(language_mode()); |
864 } | 950 } |
865 | 951 |
866 | 952 |
867 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 953 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
868 return info()->feedback_vector()->GetIndex(slot); | 954 return info()->feedback_vector()->GetIndex(slot); |
869 } | 955 } |
870 | 956 |
871 | |
872 Register BytecodeGenerator::current_context() const { return current_context_; } | |
873 | |
874 } // namespace interpreter | 957 } // namespace interpreter |
875 } // namespace internal | 958 } // namespace internal |
876 } // namespace v8 | 959 } // namespace v8 |
OLD | NEW |