Index: src/interpreter/bytecode-generator.cc |
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc |
index 6e94b5f0791182803076d8dbb550f1dfec075652..5bbc3819ad613b5b38e4081eefc05449b5780d78 100644 |
--- a/src/interpreter/bytecode-generator.cc |
+++ b/src/interpreter/bytecode-generator.cc |
@@ -81,7 +81,8 @@ class BytecodeGenerator::ContextScope BASE_EMBEDDED { |
class BytecodeGenerator::ControlScope BASE_EMBEDDED { |
public: |
explicit ControlScope(BytecodeGenerator* generator) |
- : generator_(generator), outer_(generator->execution_control()) { |
+ : generator_(generator), outer_(generator->execution_control()), |
+ context_(generator->execution_context()) { |
generator_->set_execution_control(this); |
} |
virtual ~ControlScope() { generator_->set_execution_control(outer()); } |
@@ -92,14 +93,17 @@ class BytecodeGenerator::ControlScope BASE_EMBEDDED { |
protected: |
enum Command { CMD_BREAK, CMD_CONTINUE }; |
void PerformCommand(Command command, Statement* statement); |
- virtual bool Execute(Command command, Statement* statement) = 0; |
+ virtual bool ShouldExecute(Command command, Statement* statement) = 0; |
+ virtual void Execute(Command command) = 0; |
BytecodeGenerator* generator() const { return generator_; } |
ControlScope* outer() const { return outer_; } |
+ ContextScope* context() const { return context_; } |
private: |
BytecodeGenerator* generator_; |
ControlScope* outer_; |
+ ContextScope* context_; |
DISALLOW_COPY_AND_ASSIGN(ControlScope); |
}; |
@@ -117,16 +121,20 @@ class BytecodeGenerator::ControlScopeForBreakable final |
control_builder_(control_builder) {} |
protected: |
- virtual bool Execute(Command command, Statement* statement) { |
+ bool ShouldExecute(Command command, Statement* statement) override { |
if (statement != statement_) return false; |
+ return command == CMD_BREAK; |
+ } |
+ |
+ void Execute(Command command) override { |
switch (command) { |
case CMD_BREAK: |
control_builder_->Break(); |
- return true; |
+ break; |
case CMD_CONTINUE: |
+ UNREACHABLE(); |
break; |
} |
- return false; |
} |
private: |
@@ -148,17 +156,20 @@ class BytecodeGenerator::ControlScopeForIteration final |
loop_builder_(loop_builder) {} |
protected: |
- virtual bool Execute(Command command, Statement* statement) { |
+ bool ShouldExecute(Command command, Statement* statement) override { |
if (statement != statement_) return false; |
+ return command == CMD_BREAK || command == CMD_CONTINUE; |
+ } |
+ |
+ void Execute(Command command) override { |
switch (command) { |
case CMD_BREAK: |
loop_builder_->Break(); |
- return true; |
+ break; |
case CMD_CONTINUE: |
loop_builder_->Continue(); |
- return true; |
+ break; |
} |
- return false; |
} |
private: |
@@ -171,7 +182,14 @@ void BytecodeGenerator::ControlScope::PerformCommand(Command command, |
Statement* statement) { |
ControlScope* current = this; |
do { |
- if (current->Execute(command, statement)) return; |
+ if (current->ShouldExecute(command, statement)) { |
Michael Starzinger
2016/01/21 13:25:20
As discussed offline: How would you feel about goi
rmcilroy
2016/01/22 11:46:08
Done.
|
+ if (current->context() != this->context()) { |
+ // Pop context to the expected depth. |
+ generator()->builder()->PopContext(current->context()->reg()); |
+ } |
+ current->Execute(command); |
+ return; |
+ } |
current = current->outer(); |
} while (current != nullptr); |
UNREACHABLE(); |