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/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
9 #include "src/interpreter/bytecode-register-allocator.h" | 9 #include "src/interpreter/bytecode-register-allocator.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/parsing/parser.h" | 12 #include "src/parsing/parser.h" |
13 #include "src/parsing/token.h" | 13 #include "src/parsing/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 | 20 // Scoped class tracking context objects created by the visitor. Represents |
21 // mutations of the context chain within the function body, allowing pushing and | 21 // mutations of the context chain within the function body, allowing pushing and |
22 // popping of the current {context_register} during visitation. | 22 // popping of the current {context_register} during visitation. |
23 class BytecodeGenerator::ContextScope BASE_EMBEDDED { | 23 class BytecodeGenerator::ContextScope BASE_EMBEDDED { |
24 public: | 24 public: |
25 ContextScope(BytecodeGenerator* generator, Scope* scope, | 25 ContextScope(BytecodeGenerator* generator, Scope* scope, |
26 bool should_pop_context = true) | 26 bool should_pop_context = true) |
27 : generator_(generator), | 27 : generator_(generator), |
28 scope_(scope), | 28 scope_(scope), |
29 outer_(generator_->execution_context()), | 29 outer_(generator_->execution_context()), |
30 register_(generator_->NextContextRegister()), | 30 register_(Register::current_context()), |
31 depth_(0), | 31 depth_(0), |
32 should_pop_context_(should_pop_context) { | 32 should_pop_context_(should_pop_context) { |
33 if (outer_) { | 33 if (outer_) { |
34 depth_ = outer_->depth_ + 1; | 34 depth_ = outer_->depth_ + 1; |
35 generator_->builder()->PushContext(register_); | 35 |
| 36 // Push the outer context into a new context register. |
| 37 Register outer_context_reg(builder()->first_context_register().index() + |
| 38 outer_->depth_); |
| 39 outer_->set_register(outer_context_reg); |
| 40 generator_->builder()->PushContext(outer_context_reg); |
36 } | 41 } |
37 generator_->set_execution_context(this); | 42 generator_->set_execution_context(this); |
38 } | 43 } |
39 | 44 |
40 ~ContextScope() { | 45 ~ContextScope() { |
41 if (outer_ && should_pop_context_) { | 46 if (outer_ && should_pop_context_) { |
| 47 DCHECK_EQ(register_.index(), Register::current_context().index()); |
42 generator_->builder()->PopContext(outer_->reg()); | 48 generator_->builder()->PopContext(outer_->reg()); |
| 49 outer_->set_register(register_); |
43 } | 50 } |
44 generator_->set_execution_context(outer_); | 51 generator_->set_execution_context(outer_); |
45 } | 52 } |
46 | 53 |
47 // Returns the depth of the given |scope| for the current execution context. | 54 // Returns the depth of the given |scope| for the current execution context. |
48 int ContextChainDepth(Scope* scope) { | 55 int ContextChainDepth(Scope* scope) { |
49 return scope_->ContextChainLength(scope); | 56 return scope_->ContextChainLength(scope); |
50 } | 57 } |
51 | 58 |
52 // Returns the execution context at |depth| in the current context chain if it | 59 // Returns the execution context at |depth| in the current context chain if it |
53 // is a function local execution context, otherwise returns nullptr. | 60 // is a function local execution context, otherwise returns nullptr. |
54 ContextScope* Previous(int depth) { | 61 ContextScope* Previous(int depth) { |
55 if (depth > depth_) { | 62 if (depth > depth_) { |
56 return nullptr; | 63 return nullptr; |
57 } | 64 } |
58 | 65 |
59 ContextScope* previous = this; | 66 ContextScope* previous = this; |
60 for (int i = depth; i > 0; --i) { | 67 for (int i = depth; i > 0; --i) { |
61 previous = previous->outer_; | 68 previous = previous->outer_; |
62 } | 69 } |
63 return previous; | 70 return previous; |
64 } | 71 } |
65 | 72 |
66 Scope* scope() const { return scope_; } | 73 Scope* scope() const { return scope_; } |
67 Register reg() const { return register_; } | 74 Register reg() const { return register_; } |
68 | 75 |
69 private: | 76 private: |
| 77 const BytecodeArrayBuilder* builder() const { return generator_->builder(); } |
| 78 |
| 79 void set_register(Register reg) { register_ = reg; } |
| 80 |
70 BytecodeGenerator* generator_; | 81 BytecodeGenerator* generator_; |
71 Scope* scope_; | 82 Scope* scope_; |
72 ContextScope* outer_; | 83 ContextScope* outer_; |
73 Register register_; | 84 Register register_; |
74 int depth_; | 85 int depth_; |
75 bool should_pop_context_; | 86 bool should_pop_context_; |
76 }; | 87 }; |
77 | 88 |
78 | 89 |
79 // Scoped class for tracking control statements entered by the | 90 // Scoped class for tracking control statements entered by the |
(...skipping 1779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1859 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) { | 1870 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) { |
1860 RegisterAllocationScope inner_register_scope(this); | 1871 RegisterAllocationScope inner_register_scope(this); |
1861 register_allocator()->PrepareForConsecutiveAllocations(2); | 1872 register_allocator()->PrepareForConsecutiveAllocations(2); |
1862 Register context = register_allocator()->NextConsecutiveRegister(); | 1873 Register context = register_allocator()->NextConsecutiveRegister(); |
1863 Register name = register_allocator()->NextConsecutiveRegister(); | 1874 Register name = register_allocator()->NextConsecutiveRegister(); |
1864 | 1875 |
1865 // Call LoadLookupSlot to get the callee and receiver. | 1876 // Call LoadLookupSlot to get the callee and receiver. |
1866 DCHECK(Register::AreContiguous(callee, receiver)); | 1877 DCHECK(Register::AreContiguous(callee, receiver)); |
1867 Variable* variable = callee_expr->AsVariableProxy()->var(); | 1878 Variable* variable = callee_expr->AsVariableProxy()->var(); |
1868 builder() | 1879 builder() |
1869 ->MoveRegister(execution_context()->reg(), context) | 1880 ->MoveRegister(Register::current_context(), context) |
1870 .LoadLiteral(variable->name()) | 1881 .LoadLiteral(variable->name()) |
1871 .StoreAccumulatorInRegister(name) | 1882 .StoreAccumulatorInRegister(name) |
1872 .CallRuntimeForPair(Runtime::kLoadLookupSlot, context, 2, callee); | 1883 .CallRuntimeForPair(Runtime::kLoadLookupSlot, context, 2, callee); |
1873 break; | 1884 break; |
1874 } | 1885 } |
1875 // Fall through. | 1886 // Fall through. |
1876 DCHECK_EQ(call_type, Call::POSSIBLY_EVAL_CALL); | 1887 DCHECK_EQ(call_type, Call::POSSIBLY_EVAL_CALL); |
1877 } | 1888 } |
1878 case Call::OTHER_CALL: { | 1889 case Call::OTHER_CALL: { |
1879 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 1890 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
(...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2473 } | 2484 } |
2474 | 2485 |
2475 | 2486 |
2476 void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) { | 2487 void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) { |
2477 ContextScope context_scope(this, scope); | 2488 ContextScope context_scope(this, scope); |
2478 DCHECK(scope->declarations()->is_empty()); | 2489 DCHECK(scope->declarations()->is_empty()); |
2479 Visit(stmt); | 2490 Visit(stmt); |
2480 } | 2491 } |
2481 | 2492 |
2482 | 2493 |
2483 Register BytecodeGenerator::NextContextRegister() const { | |
2484 if (execution_context() == nullptr) { | |
2485 // Return the incoming function context for the outermost execution context. | |
2486 return Register::function_context(); | |
2487 } | |
2488 Register previous = execution_context()->reg(); | |
2489 if (previous == Register::function_context()) { | |
2490 // If the previous context was the incoming function context, then the next | |
2491 // context register is the first local context register. | |
2492 return builder_.first_context_register(); | |
2493 } else { | |
2494 // Otherwise use the next local context register. | |
2495 DCHECK_LT(previous.index(), builder_.last_context_register().index()); | |
2496 return Register(previous.index() + 1); | |
2497 } | |
2498 } | |
2499 | |
2500 | |
2501 LanguageMode BytecodeGenerator::language_mode() const { | 2494 LanguageMode BytecodeGenerator::language_mode() const { |
2502 return info()->language_mode(); | 2495 return info()->language_mode(); |
2503 } | 2496 } |
2504 | 2497 |
2505 | 2498 |
2506 Strength BytecodeGenerator::language_mode_strength() const { | 2499 Strength BytecodeGenerator::language_mode_strength() const { |
2507 return strength(language_mode()); | 2500 return strength(language_mode()); |
2508 } | 2501 } |
2509 | 2502 |
2510 | 2503 |
2511 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2504 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
2512 return info()->feedback_vector()->GetIndex(slot); | 2505 return info()->feedback_vector()->GetIndex(slot); |
2513 } | 2506 } |
2514 | 2507 |
2515 } // namespace interpreter | 2508 } // namespace interpreter |
2516 } // namespace internal | 2509 } // namespace internal |
2517 } // namespace v8 | 2510 } // namespace v8 |
OLD | NEW |