Index: src/compiler/ast-graph-builder.cc |
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc |
index b6c6e0fb3f5bc1a0f396d178d09931f978332bda..f4b8676730d0b7d80b1101bdf201551bf64ba5cd 100644 |
--- a/src/compiler/ast-graph-builder.cc |
+++ b/src/compiler/ast-graph-builder.cc |
@@ -212,7 +212,6 @@ class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject { |
struct Entry { |
Command command; // The command type being applied on this path. |
Statement* statement; // The target statement for the command or {NULL}. |
- Node* value; // The passed value node for the command or {NULL}. |
Node* token; // A token identifying this particular path. |
}; |
@@ -220,7 +219,7 @@ class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject { |
// generates a new dispatch token that identifies one particular path. |
Node* RecordCommand(Command cmd, Statement* stmt, Node* value) { |
Node* token = NewPathTokenForDeferredCommand(); |
- deferred_.push_back({cmd, stmt, value, token}); |
+ deferred_.push_back({cmd, stmt, token}); |
return token; |
} |
@@ -230,7 +229,7 @@ class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject { |
// Applies all recorded control-flow commands after the finally-block again. |
// This generates a dynamic dispatch on the token from the entry point. |
- void ApplyDeferredCommands(Node* token) { |
+ void ApplyDeferredCommands(Node* token, Node* value) { |
SwitchBuilder dispatch(owner_, static_cast<int>(deferred_.size())); |
dispatch.BeginSwitch(); |
for (size_t i = 0; i < deferred_.size(); ++i) { |
@@ -241,7 +240,7 @@ class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject { |
for (size_t i = 0; i < deferred_.size(); ++i) { |
dispatch.BeginCase(static_cast<int>(i)); |
owner_->execution_control()->PerformCommand( |
- deferred_[i].command, deferred_[i].statement, deferred_[i].value); |
+ deferred_[i].command, deferred_[i].statement, value); |
dispatch.EndCase(); |
} |
dispatch.EndSwitch(); |
@@ -369,7 +368,7 @@ class AstGraphBuilder::ControlScopeForFinally : public ControlScope { |
protected: |
virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { |
Node* token = commands_->RecordCommand(cmd, target, value); |
- control_->LeaveTry(token); |
+ control_->LeaveTry(token, value); |
return true; |
} |
@@ -719,12 +718,12 @@ void AstGraphBuilder::ControlScope::PerformCommand(Command command, |
void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) { |
- PerformCommand(CMD_BREAK, stmt, nullptr); |
+ PerformCommand(CMD_BREAK, stmt, builder()->jsgraph()->TheHoleConstant()); |
} |
void AstGraphBuilder::ControlScope::ContinueTo(BreakableStatement* stmt) { |
- PerformCommand(CMD_CONTINUE, stmt, nullptr); |
+ PerformCommand(CMD_CONTINUE, stmt, builder()->jsgraph()->TheHoleConstant()); |
} |
@@ -1262,6 +1261,7 @@ void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
// 2. By exiting the try-block with a function-local control flow transfer |
// (i.e. through break/continue/return statements). |
// 3. By exiting the try-block with a thrown exception. |
+ Node* fallthrough_result = jsgraph()->TheHoleConstant(); |
ControlScope::DeferredCommands* commands = |
new (zone()) ControlScope::DeferredCommands(this); |
@@ -1272,15 +1272,32 @@ void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
ControlScopeForFinally scope(this, commands, &try_control); |
Visit(stmt->try_block()); |
} |
- try_control.EndTry(commands->GetFallThroughToken()); |
+ try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result); |
+ |
+ // The result value semantics depend on how the block was entered: |
+ // - ReturnStatement: It represents the return value being returned. |
+ // - ThrowStatement: It represents the exception being thrown. |
+ // - BreakStatement/ContinueStatement: Filled with the hole. |
+ // - Falling through into finally-block: Filled with the hole. |
+ Node* result = try_control.GetResultValueNode(); |
+ |
+ // TODO(mstarzinger): See FullCodeGenerator::EnterFinallyBlock. |
+ environment()->Push(jsgraph()->SmiConstant(Code::kHeaderSize)); |
+ environment()->Push(result); |
+ environment()->Push(jsgraph()->TheHoleConstant()); // pending_message_obj |
+ environment()->Push(jsgraph()->SmiConstant(0)); // has_pending_message |
+ environment()->Push(jsgraph()->TheHoleConstant()); // pending_message_script |
// Evaluate the finally-block. |
Visit(stmt->finally_block()); |
try_control.EndFinally(); |
+ // TODO(mstarzinger): See FullCodeGenerator::ExitFinallyBlock. |
+ environment()->Drop(5); |
+ |
// Dynamic dispatch after the finally-block. |
Node* token = try_control.GetDispatchTokenNode(); |
- commands->ApplyDeferredCommands(token); |
+ commands->ApplyDeferredCommands(token, result); |
// TODO(mstarzinger): Remove bailout once everything works. |
if (!FLAG_turbo_exceptions) SetStackOverflow(); |
@@ -3022,7 +3039,7 @@ Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count, |
if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) { |
Node* on_exception = graph()->NewNode(common()->IfException(), result); |
environment_->UpdateControlDependency(on_exception); |
- execution_control()->ThrowValue(jsgraph()->UndefinedConstant()); |
+ execution_control()->ThrowValue(result); |
} |
// Add implicit success continuation for throwing nodes. |
if (!result->op()->HasProperty(Operator::kNoThrow)) { |