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