| Index: src/compiler/bytecode-graph-builder.cc
 | 
| diff --git a/src/compiler/bytecode-graph-builder.cc b/src/compiler/bytecode-graph-builder.cc
 | 
| index dec8194611fdd1b0c4534207928544575764d8e1..dbf7756bceb3447430729bc9717133016cca6297 100644
 | 
| --- a/src/compiler/bytecode-graph-builder.cc
 | 
| +++ b/src/compiler/bytecode-graph-builder.cc
 | 
| @@ -375,7 +375,6 @@ bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate(
 | 
|                                  1, output_poke_start, output_poke_end);
 | 
|  }
 | 
|  
 | 
| -
 | 
|  BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone,
 | 
|                                             CompilationInfo* compilation_info,
 | 
|                                             JSGraph* jsgraph)
 | 
| @@ -383,6 +382,8 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone,
 | 
|        info_(compilation_info),
 | 
|        jsgraph_(jsgraph),
 | 
|        bytecode_array_(handle(info()->shared_info()->bytecode_array())),
 | 
| +      exception_handler_table_(
 | 
| +          handle(HandlerTable::cast(bytecode_array()->handler_table()))),
 | 
|        frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
 | 
|            FrameStateType::kInterpretedFunction,
 | 
|            bytecode_array()->parameter_count(),
 | 
| @@ -390,11 +391,12 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone,
 | 
|            CALL_MAINTAINS_NATIVE_CONTEXT)),
 | 
|        merge_environments_(local_zone),
 | 
|        loop_header_environments_(local_zone),
 | 
| +      exception_handlers_(local_zone),
 | 
| +      current_exception_handler_(0),
 | 
|        input_buffer_size_(0),
 | 
|        input_buffer_(nullptr),
 | 
|        exit_controls_(local_zone) {}
 | 
|  
 | 
| -
 | 
|  Node* BytecodeGraphBuilder::GetNewTarget() {
 | 
|    if (!new_target_.is_set()) {
 | 
|      int params = bytecode_array()->parameter_count();
 | 
| @@ -527,6 +529,7 @@ void BytecodeGraphBuilder::VisitBytecodes() {
 | 
|    while (!iterator.done()) {
 | 
|      int current_offset = iterator.current_offset();
 | 
|      if (analysis.is_reachable(current_offset)) {
 | 
| +      EnterAndExitExceptionHandlers(current_offset);
 | 
|        MergeEnvironmentsOfForwardBranches(current_offset);
 | 
|        BuildLoopHeaderForBackwardBranches(current_offset);
 | 
|  
 | 
| @@ -543,6 +546,7 @@ void BytecodeGraphBuilder::VisitBytecodes() {
 | 
|    }
 | 
|    set_branch_analysis(nullptr);
 | 
|    set_bytecode_iterator(nullptr);
 | 
| +  DCHECK(exception_handlers_.empty());
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -1949,6 +1953,27 @@ Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) {
 | 
|    return input_buffer_;
 | 
|  }
 | 
|  
 | 
| +void BytecodeGraphBuilder::EnterAndExitExceptionHandlers(int current_offset) {
 | 
| +  Handle<HandlerTable> table = exception_handler_table();
 | 
| +  int num_entries = table->NumberOfRangeEntries();
 | 
| +
 | 
| +  // Potentially exit exception handlers.
 | 
| +  while (!exception_handlers_.empty()) {
 | 
| +    int current_end = exception_handlers_.top().end_offset_;
 | 
| +    if (current_offset < current_end) break;  // Still covered by range.
 | 
| +    exception_handlers_.pop();
 | 
| +  }
 | 
| +
 | 
| +  // Potentially enter exception handlers.
 | 
| +  while (current_exception_handler_ < num_entries) {
 | 
| +    int next_start = table->GetRangeStart(current_exception_handler_);
 | 
| +    if (current_offset < next_start) break;  // Not yet covered by range.
 | 
| +    int next_end = table->GetRangeEnd(current_exception_handler_);
 | 
| +    int next_handler = table->GetRangeHandler(current_exception_handler_);
 | 
| +    exception_handlers_.push({next_start, next_end, next_handler});
 | 
| +    current_exception_handler_++;
 | 
| +  }
 | 
| +}
 | 
|  
 | 
|  void BytecodeGraphBuilder::PrepareEntryFrameState(Node* node) {
 | 
|    DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
 | 
| @@ -1976,6 +2001,7 @@ Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count,
 | 
|    if (!has_context && frame_state_count == 0 && !has_control && !has_effect) {
 | 
|      result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
 | 
|    } else {
 | 
| +    bool inside_handler = !exception_handlers_.empty();
 | 
|      int input_count_with_deps = value_input_count;
 | 
|      if (has_context) ++input_count_with_deps;
 | 
|      input_count_with_deps += frame_state_count;
 | 
| @@ -2009,11 +2035,32 @@ Node* BytecodeGraphBuilder::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_handler) {
 | 
| +        int throw_offset = bytecode_iterator()->current_offset();
 | 
| +        int handler_offset = exception_handlers_.top().handler_offset_;
 | 
| +        // TODO(mstarzinger): Thread through correct prediction!
 | 
| +        IfExceptionHint hint = IfExceptionHint::kLocallyCaught;
 | 
| +        // TODO(mstarzinger): For now we mutate the branch analysis result and
 | 
| +        // add the artificial control flow from throw-site to handler-entry.
 | 
| +        // This can be simplified by pushing environment forward along the
 | 
| +        // direction of the data-flow.
 | 
| +        branch_analysis_->AddExceptionalBranch(throw_offset, handler_offset);
 | 
| +        Environment* success_env = environment()->CopyForConditional();
 | 
| +        const Operator* op = common()->IfException(hint);
 | 
| +        Node* effect = environment()->GetEffectDependency();
 | 
| +        Node* on_exception = graph()->NewNode(op, effect, result);
 | 
| +        environment()->UpdateControlDependency(on_exception);
 | 
| +        environment()->UpdateEffectDependency(on_exception);
 | 
| +        environment()->BindAccumulator(on_exception);
 | 
| +        BuildJump(throw_offset, handler_offset);
 | 
| +        set_environment(success_env);
 | 
| +      }
 | 
|        // Add implicit success continuation for throwing nodes.
 | 
|        if (!result->op()->HasProperty(Operator::kNoThrow)) {
 | 
|          const Operator* if_success = common()->IfSuccess();
 | 
|          Node* on_success = graph()->NewNode(if_success, result);
 | 
| -        environment_->UpdateControlDependency(on_success);
 | 
| +        environment()->UpdateControlDependency(on_success);
 | 
|        }
 | 
|      }
 | 
|    }
 | 
| 
 |