Index: src/compiler/ast-graph-builder.cc |
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc |
index a40977fcc84ab6cf0829511146470f055208e3ce..ae075ab43a70ce5ba0c1c0d99a1ca1841132fc2a 100644 |
--- a/src/compiler/ast-graph-builder.cc |
+++ b/src/compiler/ast-graph-builder.cc |
@@ -165,8 +165,6 @@ class AstGraphBuilder::ControlScope BASE_EMBEDDED { |
void ReturnValue(Node* return_value); |
void ThrowValue(Node* exception_value); |
- class DeferredCommands; |
- |
protected: |
enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW }; |
@@ -206,93 +204,6 @@ class AstGraphBuilder::ControlScope BASE_EMBEDDED { |
int stack_height_; |
}; |
-// Helper class for a try-finally control scope. It can record intercepted |
-// control-flow commands that cause entry into a finally-block, and re-apply |
-// them after again leaving that block. Special tokens are used to identify |
-// paths going through the finally-block to dispatch after leaving the block. |
-class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject { |
- public: |
- explicit DeferredCommands(AstGraphBuilder* owner) |
- : owner_(owner), |
- deferred_(owner->local_zone()), |
- return_token_(nullptr), |
- throw_token_(nullptr) {} |
- |
- // One recorded control-flow command. |
- struct Entry { |
- Command command; // The command type being applied on this path. |
- Statement* statement; // The target statement for the command or {nullptr}. |
- Node* token; // A token identifying this particular path. |
- }; |
- |
- // Records a control-flow command while entering the finally-block. This also |
- // generates a new dispatch token that identifies one particular path. |
- Node* RecordCommand(Command cmd, Statement* stmt, Node* value) { |
- Node* token = nullptr; |
- switch (cmd) { |
- case CMD_BREAK: |
- case CMD_CONTINUE: |
- token = NewPathToken(dispenser_.GetBreakContinueToken()); |
- break; |
- case CMD_THROW: |
- if (throw_token_) return throw_token_; |
- token = NewPathToken(TokenDispenserForFinally::kThrowToken); |
- throw_token_ = token; |
- break; |
- case CMD_RETURN: |
- if (return_token_) return return_token_; |
- token = NewPathToken(TokenDispenserForFinally::kReturnToken); |
- return_token_ = token; |
- break; |
- } |
- DCHECK_NOT_NULL(token); |
- deferred_.push_back({cmd, stmt, token}); |
- return token; |
- } |
- |
- // Returns the dispatch token to be used to identify the implicit fall-through |
- // path at the end of a try-block into the corresponding finally-block. |
- Node* GetFallThroughToken() { return NewPathTokenForImplicitFallThrough(); } |
- |
- // 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, Node* value) { |
- SwitchBuilder dispatch(owner_, static_cast<int>(deferred_.size())); |
- dispatch.BeginSwitch(); |
- for (size_t i = 0; i < deferred_.size(); ++i) { |
- Node* condition = NewPathDispatchCondition(token, deferred_[i].token); |
- dispatch.BeginLabel(static_cast<int>(i), condition); |
- dispatch.EndLabel(); |
- } |
- 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, value); |
- dispatch.EndCase(); |
- } |
- dispatch.EndSwitch(); |
- } |
- |
- protected: |
- Node* NewPathToken(int token_id) { |
- return owner_->jsgraph()->Constant(token_id); |
- } |
- Node* NewPathTokenForImplicitFallThrough() { |
- return NewPathToken(TokenDispenserForFinally::kFallThroughToken); |
- } |
- Node* NewPathDispatchCondition(Node* t1, Node* t2) { |
- return owner_->NewNode( |
- owner_->javascript()->StrictEqual(CompareOperationHint::kAny), t1, t2); |
- } |
- |
- private: |
- TokenDispenserForFinally dispenser_; |
- AstGraphBuilder* owner_; |
- ZoneVector<Entry> deferred_; |
- Node* return_token_; |
- Node* throw_token_; |
-}; |
- |
// Control scope implementation for a BreakableStatement. |
class AstGraphBuilder::ControlScopeForBreakable : public ControlScope { |
@@ -355,61 +266,6 @@ class AstGraphBuilder::ControlScopeForIteration : public ControlScope { |
}; |
-// Control scope implementation for a TryCatchStatement. |
-class AstGraphBuilder::ControlScopeForCatch : public ControlScope { |
- public: |
- ControlScopeForCatch(AstGraphBuilder* owner, TryCatchStatement* stmt, |
- TryCatchBuilder* control) |
- : ControlScope(owner), control_(control) { |
- builder()->try_nesting_level_++; // Increment nesting. |
- } |
- ~ControlScopeForCatch() { |
- builder()->try_nesting_level_--; // Decrement nesting. |
- } |
- |
- protected: |
- bool Execute(Command cmd, Statement* target, Node** value) override { |
- switch (cmd) { |
- case CMD_THROW: |
- control_->Throw(*value); |
- return true; |
- case CMD_BREAK: |
- case CMD_CONTINUE: |
- case CMD_RETURN: |
- break; |
- } |
- return false; |
- } |
- |
- private: |
- TryCatchBuilder* control_; |
-}; |
- |
- |
-// Control scope implementation for a TryFinallyStatement. |
-class AstGraphBuilder::ControlScopeForFinally : public ControlScope { |
- public: |
- ControlScopeForFinally(AstGraphBuilder* owner, TryFinallyStatement* stmt, |
- DeferredCommands* commands, TryFinallyBuilder* control) |
- : ControlScope(owner), commands_(commands), control_(control) { |
- builder()->try_nesting_level_++; // Increment nesting. |
- } |
- ~ControlScopeForFinally() { |
- builder()->try_nesting_level_--; // Decrement nesting. |
- } |
- |
- protected: |
- bool Execute(Command cmd, Statement* target, Node** value) override { |
- Node* token = commands_->RecordCommand(cmd, target, *value); |
- control_->LeaveTry(token, *value); |
- return true; |
- } |
- |
- private: |
- DeferredCommands* commands_; |
- TryFinallyBuilder* control_; |
-}; |
- |
AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, |
JSGraph* jsgraph, float invocation_frequency, |
LoopAssignmentAnalysis* loop) |
@@ -423,7 +279,6 @@ AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, |
globals_(0, local_zone), |
execution_control_(nullptr), |
execution_context_(nullptr), |
- try_nesting_level_(0), |
input_buffer_size_(0), |
input_buffer_(nullptr), |
exit_controls_(local_zone), |
@@ -1458,99 +1313,14 @@ void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { |
void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
- TryCatchBuilder try_control(this); |
- |
- // Evaluate the try-block inside a control scope. This simulates a handler |
- // that is intercepting 'throw' control commands. |
- try_control.BeginTry(); |
- { |
- ControlScopeForCatch scope(this, stmt, &try_control); |
- STATIC_ASSERT(TryBlockConstant::kElementCount == 1); |
- environment()->Push(current_context()); |
- Visit(stmt->try_block()); |
- environment()->Pop(); |
- } |
- try_control.EndTry(); |
- |
- // If requested, clear message object as we enter the catch block. |
- if (stmt->clear_pending_message()) { |
- Node* the_hole = jsgraph()->TheHoleConstant(); |
- NewNode(javascript()->StoreMessage(), the_hole); |
- } |
- |
- // Create a catch scope that binds the exception. |
- Node* exception = try_control.GetExceptionNode(); |
- Handle<String> name = stmt->variable()->name(); |
- Handle<ScopeInfo> scope_info = stmt->scope()->scope_info(); |
- const Operator* op = javascript()->CreateCatchContext(name, scope_info); |
- Node* context = NewNode(op, exception, GetFunctionClosureForContext()); |
- |
- // Evaluate the catch-block. |
- VisitInScope(stmt->catch_block(), stmt->scope(), context); |
- try_control.EndCatch(); |
+ // Exception handling is supported only by going through Ignition first. |
+ UNREACHABLE(); |
} |
void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
- TryFinallyBuilder try_control(this); |
- |
- // We keep a record of all paths that enter the finally-block to be able to |
- // dispatch to the correct continuation point after the statements in the |
- // finally-block have been evaluated. |
- // |
- // The try-finally construct can enter the finally-block in three ways: |
- // 1. By exiting the try-block normally, falling through at the end. |
- // 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 (local_zone()) ControlScope::DeferredCommands(this); |
- |
- // Evaluate the try-block inside a control scope. This simulates a handler |
- // that is intercepting all control commands. |
- try_control.BeginTry(); |
- { |
- ControlScopeForFinally scope(this, stmt, commands, &try_control); |
- STATIC_ASSERT(TryBlockConstant::kElementCount == 1); |
- environment()->Push(current_context()); |
- Visit(stmt->try_block()); |
- environment()->Pop(); |
- } |
- 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(); |
- Node* token = try_control.GetDispatchTokenNode(); |
- |
- // The result value, dispatch token and message is expected on the operand |
- // stack (this is in sync with FullCodeGenerator::EnterFinallyBlock). |
- Node* message = NewNode(javascript()->LoadMessage()); |
- environment()->Push(token); |
- environment()->Push(result); |
- environment()->Push(message); |
- |
- // Clear message object as we enter the finally block. |
- Node* the_hole = jsgraph()->TheHoleConstant(); |
- NewNode(javascript()->StoreMessage(), the_hole); |
- |
- // Evaluate the finally-block. |
- Visit(stmt->finally_block()); |
- try_control.EndFinally(); |
- |
- // The result value, dispatch token and message is restored from the operand |
- // stack (this is in sync with FullCodeGenerator::ExitFinallyBlock). |
- message = environment()->Pop(); |
- result = environment()->Pop(); |
- token = environment()->Pop(); |
- NewNode(javascript()->StoreMessage(), message); |
- |
- // Dynamic dispatch after the finally-block. |
- commands->ApplyDeferredCommands(token, result); |
+ // Exception handling is supported only by going through Ignition first. |
+ UNREACHABLE(); |
} |
@@ -4051,7 +3821,6 @@ Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count, |
if (!has_context && !has_frame_state && !has_control && !has_effect) { |
result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); |
} else { |
- bool inside_try_scope = try_nesting_level_ > 0; |
int input_count_with_deps = value_input_count; |
if (has_context) ++input_count_with_deps; |
if (has_frame_state) ++input_count_with_deps; |
@@ -4085,18 +3854,6 @@ Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count, |
if (result->op()->EffectOutputCount() > 0) { |
environment_->UpdateEffectDependency(result); |
} |
- // Add implicit exception continuation for throwing nodes. |
- if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) { |
- // Copy the environment for the success continuation. |
- Environment* success_env = environment()->CopyForConditional(); |
- const Operator* op = common()->IfException(); |
- Node* effect = environment()->GetEffectDependency(); |
- Node* on_exception = graph()->NewNode(op, effect, result); |
- environment_->UpdateControlDependency(on_exception); |
- environment_->UpdateEffectDependency(on_exception); |
- execution_control()->ThrowValue(on_exception); |
- set_environment(success_env); |
- } |
// Add implicit success continuation for throwing nodes. |
if (!result->op()->HasProperty(Operator::kNoThrow)) { |
const Operator* op = common()->IfSuccess(); |