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 and allows to | |
22 // change the current {scope} and {context} during visitation. | |
Michael Starzinger
2015/10/13 09:38:43
nit: Comment looks outdated. Doesn't really track
rmcilroy
2015/10/13 10:35:22
Done.
| |
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); | |
Michael Starzinger
2015/10/13 09:38:43
How hard will it be to determine in advance how de
rmcilroy
2015/10/13 10:35:22
Yeah, we don't have that information yet. I'll nee
Michael Starzinger
2015/10/13 11:12:13
Acknowledged. Not sure how hard/easy this will be,
| |
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 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
470 case VariableLocation::GLOBAL: { | 521 case VariableLocation::GLOBAL: { |
471 // Global var, const, or let variable. | 522 // Global var, const, or let variable. |
472 // TODO(rmcilroy): If context chain depth is short enough, do this using | 523 // TODO(rmcilroy): If context chain depth is short enough, do this using |
473 // a generic version of LoadGlobalViaContextStub rather than calling the | 524 // a generic version of LoadGlobalViaContextStub rather than calling the |
474 // runtime. | 525 // runtime. |
475 DCHECK(variable->IsStaticGlobalObjectProperty()); | 526 DCHECK(variable->IsStaticGlobalObjectProperty()); |
476 builder()->LoadGlobal(variable->index()); | 527 builder()->LoadGlobal(variable->index()); |
477 break; | 528 break; |
478 } | 529 } |
479 case VariableLocation::UNALLOCATED: { | 530 case VariableLocation::UNALLOCATED: { |
480 TemporaryRegisterScope temporary_register_scope(&builder_); | 531 TemporaryRegisterScope temporary_register_scope(builder()); |
481 Register obj = temporary_register_scope.NewRegister(); | 532 Register obj = temporary_register_scope.NewRegister(); |
482 builder()->LoadContextSlot(current_context(), | 533 builder()->LoadContextSlot(current_context(), |
483 Context::GLOBAL_OBJECT_INDEX); | 534 Context::GLOBAL_OBJECT_INDEX); |
484 builder()->StoreAccumulatorInRegister(obj); | 535 builder()->StoreAccumulatorInRegister(obj); |
485 builder()->LoadLiteral(variable->name()); | 536 builder()->LoadLiteral(variable->name()); |
486 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); | 537 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); |
487 break; | 538 break; |
488 } | 539 } |
489 case VariableLocation::CONTEXT: | 540 case VariableLocation::CONTEXT: |
490 case VariableLocation::LOOKUP: | 541 case VariableLocation::LOOKUP: |
(...skipping 21 matching lines...) Expand all Loading... | |
512 case VariableLocation::GLOBAL: { | 563 case VariableLocation::GLOBAL: { |
513 // Global var, const, or let variable. | 564 // Global var, const, or let variable. |
514 // TODO(rmcilroy): If context chain depth is short enough, do this using | 565 // TODO(rmcilroy): If context chain depth is short enough, do this using |
515 // a generic version of LoadGlobalViaContextStub rather than calling the | 566 // a generic version of LoadGlobalViaContextStub rather than calling the |
516 // runtime. | 567 // runtime. |
517 DCHECK(variable->IsStaticGlobalObjectProperty()); | 568 DCHECK(variable->IsStaticGlobalObjectProperty()); |
518 builder()->StoreGlobal(variable->index(), language_mode()); | 569 builder()->StoreGlobal(variable->index(), language_mode()); |
519 break; | 570 break; |
520 } | 571 } |
521 case VariableLocation::UNALLOCATED: { | 572 case VariableLocation::UNALLOCATED: { |
522 TemporaryRegisterScope temporary_register_scope(&builder_); | 573 TemporaryRegisterScope temporary_register_scope(builder()); |
523 Register value = temporary_register_scope.NewRegister(); | 574 Register value = temporary_register_scope.NewRegister(); |
524 Register obj = temporary_register_scope.NewRegister(); | 575 Register obj = temporary_register_scope.NewRegister(); |
525 Register name = temporary_register_scope.NewRegister(); | 576 Register name = temporary_register_scope.NewRegister(); |
526 // TODO(rmcilroy): Investigate whether we can avoid having to stash the | 577 // TODO(rmcilroy): Investigate whether we can avoid having to stash the |
527 // value in a register. | 578 // value in a register. |
528 builder()->StoreAccumulatorInRegister(value); | 579 builder()->StoreAccumulatorInRegister(value); |
529 builder()->LoadContextSlot(current_context(), | 580 builder()->LoadContextSlot(current_context(), |
530 Context::GLOBAL_OBJECT_INDEX); | 581 Context::GLOBAL_OBJECT_INDEX); |
531 builder()->StoreAccumulatorInRegister(obj); | 582 builder()->StoreAccumulatorInRegister(obj); |
532 builder()->LoadLiteral(variable->name()); | 583 builder()->LoadLiteral(variable->name()); |
533 builder()->StoreAccumulatorInRegister(name); | 584 builder()->StoreAccumulatorInRegister(name); |
534 builder()->LoadAccumulatorWithRegister(value); | 585 builder()->LoadAccumulatorWithRegister(value); |
535 builder()->StoreNamedProperty(obj, name, feedback_index(slot), | 586 builder()->StoreNamedProperty(obj, name, feedback_index(slot), |
536 language_mode()); | 587 language_mode()); |
537 break; | 588 break; |
538 } | 589 } |
539 case VariableLocation::CONTEXT: | 590 case VariableLocation::CONTEXT: |
540 case VariableLocation::LOOKUP: | 591 case VariableLocation::LOOKUP: |
541 UNIMPLEMENTED(); | 592 UNIMPLEMENTED(); |
542 } | 593 } |
543 } | 594 } |
544 | 595 |
545 | 596 |
546 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 597 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
547 DCHECK(expr->target()->IsValidReferenceExpression()); | 598 DCHECK(expr->target()->IsValidReferenceExpression()); |
548 TemporaryRegisterScope temporary_register_scope(&builder_); | 599 TemporaryRegisterScope temporary_register_scope(builder()); |
549 Register object, key; | 600 Register object, key; |
550 | 601 |
551 // Left-hand side can only be a property, a global or a variable slot. | 602 // Left-hand side can only be a property, a global or a variable slot. |
552 Property* property = expr->target()->AsProperty(); | 603 Property* property = expr->target()->AsProperty(); |
553 LhsKind assign_type = Property::GetAssignType(property); | 604 LhsKind assign_type = Property::GetAssignType(property); |
554 | 605 |
555 // Evaluate LHS expression. | 606 // Evaluate LHS expression. |
556 switch (assign_type) { | 607 switch (assign_type) { |
557 case VARIABLE: | 608 case VARIABLE: |
558 // Nothing to do to evaluate variable assignment LHS. | 609 // Nothing to do to evaluate variable assignment LHS. |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
632 break; | 683 break; |
633 } | 684 } |
634 case NAMED_SUPER_PROPERTY: | 685 case NAMED_SUPER_PROPERTY: |
635 case KEYED_SUPER_PROPERTY: | 686 case KEYED_SUPER_PROPERTY: |
636 UNIMPLEMENTED(); | 687 UNIMPLEMENTED(); |
637 } | 688 } |
638 } | 689 } |
639 | 690 |
640 | 691 |
641 void BytecodeGenerator::VisitProperty(Property* expr) { | 692 void BytecodeGenerator::VisitProperty(Property* expr) { |
642 TemporaryRegisterScope temporary_register_scope(&builder_); | 693 TemporaryRegisterScope temporary_register_scope(builder()); |
643 Register obj = temporary_register_scope.NewRegister(); | 694 Register obj = temporary_register_scope.NewRegister(); |
644 Visit(expr->obj()); | 695 Visit(expr->obj()); |
645 builder()->StoreAccumulatorInRegister(obj); | 696 builder()->StoreAccumulatorInRegister(obj); |
646 VisitPropertyLoad(obj, expr); | 697 VisitPropertyLoad(obj, expr); |
647 } | 698 } |
648 | 699 |
649 | 700 |
650 void BytecodeGenerator::VisitCall(Call* expr) { | 701 void BytecodeGenerator::VisitCall(Call* expr) { |
651 Expression* callee_expr = expr->expression(); | 702 Expression* callee_expr = expr->expression(); |
652 Call::CallType call_type = expr->GetCallType(isolate()); | 703 Call::CallType call_type = expr->GetCallType(isolate()); |
653 | 704 |
654 // Prepare the callee and the receiver to the function call. This depends on | 705 // Prepare the callee and the receiver to the function call. This depends on |
655 // the semantics of the underlying call type. | 706 // the semantics of the underlying call type. |
656 TemporaryRegisterScope temporary_register_scope(&builder_); | 707 TemporaryRegisterScope temporary_register_scope(builder()); |
657 Register callee = temporary_register_scope.NewRegister(); | 708 Register callee = temporary_register_scope.NewRegister(); |
658 Register receiver = temporary_register_scope.NewRegister(); | 709 Register receiver = temporary_register_scope.NewRegister(); |
659 | 710 |
660 switch (call_type) { | 711 switch (call_type) { |
661 case Call::PROPERTY_CALL: { | 712 case Call::PROPERTY_CALL: { |
662 Property* property = callee_expr->AsProperty(); | 713 Property* property = callee_expr->AsProperty(); |
663 if (property->IsSuperAccess()) { | 714 if (property->IsSuperAccess()) { |
664 UNIMPLEMENTED(); | 715 UNIMPLEMENTED(); |
665 } | 716 } |
666 Visit(property->obj()); | 717 Visit(property->obj()); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
705 void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); } | 756 void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); } |
706 | 757 |
707 | 758 |
708 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 759 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
709 if (expr->is_jsruntime()) { | 760 if (expr->is_jsruntime()) { |
710 UNIMPLEMENTED(); | 761 UNIMPLEMENTED(); |
711 } | 762 } |
712 | 763 |
713 // Evaluate all arguments to the runtime call. | 764 // Evaluate all arguments to the runtime call. |
714 ZoneList<Expression*>* args = expr->arguments(); | 765 ZoneList<Expression*>* args = expr->arguments(); |
715 TemporaryRegisterScope temporary_register_scope(&builder_); | 766 TemporaryRegisterScope temporary_register_scope(builder()); |
716 // Ensure we always have a valid first_arg register even if there are no | 767 // Ensure we always have a valid first_arg register even if there are no |
717 // arguments to pass. | 768 // arguments to pass. |
718 Register first_arg = temporary_register_scope.NewRegister(); | 769 Register first_arg = temporary_register_scope.NewRegister(); |
719 for (int i = 0; i < args->length(); ++i) { | 770 for (int i = 0; i < args->length(); ++i) { |
720 Register arg = | 771 Register arg = |
721 (i == 0) ? first_arg : temporary_register_scope.NewRegister(); | 772 (i == 0) ? first_arg : temporary_register_scope.NewRegister(); |
722 Visit(args->at(i)); | 773 Visit(args->at(i)); |
723 DCHECK_EQ(arg.index() - i, first_arg.index()); | 774 DCHECK_EQ(arg.index() - i, first_arg.index()); |
724 builder()->StoreAccumulatorInRegister(arg); | 775 builder()->StoreAccumulatorInRegister(arg); |
725 } | 776 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
786 break; | 837 break; |
787 } | 838 } |
788 } | 839 } |
789 | 840 |
790 | 841 |
791 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 842 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
792 Token::Value op = expr->op(); | 843 Token::Value op = expr->op(); |
793 Expression* left = expr->left(); | 844 Expression* left = expr->left(); |
794 Expression* right = expr->right(); | 845 Expression* right = expr->right(); |
795 | 846 |
796 TemporaryRegisterScope temporary_register_scope(&builder_); | 847 TemporaryRegisterScope temporary_register_scope(builder()); |
797 Register temporary = temporary_register_scope.NewRegister(); | 848 Register temporary = temporary_register_scope.NewRegister(); |
798 | 849 |
799 Visit(left); | 850 Visit(left); |
800 builder()->StoreAccumulatorInRegister(temporary); | 851 builder()->StoreAccumulatorInRegister(temporary); |
801 Visit(right); | 852 Visit(right); |
802 builder()->CompareOperation(op, temporary, language_mode_strength()); | 853 builder()->CompareOperation(op, temporary, language_mode_strength()); |
803 } | 854 } |
804 | 855 |
805 | 856 |
806 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } | 857 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } |
(...skipping 13 matching lines...) Expand all Loading... | |
820 UNIMPLEMENTED(); | 871 UNIMPLEMENTED(); |
821 } | 872 } |
822 | 873 |
823 | 874 |
824 void BytecodeGenerator::VisitSuperPropertyReference( | 875 void BytecodeGenerator::VisitSuperPropertyReference( |
825 SuperPropertyReference* expr) { | 876 SuperPropertyReference* expr) { |
826 UNIMPLEMENTED(); | 877 UNIMPLEMENTED(); |
827 } | 878 } |
828 | 879 |
829 | 880 |
881 void BytecodeGenerator::VisitNewLocalFunctionContext() { | |
882 Scope* scope = this->scope(); | |
883 | |
884 // Allocate a new local context. | |
885 if (scope->is_script_scope()) { | |
886 TemporaryRegisterScope temporary_register_scope(builder()); | |
887 Register closure = temporary_register_scope.NewRegister(); | |
888 Register scope_info = temporary_register_scope.NewRegister(); | |
889 DCHECK_EQ(closure.index() + 1, scope_info.index()); | |
890 builder() | |
891 ->LoadAccumulatorWithRegister(Register::function_closure()) | |
892 .StoreAccumulatorInRegister(closure) | |
893 .LoadLiteral(scope->GetScopeInfo(isolate())) | |
894 .StoreAccumulatorInRegister(scope_info) | |
895 .CallRuntime(Runtime::kNewScriptContext, closure, 2); | |
896 } else { | |
897 builder()->CallRuntime(Runtime::kNewFunctionContext, | |
898 Register::function_closure(), 1); | |
899 } | |
900 | |
901 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { | |
902 UNIMPLEMENTED(); | |
903 } | |
904 | |
905 // Copy parameters into context if necessary. | |
906 int num_parameters = scope->num_parameters(); | |
907 for (int i = 0; i < num_parameters; i++) { | |
908 Variable* variable = scope->parameter(i); | |
909 if (variable->IsContextSlot()) { | |
910 UNIMPLEMENTED(); | |
911 } | |
912 } | |
913 } | |
914 | |
915 | |
830 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { | 916 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { |
831 Token::Value op = binop->op(); | 917 Token::Value op = binop->op(); |
832 Expression* left = binop->left(); | 918 Expression* left = binop->left(); |
833 Expression* right = binop->right(); | 919 Expression* right = binop->right(); |
834 | 920 |
835 TemporaryRegisterScope temporary_register_scope(&builder_); | 921 TemporaryRegisterScope temporary_register_scope(builder()); |
836 Register temporary = temporary_register_scope.NewRegister(); | 922 Register temporary = temporary_register_scope.NewRegister(); |
837 | 923 |
838 Visit(left); | 924 Visit(left); |
839 builder()->StoreAccumulatorInRegister(temporary); | 925 builder()->StoreAccumulatorInRegister(temporary); |
840 Visit(right); | 926 Visit(right); |
841 builder()->BinaryOperation(op, temporary, language_mode_strength()); | 927 builder()->BinaryOperation(op, temporary, language_mode_strength()); |
842 } | 928 } |
843 | 929 |
844 | 930 |
845 LanguageMode BytecodeGenerator::language_mode() const { | 931 LanguageMode BytecodeGenerator::language_mode() const { |
846 return info()->language_mode(); | 932 return info()->language_mode(); |
847 } | 933 } |
848 | 934 |
849 | 935 |
850 Strength BytecodeGenerator::language_mode_strength() const { | 936 Strength BytecodeGenerator::language_mode_strength() const { |
851 return strength(language_mode()); | 937 return strength(language_mode()); |
852 } | 938 } |
853 | 939 |
854 | 940 |
855 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 941 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
856 return info()->feedback_vector()->GetIndex(slot); | 942 return info()->feedback_vector()->GetIndex(slot); |
857 } | 943 } |
858 | 944 |
859 | |
860 Register BytecodeGenerator::current_context() const { return current_context_; } | |
861 | |
862 } // namespace interpreter | 945 } // namespace interpreter |
863 } // namespace internal | 946 } // namespace internal |
864 } // namespace v8 | 947 } // namespace v8 |
OLD | NEW |