Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE

This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.

FPIIM-449

Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index 4bdafbf..e00e5ab 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -11,8 +11,10 @@
 #include "src/frames-inl.h"
 #include "src/full-codegen/full-codegen.h"
 #include "src/global-handles.h"
+#include "src/interpreter/interpreter.h"
 #include "src/macro-assembler.h"
 #include "src/profiler/cpu-profiler.h"
+#include "src/tracing/trace-event.h"
 #include "src/v8.h"
 
 
@@ -35,7 +37,6 @@
 
 DeoptimizerData::DeoptimizerData(MemoryAllocator* allocator)
     : allocator_(allocator),
-      deoptimized_frame_info_(NULL),
       current_(NULL) {
   for (int i = 0; i < Deoptimizer::kBailoutTypesWithCodeEntry; ++i) {
     deopt_entry_code_entries_[i] = -1;
@@ -52,13 +53,6 @@
 }
 
 
-void DeoptimizerData::Iterate(ObjectVisitor* v) {
-  if (deoptimized_frame_info_ != NULL) {
-    deoptimized_frame_info_->Iterate(v);
-  }
-}
-
-
 Code* Deoptimizer::FindDeoptimizingCode(Address addr) {
   if (function_->IsHeapObject()) {
     // Search all deoptimizing code in the native context of the function.
@@ -140,73 +134,27 @@
     int jsframe_index,
     Isolate* isolate) {
   CHECK(frame->is_optimized());
-  CHECK(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL);
 
-  // Get the function and code from the frame.
-  JSFunction* function = frame->function();
-  Code* code = frame->LookupCode();
+  TranslatedState translated_values(frame);
+  translated_values.Prepare(false, frame->fp());
 
-  // Locate the deoptimization point in the code. As we are at a call the
-  // return address must be at a place in the code with deoptimization support.
-  SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc());
-  int deoptimization_index = safepoint_entry.deoptimization_index();
-  CHECK_NE(deoptimization_index, Safepoint::kNoDeoptimizationIndex);
+  TranslatedState::iterator frame_it = translated_values.end();
+  int counter = jsframe_index;
+  for (auto it = translated_values.begin(); it != translated_values.end();
+       it++) {
+    if (it->kind() == TranslatedFrame::kFunction ||
+        it->kind() == TranslatedFrame::kInterpretedFunction) {
+      if (counter == 0) {
+        frame_it = it;
+        break;
+      }
+      counter--;
+    }
+  }
+  CHECK(frame_it != translated_values.end());
 
-  // Always use the actual stack slots when calculating the fp to sp
-  // delta adding two for the function and context.
-  unsigned stack_slots = code->stack_slots();
-  unsigned arguments_stack_height =
-      Deoptimizer::ComputeOutgoingArgumentSize(code, deoptimization_index);
-  unsigned fp_to_sp_delta = (stack_slots * kPointerSize) +
-                            StandardFrameConstants::kFixedFrameSizeFromFp +
-                            arguments_stack_height;
-
-  Deoptimizer* deoptimizer = new Deoptimizer(isolate,
-                                             function,
-                                             Deoptimizer::DEBUGGER,
-                                             deoptimization_index,
-                                             frame->pc(),
-                                             fp_to_sp_delta,
-                                             code);
-  Address tos = frame->fp() - fp_to_sp_delta;
-  deoptimizer->FillInputFrame(tos, frame);
-
-  // Calculate the output frames.
-  Deoptimizer::ComputeOutputFrames(deoptimizer);
-
-  // Create the GC safe output frame information and register it for GC
-  // handling.
-  CHECK_LT(jsframe_index, deoptimizer->jsframe_count());
-
-  // Convert JS frame index into frame index.
-  int frame_index = deoptimizer->ConvertJSFrameIndexToFrameIndex(jsframe_index);
-
-  bool has_arguments_adaptor =
-      frame_index > 0 &&
-      deoptimizer->output_[frame_index - 1]->GetFrameType() ==
-      StackFrame::ARGUMENTS_ADAPTOR;
-
-  int construct_offset = has_arguments_adaptor ? 2 : 1;
-  bool has_construct_stub =
-      frame_index >= construct_offset &&
-      deoptimizer->output_[frame_index - construct_offset]->GetFrameType() ==
-      StackFrame::CONSTRUCT;
-
-  DeoptimizedFrameInfo* info = new DeoptimizedFrameInfo(deoptimizer,
-                                                        frame_index,
-                                                        has_arguments_adaptor,
-                                                        has_construct_stub);
-  isolate->deoptimizer_data()->deoptimized_frame_info_ = info;
-
-  // Done with the GC-unsafe frame descriptions. This re-enables allocation.
-  deoptimizer->DeleteFrameDescriptions();
-
-  // Allocate a heap number for the doubles belonging to this frame.
-  deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame(
-      frame_index, info->parameters_count(), info->expression_count(), info);
-
-  // Finished using the deoptimizer instance.
-  delete deoptimizer;
+  DeoptimizedFrameInfo* info =
+      new DeoptimizedFrameInfo(&translated_values, frame_it, isolate);
 
   return info;
 }
@@ -214,9 +162,7 @@
 
 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
                                                  Isolate* isolate) {
-  CHECK_EQ(isolate->deoptimizer_data()->deoptimized_frame_info_, info);
   delete info;
-  isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL;
 }
 
 
@@ -394,8 +340,8 @@
     element = next;
   }
 
-  // TODO(titzer): we need a handle scope only because of the macro assembler,
-  // which is only used in EnsureCodeForDeoptimizationEntry.
+  // We need a handle scope only because of the macro assembler,
+  // which is used in code patching in EnsureCodeForDeoptimizationEntry.
   HandleScope scope(isolate);
 
   // Now patch all the codes for deoptimization.
@@ -426,6 +372,8 @@
 
 
 void Deoptimizer::DeoptimizeAll(Isolate* isolate) {
+  TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
+  TRACE_EVENT0("v8", "V8.DeoptimizeCode");
   if (FLAG_trace_deopt) {
     CodeTracer::Scope scope(isolate->GetCodeTracer());
     PrintF(scope.file(), "[deoptimize all code in all contexts]\n");
@@ -443,6 +391,8 @@
 
 
 void Deoptimizer::DeoptimizeMarkedCode(Isolate* isolate) {
+  TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
+  TRACE_EVENT0("v8", "V8.DeoptimizeCode");
   if (FLAG_trace_deopt) {
     CodeTracer::Scope scope(isolate->GetCodeTracer());
     PrintF(scope.file(), "[deoptimize marked code in all contexts]\n");
@@ -470,6 +420,8 @@
 
 
 void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
+  TimerEventScope<TimerEventDeoptimizeCode> timer(function->GetIsolate());
+  TRACE_EVENT0("v8", "V8.DeoptimizeCode");
   Code* code = function->code();
   if (code->kind() == Code::OPTIMIZED_FUNCTION) {
     // Mark the code for deoptimization and unlink any functions that also
@@ -513,7 +465,6 @@
   return NULL;
 }
 
-
 Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction* function,
                          BailoutType type, unsigned bailout_id, Address from,
                          int fp_to_sp_delta, Code* optimized_code)
@@ -524,11 +475,19 @@
       from_(from),
       fp_to_sp_delta_(fp_to_sp_delta),
       has_alignment_padding_(0),
+      deoptimizing_throw_(false),
+      catch_handler_data_(-1),
+      catch_handler_pc_offset_(-1),
       input_(nullptr),
       output_count_(0),
       jsframe_count_(0),
       output_(nullptr),
       trace_scope_(nullptr) {
+  if (isolate->deoptimizer_lazy_throw()) {
+    isolate->set_deoptimizer_lazy_throw(false);
+    deoptimizing_throw_ = true;
+  }
+
   // For COMPILED_STUBs called from builtins, the function pointer is a SMI
   // indicating an internal frame.
   if (function->IsSmi()) {
@@ -567,7 +526,11 @@
     PROFILE(isolate_, CodeDeoptEvent(compiled_code_, from_, fp_to_sp_delta_));
   }
   unsigned size = ComputeInputFrameSize();
-  input_ = new(size) FrameDescription(size, function);
+  int parameter_count =
+      function == nullptr
+          ? 0
+          : (function->shared()->internal_formal_parameter_count() + 1);
+  input_ = new (size) FrameDescription(size, parameter_count);
   input_->SetFrameType(frame_type);
 }
 
@@ -702,6 +665,41 @@
   return length;
 }
 
+namespace {
+
+int LookupCatchHandler(TranslatedFrame* translated_frame, int* data_out) {
+  switch (translated_frame->kind()) {
+    case TranslatedFrame::kFunction: {
+      BailoutId node_id = translated_frame->node_id();
+      JSFunction* function =
+          JSFunction::cast(translated_frame->begin()->GetRawValue());
+      Code* non_optimized_code = function->shared()->code();
+      FixedArray* raw_data = non_optimized_code->deoptimization_data();
+      DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
+      unsigned pc_and_state =
+          Deoptimizer::GetOutputInfo(data, node_id, function->shared());
+      unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
+      HandlerTable* table =
+          HandlerTable::cast(non_optimized_code->handler_table());
+      HandlerTable::CatchPrediction prediction;
+      return table->LookupRange(pc_offset, data_out, &prediction);
+    }
+    case TranslatedFrame::kInterpretedFunction: {
+      int bytecode_offset = translated_frame->node_id().ToInt();
+      JSFunction* function =
+          JSFunction::cast(translated_frame->begin()->GetRawValue());
+      BytecodeArray* bytecode = function->shared()->bytecode_array();
+      HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
+      HandlerTable::CatchPrediction prediction;
+      return table->LookupRange(bytecode_offset, data_out, &prediction);
+    }
+    default:
+      break;
+  }
+  return -1;
+}
+
+}  // namespace
 
 // We rely on this function not causing a GC.  It is called from generated code
 // without having a real stack frame in place.
@@ -742,6 +740,22 @@
 
   // Do the input frame to output frame(s) translation.
   size_t count = translated_state_.frames().size();
+  // If we are supposed to go to the catch handler, find the catching frame
+  // for the catch and make sure we only deoptimize upto that frame.
+  if (deoptimizing_throw_) {
+    size_t catch_handler_frame_index = count;
+    for (size_t i = count; i-- > 0;) {
+      catch_handler_pc_offset_ = LookupCatchHandler(
+          &(translated_state_.frames()[i]), &catch_handler_data_);
+      if (catch_handler_pc_offset_ >= 0) {
+        catch_handler_frame_index = i;
+        break;
+      }
+    }
+    CHECK_LT(catch_handler_frame_index, count);
+    count = catch_handler_frame_index + 1;
+  }
+
   DCHECK(output_ == NULL);
   output_ = new FrameDescription*[count];
   for (size_t i = 0; i < count; ++i) {
@@ -760,11 +774,12 @@
     int frame_index = static_cast<int>(i);
     switch (translated_state_.frames()[i].kind()) {
       case TranslatedFrame::kFunction:
-        DoComputeJSFrame(frame_index);
+        DoComputeJSFrame(frame_index, deoptimizing_throw_ && i == count - 1);
         jsframe_count_++;
         break;
       case TranslatedFrame::kInterpretedFunction:
-        DoComputeInterpretedFrame(frame_index);
+        DoComputeInterpretedFrame(frame_index,
+                                  deoptimizing_throw_ && i == count - 1);
         jsframe_count_++;
         break;
       case TranslatedFrame::kArgumentsAdaptor:
@@ -809,40 +824,53 @@
   }
 }
 
-
-void Deoptimizer::DoComputeJSFrame(int frame_index) {
+void Deoptimizer::DoComputeJSFrame(int frame_index, bool goto_catch_handler) {
   TranslatedFrame* translated_frame =
       &(translated_state_.frames()[frame_index]);
+  SharedFunctionInfo* shared = translated_frame->raw_shared_info();
+
   TranslatedFrame::iterator value_iterator = translated_frame->begin();
+  bool is_bottommost = (0 == frame_index);
+  bool is_topmost = (output_count_ - 1 == frame_index);
   int input_index = 0;
 
   BailoutId node_id = translated_frame->node_id();
   unsigned height =
       translated_frame->height() - 1;  // Do not count the context.
   unsigned height_in_bytes = height * kPointerSize;
+  if (goto_catch_handler) {
+    // Take the stack height from the handler table.
+    height = catch_handler_data_;
+    // We also make space for the exception itself.
+    height_in_bytes = (height + 1) * kPointerSize;
+    CHECK(is_topmost);
+  }
+
   JSFunction* function = JSFunction::cast(value_iterator->GetRawValue());
   value_iterator++;
   input_index++;
   if (trace_scope_ != NULL) {
     PrintF(trace_scope_->file(), "  translating frame ");
-    function->PrintName(trace_scope_->file());
+    base::SmartArrayPointer<char> name = shared->DebugName()->ToCString();
+    PrintF(trace_scope_->file(), "%s", name.get());
     PrintF(trace_scope_->file(),
            " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes);
+    PrintF(trace_scope_->file(), " => node=%d, height=%d%s\n", node_id.ToInt(),
+           height_in_bytes, goto_catch_handler ? " (throw)" : "");
   }
 
   // The 'fixed' part of the frame consists of the incoming parameters and
   // the part described by JavaScriptFrameConstants.
-  unsigned fixed_frame_size = ComputeJavascriptFixedSize(function);
+  unsigned fixed_frame_size = ComputeJavascriptFixedSize(shared);
   unsigned input_frame_size = input_->GetFrameSize();
   unsigned output_frame_size = height_in_bytes + fixed_frame_size;
 
   // Allocate and store the output frame description.
-  FrameDescription* output_frame =
-      new(output_frame_size) FrameDescription(output_frame_size, function);
+  int parameter_count = shared->internal_formal_parameter_count() + 1;
+  FrameDescription* output_frame = new (output_frame_size)
+      FrameDescription(output_frame_size, parameter_count);
   output_frame->SetFrameType(StackFrame::JAVA_SCRIPT);
 
-  bool is_bottommost = (0 == frame_index);
-  bool is_topmost = (output_count_ - 1 == frame_index);
   CHECK(frame_index >= 0 && frame_index < output_count_);
   CHECK_NULL(output_[frame_index]);
   output_[frame_index] = output_frame;
@@ -856,9 +884,8 @@
   if (is_bottommost) {
     // Determine whether the input frame contains alignment padding.
     has_alignment_padding_ =
-        (!compiled_code_->is_turbofanned() && HasAlignmentPadding(function))
-            ? 1
-            : 0;
+        (!compiled_code_->is_turbofanned() && HasAlignmentPadding(shared)) ? 1
+                                                                           : 0;
     // 2 = context and function in the frame.
     // If the optimized frame had alignment padding, adjust the frame pointer
     // to point to the new position of the old frame pointer after padding
@@ -872,8 +899,6 @@
   output_frame->SetTop(top_address);
 
   // Compute the incoming parameter translation.
-  int parameter_count =
-      function->shared()->internal_formal_parameter_count() + 1;
   unsigned output_offset = output_frame_size;
   unsigned input_offset = input_frame_size;
   for (int i = 0; i < parameter_count; ++i) {
@@ -945,8 +970,20 @@
   Register context_reg = JavaScriptFrame::context_register();
   output_offset -= kPointerSize;
   input_offset -= kPointerSize;
+
+  TranslatedFrame::iterator context_pos = value_iterator;
+  int context_input_index = input_index;
+  // When deoptimizing into a catch block, we need to take the context
+  // from just above the top of the operand stack (we push the context
+  // at the entry of the try block).
+  if (goto_catch_handler) {
+    for (unsigned i = 0; i < height + 1; ++i) {
+      context_pos++;
+      context_input_index++;
+    }
+  }
   // Read the context from the translations.
-  Object* context = value_iterator->GetRawValue();
+  Object* context = context_pos->GetRawValue();
   if (context == isolate_->heap()->undefined_value()) {
     // If the context was optimized away, just use the context from
     // the activation. This should only apply to Crankshaft code.
@@ -959,13 +996,13 @@
   value = reinterpret_cast<intptr_t>(context);
   output_frame->SetContext(value);
   if (is_topmost) output_frame->SetRegister(context_reg.code(), value);
-  WriteValueToOutput(context, input_index, frame_index, output_offset,
+  WriteValueToOutput(context, context_input_index, frame_index, output_offset,
                      "context    ");
   if (context == isolate_->heap()->arguments_marker()) {
     Address output_address =
         reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
         output_offset;
-    values_to_materialize_.push_back({output_address, value_iterator});
+    values_to_materialize_.push_back({output_address, context_pos});
   }
   value_iterator++;
   input_index++;
@@ -985,19 +1022,19 @@
     WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
                                  output_offset);
   }
+  if (goto_catch_handler) {
+    // Write out the exception for the catch handler.
+    output_offset -= kPointerSize;
+    Object* exception_obj = reinterpret_cast<Object*>(
+        input_->GetRegister(FullCodeGenerator::result_register().code()));
+    WriteValueToOutput(exception_obj, input_index, frame_index, output_offset,
+                       "exception   ");
+    input_index++;
+  }
   CHECK_EQ(0u, output_offset);
 
-  // Compute this frame's PC, state, and continuation.
-  Code* non_optimized_code = function->shared()->code();
-  FixedArray* raw_data = non_optimized_code->deoptimization_data();
-  DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
-  Address start = non_optimized_code->instruction_start();
-  unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared());
-  unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
-  intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset);
-  output_frame->SetPc(pc_value);
-
   // Update constant pool.
+  Code* non_optimized_code = shared->code();
   if (FLAG_enable_embedded_constant_pool) {
     intptr_t constant_pool_value =
         reinterpret_cast<intptr_t>(non_optimized_code->constant_pool());
@@ -1009,8 +1046,22 @@
     }
   }
 
+  // Compute this frame's PC, state, and continuation.
+  FixedArray* raw_data = non_optimized_code->deoptimization_data();
+  DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
+  Address start = non_optimized_code->instruction_start();
+  unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared());
+  unsigned pc_offset = goto_catch_handler
+                           ? catch_handler_pc_offset_
+                           : FullCodeGenerator::PcField::decode(pc_and_state);
+  intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset);
+  output_frame->SetPc(pc_value);
+
+  // If we are going to the catch handler, then the exception lives in
+  // the accumulator.
   FullCodeGenerator::State state =
-      FullCodeGenerator::StateField::decode(pc_and_state);
+      goto_catch_handler ? FullCodeGenerator::TOS_REG
+                         : FullCodeGenerator::StateField::decode(pc_and_state);
   output_frame->SetState(Smi::FromInt(state));
 
   // Set the continuation for the topmost frame.
@@ -1029,14 +1080,16 @@
   }
 }
 
-
-void Deoptimizer::DoComputeInterpretedFrame(int frame_index) {
+void Deoptimizer::DoComputeInterpretedFrame(int frame_index,
+                                            bool goto_catch_handler) {
   TranslatedFrame* translated_frame =
       &(translated_state_.frames()[frame_index]);
+  SharedFunctionInfo* shared = translated_frame->raw_shared_info();
+
   TranslatedFrame::iterator value_iterator = translated_frame->begin();
   int input_index = 0;
 
-  BailoutId bytecode_offset = translated_frame->node_id();
+  int bytecode_offset = translated_frame->node_id().ToInt();
   unsigned height = translated_frame->height();
   unsigned height_in_bytes = height * kPointerSize;
   JSFunction* function = JSFunction::cast(value_iterator->GetRawValue());
@@ -1044,20 +1097,26 @@
   input_index++;
   if (trace_scope_ != NULL) {
     PrintF(trace_scope_->file(), "  translating interpreted frame ");
-    function->PrintName(trace_scope_->file());
-    PrintF(trace_scope_->file(), " => bytecode_offset=%d, height=%d\n",
-           bytecode_offset.ToInt(), height_in_bytes);
+    base::SmartArrayPointer<char> name = shared->DebugName()->ToCString();
+    PrintF(trace_scope_->file(), "%s", name.get());
+    PrintF(trace_scope_->file(), " => bytecode_offset=%d, height=%d%s\n",
+           bytecode_offset, height_in_bytes,
+           goto_catch_handler ? " (throw)" : "");
+  }
+  if (goto_catch_handler) {
+    bytecode_offset = catch_handler_pc_offset_;
   }
 
   // The 'fixed' part of the frame consists of the incoming parameters and
   // the part described by InterpreterFrameConstants.
-  unsigned fixed_frame_size = ComputeInterpretedFixedSize(function);
+  unsigned fixed_frame_size = ComputeInterpretedFixedSize(shared);
   unsigned input_frame_size = input_->GetFrameSize();
   unsigned output_frame_size = height_in_bytes + fixed_frame_size;
 
   // Allocate and store the output frame description.
-  FrameDescription* output_frame =
-      new (output_frame_size) FrameDescription(output_frame_size, function);
+  int parameter_count = shared->internal_formal_parameter_count() + 1;
+  FrameDescription* output_frame = new (output_frame_size)
+      FrameDescription(output_frame_size, parameter_count);
   output_frame->SetFrameType(StackFrame::INTERPRETED);
 
   bool is_bottommost = (0 == frame_index);
@@ -1084,8 +1143,6 @@
   output_frame->SetTop(top_address);
 
   // Compute the incoming parameter translation.
-  int parameter_count =
-      function->shared()->internal_formal_parameter_count() + 1;
   unsigned output_offset = output_frame_size;
   unsigned input_offset = input_frame_size;
   for (int i = 0; i < parameter_count; ++i) {
@@ -1159,14 +1216,27 @@
   Register context_reg = InterpretedFrame::context_register();
   output_offset -= kPointerSize;
   input_offset -= kPointerSize;
+
+  // When deoptimizing into a catch block, we need to take the context
+  // from a register that was specified in the handler table.
+  TranslatedFrame::iterator context_pos = value_iterator;
+  int context_input_index = input_index;
+  if (goto_catch_handler) {
+    // Skip to the translated value of the register specified
+    // in the handler table.
+    for (int i = 0; i < catch_handler_data_ + 1; ++i) {
+      context_pos++;
+      context_input_index++;
+    }
+  }
   // Read the context from the translations.
-  Object* context = value_iterator->GetRawValue();
+  Object* context = context_pos->GetRawValue();
   // The context should not be a placeholder for a materialized object.
   CHECK(context != isolate_->heap()->arguments_marker());
   value = reinterpret_cast<intptr_t>(context);
   output_frame->SetContext(value);
   if (is_topmost) output_frame->SetRegister(context_reg.code(), value);
-  WriteValueToOutput(context, input_index, frame_index, output_offset,
+  WriteValueToOutput(context, context_input_index, frame_index, output_offset,
                      "context    ");
   value_iterator++;
   input_index++;
@@ -1180,45 +1250,64 @@
   DCHECK(!is_bottommost || input_->GetFrameSlot(input_offset) == value);
   WriteValueToOutput(function, 0, frame_index, output_offset, "function    ");
 
-  // TODO(rmcilroy): Deal with new.target correctly - currently just set it to
+  // The new.target slot is only used during function activiation which is
+  // before the first deopt point, so should never be needed. Just set it to
   // undefined.
   output_offset -= kPointerSize;
   input_offset -= kPointerSize;
   Object* new_target = isolate_->heap()->undefined_value();
   WriteValueToOutput(new_target, 0, frame_index, output_offset, "new_target  ");
 
+  // Set the bytecode array pointer.
+  output_offset -= kPointerSize;
+  input_offset -= kPointerSize;
+  Object* bytecode_array = shared->bytecode_array();
+  WriteValueToOutput(bytecode_array, 0, frame_index, output_offset,
+                     "bytecode array ");
+
   // The bytecode offset was mentioned explicitly in the BEGIN_FRAME.
   output_offset -= kPointerSize;
   input_offset -= kPointerSize;
   int raw_bytecode_offset =
-      BytecodeArray::kHeaderSize - kHeapObjectTag + bytecode_offset.ToInt();
+      BytecodeArray::kHeaderSize - kHeapObjectTag + bytecode_offset;
   Smi* smi_bytecode_offset = Smi::FromInt(raw_bytecode_offset);
   WriteValueToOutput(smi_bytecode_offset, 0, frame_index, output_offset,
                      "bytecode offset ");
 
   // Translate the rest of the interpreter registers in the frame.
-  for (unsigned i = 0; i < height; ++i) {
+  for (unsigned i = 0; i < height - 1; ++i) {
     output_offset -= kPointerSize;
     WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
                                  output_offset);
   }
+
+  // Put the accumulator on the stack. It will be popped by the
+  // InterpreterNotifyDeopt builtin (possibly after materialization).
+  output_offset -= kPointerSize;
+  if (goto_catch_handler) {
+    // If we are lazy deopting to a catch handler, we set the accumulator to
+    // the exception (which lives in the result register).
+    intptr_t accumulator_value =
+        input_->GetRegister(FullCodeGenerator::result_register().code());
+    WriteValueToOutput(reinterpret_cast<Object*>(accumulator_value), 0,
+                       frame_index, output_offset, "accumulator ");
+    value_iterator++;
+  } else {
+    WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
+                                 output_offset);
+  }
   CHECK_EQ(0u, output_offset);
 
-  // Set the accumulator register.
-  output_frame->SetRegister(
-      kInterpreterAccumulatorRegister.code(),
-      reinterpret_cast<intptr_t>(value_iterator->GetRawValue()));
-  value_iterator++;
-
   Builtins* builtins = isolate_->builtins();
-  Code* trampoline = builtins->builtin(Builtins::kInterpreterEntryTrampoline);
-  output_frame->SetPc(reinterpret_cast<intptr_t>(trampoline->entry()));
+  Code* dispatch_builtin =
+      builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
+  output_frame->SetPc(reinterpret_cast<intptr_t>(dispatch_builtin->entry()));
   output_frame->SetState(0);
 
   // Update constant pool.
   if (FLAG_enable_embedded_constant_pool) {
     intptr_t constant_pool_value =
-        reinterpret_cast<intptr_t>(trampoline->constant_pool());
+        reinterpret_cast<intptr_t>(dispatch_builtin->constant_pool());
     output_frame->SetConstantPool(constant_pool_value);
     if (is_topmost) {
       Register constant_pool_reg =
@@ -1266,8 +1355,9 @@
   unsigned output_frame_size = height_in_bytes + fixed_frame_size;
 
   // Allocate and store the output frame description.
-  FrameDescription* output_frame =
-      new(output_frame_size) FrameDescription(output_frame_size, function);
+  int parameter_count = height;
+  FrameDescription* output_frame = new (output_frame_size)
+      FrameDescription(output_frame_size, parameter_count);
   output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR);
 
   // Arguments adaptor can not be topmost or bottommost.
@@ -1282,7 +1372,6 @@
   output_frame->SetTop(top_address);
 
   // Compute the incoming parameter translation.
-  int parameter_count = height;
   unsigned output_offset = output_frame_size;
   for (int i = 0; i < parameter_count; ++i) {
     output_offset -= kPointerSize;
@@ -1362,7 +1451,7 @@
   Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
   unsigned height = translated_frame->height();
   unsigned height_in_bytes = height * kPointerSize;
-  JSFunction* function = JSFunction::cast(value_iterator->GetRawValue());
+  // Skip function.
   value_iterator++;
   input_index++;
   if (trace_scope_ != NULL) {
@@ -1375,7 +1464,7 @@
 
   // Allocate and store the output frame description.
   FrameDescription* output_frame =
-      new(output_frame_size) FrameDescription(output_frame_size, function);
+      new (output_frame_size) FrameDescription(output_frame_size);
   output_frame->SetFrameType(StackFrame::CONSTRUCT);
 
   // Construct stub can not be topmost or bottommost.
@@ -1488,7 +1577,7 @@
   TranslatedFrame::iterator value_iterator = translated_frame->begin();
   int input_index = 0;
 
-  JSFunction* accessor = JSFunction::cast(value_iterator->GetRawValue());
+  // Skip accessor.
   value_iterator++;
   input_index++;
   // The receiver (and the implicit return value, if any) are expected in
@@ -1515,7 +1604,7 @@
 
   // Allocate and store the output frame description.
   FrameDescription* output_frame =
-      new(output_frame_size) FrameDescription(output_frame_size, accessor);
+      new (output_frame_size) FrameDescription(output_frame_size);
   output_frame->SetFrameType(StackFrame::INTERNAL);
 
   // A frame for an accessor stub can not be the topmost or bottommost one.
@@ -1657,7 +1746,9 @@
   // object to the stub failure handler.
   int param_count = descriptor.GetRegisterParameterCount();
   int stack_param_count = descriptor.GetStackParameterCount();
-  CHECK_EQ(translated_frame->height(), param_count);
+  // The translated frame contains all of the register parameters
+  // plus the context.
+  CHECK_EQ(translated_frame->height(), param_count + 1);
   CHECK_GE(param_count, 0);
 
   int height_in_bytes = kPointerSize * (param_count + stack_param_count) +
@@ -1674,7 +1765,7 @@
 
   // The stub failure trampoline is a single frame.
   FrameDescription* output_frame =
-      new(output_frame_size) FrameDescription(output_frame_size, NULL);
+      new (output_frame_size) FrameDescription(output_frame_size);
   output_frame->SetFrameType(StackFrame::STUB_FAILURE_TRAMPOLINE);
   CHECK_EQ(frame_index, 0);
   output_[frame_index] = output_frame;
@@ -1716,15 +1807,10 @@
                          "caller's constant_pool\n");
   }
 
-  // The context can be gotten from the input frame.
-  Register context_reg = StubFailureTrampolineFrame::context_register();
-  input_frame_offset -= kPointerSize;
-  value = input_->GetFrameSlot(input_frame_offset);
-  output_frame->SetRegister(context_reg.code(), value);
+  // Remember where the context will need to be written back from the deopt
+  // translation.
   output_frame_offset -= kPointerSize;
-  output_frame->SetFrameSlot(output_frame_offset, value);
-  CHECK(reinterpret_cast<Object*>(value)->IsContext());
-  DebugPrintOutputSlot(value, frame_index, output_frame_offset, "context\n");
+  unsigned context_frame_offset = output_frame_offset;
 
   // A marker value is used in place of the function.
   output_frame_offset -= kPointerSize;
@@ -1782,6 +1868,15 @@
     }
   }
 
+  Object* maybe_context = value_iterator->GetRawValue();
+  CHECK(maybe_context->IsContext());
+  Register context_reg = StubFailureTrampolineFrame::context_register();
+  value = reinterpret_cast<intptr_t>(maybe_context);
+  output_frame->SetRegister(context_reg.code(), value);
+  output_frame->SetFrameSlot(context_frame_offset, value);
+  DebugPrintOutputSlot(value, frame_index, context_frame_offset, "context\n");
+  ++value_iterator;
+
   // Copy constant stack parameters to the failure frame. If the number of stack
   // parameters is not known in the descriptor, the arguments object is the way
   // to access them.
@@ -1875,55 +1970,6 @@
 }
 
 
-void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame(
-    int frame_index, int parameter_count, int expression_count,
-    DeoptimizedFrameInfo* info) {
-  CHECK_EQ(DEBUGGER, bailout_type_);
-
-  translated_state_.Prepare(false, nullptr);
-
-  TranslatedFrame* frame = &(translated_state_.frames()[frame_index]);
-  CHECK(frame->kind() == TranslatedFrame::kFunction);
-  int frame_arg_count = frame->shared_info()->internal_formal_parameter_count();
-
-  // The height is #expressions + 1 for context.
-  CHECK_EQ(expression_count + 1, frame->height());
-  TranslatedFrame* argument_frame = frame;
-  if (frame_index > 0) {
-    TranslatedFrame* previous_frame =
-        &(translated_state_.frames()[frame_index - 1]);
-    if (previous_frame->kind() == TranslatedFrame::kArgumentsAdaptor) {
-      argument_frame = previous_frame;
-      CHECK_EQ(parameter_count, argument_frame->height() - 1);
-    } else {
-      CHECK_EQ(frame_arg_count, parameter_count);
-    }
-  } else {
-    CHECK_EQ(frame_arg_count, parameter_count);
-  }
-
-  TranslatedFrame::iterator arg_iter = argument_frame->begin();
-  arg_iter++;  // Skip the function.
-  arg_iter++;  // Skip the receiver.
-  for (int i = 0; i < parameter_count; i++, arg_iter++) {
-    if (!arg_iter->IsMaterializedObject()) {
-      info->SetParameter(i, *(arg_iter->GetValue()));
-    }
-  }
-
-  TranslatedFrame::iterator iter = frame->begin();
-  // Skip the function, receiver, context and arguments.
-  for (int i = 0; i < frame_arg_count + 3; i++, iter++) {
-  }
-
-  for (int i = 0; i < expression_count; i++, iter++) {
-    if (!iter->IsMaterializedObject()) {
-      info->SetExpression(i, *(iter->GetValue()));
-    }
-  }
-}
-
-
 void Deoptimizer::WriteTranslatedValueToOutput(
     TranslatedFrame::iterator* iterator, int* input_index, int frame_index,
     unsigned output_offset, const char* debug_hint_string,
@@ -1980,7 +2026,12 @@
 
 
 unsigned Deoptimizer::ComputeInputFrameSize() const {
-  unsigned fixed_size = ComputeJavascriptFixedSize(function_);
+  unsigned fixed_size = StandardFrameConstants::kFixedFrameSize;
+  if (!function_->IsSmi()) {
+    fixed_size += ComputeIncomingArgumentSize(function_->shared());
+  } else {
+    CHECK_EQ(Smi::cast(function_), Smi::FromInt(StackFrame::STUB));
+  }
   // The fp-to-sp delta already takes the context, constant pool pointer and the
   // function into account so we have to avoid double counting them.
   unsigned result = fixed_size + fp_to_sp_delta_ -
@@ -1989,39 +2040,33 @@
     unsigned stack_slots = compiled_code_->stack_slots();
     unsigned outgoing_size =
         ComputeOutgoingArgumentSize(compiled_code_, bailout_id_);
-    CHECK(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size);
+    CHECK(result ==
+          fixed_size + (stack_slots * kPointerSize) -
+              StandardFrameConstants::kFixedFrameSize + outgoing_size);
   }
   return result;
 }
 
-
-unsigned Deoptimizer::ComputeJavascriptFixedSize(JSFunction* function) const {
+// static
+unsigned Deoptimizer::ComputeJavascriptFixedSize(SharedFunctionInfo* shared) {
   // The fixed part of the frame consists of the return address, frame
   // pointer, function, context, and all the incoming arguments.
-  return ComputeIncomingArgumentSize(function) +
+  return ComputeIncomingArgumentSize(shared) +
          StandardFrameConstants::kFixedFrameSize;
 }
 
-
-unsigned Deoptimizer::ComputeInterpretedFixedSize(JSFunction* function) const {
+// static
+unsigned Deoptimizer::ComputeInterpretedFixedSize(SharedFunctionInfo* shared) {
   // The fixed part of the frame consists of the return address, frame
   // pointer, function, context, new.target, bytecode offset and all the
   // incoming arguments.
-  return ComputeIncomingArgumentSize(function) +
+  return ComputeIncomingArgumentSize(shared) +
          InterpreterFrameConstants::kFixedFrameSize;
 }
 
-
-unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const {
-  // The incoming arguments is the values for formal parameters and
-  // the receiver. Every slot contains a pointer.
-  if (function->IsSmi()) {
-    CHECK_EQ(Smi::cast(function), Smi::FromInt(StackFrame::STUB));
-    return 0;
-  }
-  unsigned arguments =
-      function->shared()->internal_formal_parameter_count() + 1;
-  return arguments * kPointerSize;
+// static
+unsigned Deoptimizer::ComputeIncomingArgumentSize(SharedFunctionInfo* shared) {
+  return (shared->internal_formal_parameter_count() + 1) * kPointerSize;
 }
 
 
@@ -2079,11 +2124,9 @@
   data->deopt_entry_code_entries_[type] = entry_count;
 }
 
-
-FrameDescription::FrameDescription(uint32_t frame_size,
-                                   JSFunction* function)
+FrameDescription::FrameDescription(uint32_t frame_size, int parameter_count)
     : frame_size_(frame_size),
-      function_(function),
+      parameter_count_(parameter_count),
       top_(kZapUint32),
       pc_(kZapUint32),
       fp_(kZapUint32),
@@ -2107,10 +2150,10 @@
 int FrameDescription::ComputeFixedSize() {
   if (type_ == StackFrame::INTERPRETED) {
     return InterpreterFrameConstants::kFixedFrameSize +
-           (ComputeParametersCount() + 1) * kPointerSize;
+           parameter_count() * kPointerSize;
   } else {
     return StandardFrameConstants::kFixedFrameSize +
-           (ComputeParametersCount() + 1) * kPointerSize;
+           parameter_count() * kPointerSize;
   }
 }
 
@@ -2123,54 +2166,13 @@
     return base - ((slot_index + 1) * kPointerSize);
   } else {
     // Incoming parameter.
-    int arg_size = (ComputeParametersCount() + 1) * kPointerSize;
+    int arg_size = parameter_count() * kPointerSize;
     unsigned base = GetFrameSize() - arg_size;
     return base - ((slot_index + 1) * kPointerSize);
   }
 }
 
 
-int FrameDescription::ComputeParametersCount() {
-  switch (type_) {
-    case StackFrame::JAVA_SCRIPT:
-      return function_->shared()->internal_formal_parameter_count();
-    case StackFrame::ARGUMENTS_ADAPTOR: {
-      // Last slot contains number of incomming arguments as a smi.
-      // Can't use GetExpression(0) because it would cause infinite recursion.
-      return reinterpret_cast<Smi*>(*GetFrameSlotPointer(0))->value();
-    }
-    case StackFrame::STUB:
-      return -1;  // Minus receiver.
-    default:
-      FATAL("Unexpected stack frame type");
-      return 0;
-  }
-}
-
-
-Object* FrameDescription::GetParameter(int index) {
-  CHECK_GE(index, 0);
-  CHECK_LT(index, ComputeParametersCount());
-  // The slot indexes for incoming arguments are negative.
-  unsigned offset = GetOffsetFromSlotIndex(index - ComputeParametersCount());
-  return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset));
-}
-
-
-unsigned FrameDescription::GetExpressionCount() {
-  CHECK_EQ(StackFrame::JAVA_SCRIPT, type_);
-  unsigned size = GetFrameSize() - ComputeFixedSize();
-  return size / kPointerSize;
-}
-
-
-Object* FrameDescription::GetExpression(int index) {
-  DCHECK_EQ(StackFrame::JAVA_SCRIPT, type_);
-  unsigned offset = GetOffsetFromSlotIndex(index);
-  return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset));
-}
-
-
 void TranslationBuffer::Add(int32_t value, Zone* zone) {
   // This wouldn't handle kMinInt correctly if it ever encountered it.
   DCHECK(value != kMinInt);
@@ -2359,14 +2361,13 @@
 
 
 void Translation::StoreJSFrameFunction() {
-  buffer_->Add(JS_FRAME_FUNCTION, zone());
+  StoreStackSlot((StandardFrameConstants::kCallerPCOffset -
+                  StandardFrameConstants::kMarkerOffset) /
+                 kPointerSize);
 }
 
-
 int Translation::NumberOfOperandsFor(Opcode opcode) {
   switch (opcode) {
-    case JS_FRAME_FUNCTION:
-      return 0;
     case GETTER_STUB_FRAME:
     case SETTER_STUB_FRAME:
     case DUPLICATED_OBJECT:
@@ -2493,60 +2494,111 @@
   return new_array;
 }
 
+namespace {
 
-DeoptimizedFrameInfo::DeoptimizedFrameInfo(Deoptimizer* deoptimizer,
-                                           int frame_index,
-                                           bool has_arguments_adaptor,
-                                           bool has_construct_stub) {
-  FrameDescription* output_frame = deoptimizer->output_[frame_index];
-  function_ = output_frame->GetFunction();
-  context_ = reinterpret_cast<Object*>(output_frame->GetContext());
-  has_construct_stub_ = has_construct_stub;
-  expression_count_ = output_frame->GetExpressionCount();
-  expression_stack_ = new Object* [expression_count_];
-  // Get the source position using the unoptimized code.
-  Address pc = reinterpret_cast<Address>(output_frame->GetPc());
-  Code* code = Code::cast(deoptimizer->isolate()->FindCodeObject(pc));
-  source_position_ = code->SourcePosition(pc);
-
-  for (int i = 0; i < expression_count_; i++) {
-    Object* value = output_frame->GetExpression(i);
-    // Replace materialization markers with the undefined value.
-    if (value == deoptimizer->isolate()->heap()->arguments_marker()) {
-      value = deoptimizer->isolate()->heap()->undefined_value();
+Handle<Object> GetValueForDebugger(TranslatedFrame::iterator it,
+                                   Isolate* isolate) {
+  if (it->GetRawValue() == isolate->heap()->arguments_marker()) {
+    if (!it->IsMaterializableByDebugger()) {
+      return isolate->factory()->undefined_value();
     }
-    SetExpression(i, value);
   }
+  return it->GetValue();
+}
 
-  if (has_arguments_adaptor) {
-    output_frame = deoptimizer->output_[frame_index - 1];
-    CHECK_EQ(output_frame->GetFrameType(), StackFrame::ARGUMENTS_ADAPTOR);
-  }
-
-  parameters_count_ = output_frame->ComputeParametersCount();
-  parameters_ = new Object* [parameters_count_];
-  for (int i = 0; i < parameters_count_; i++) {
-    Object* value = output_frame->GetParameter(i);
-    // Replace materialization markers with the undefined value.
-    if (value == deoptimizer->isolate()->heap()->arguments_marker()) {
-      value = deoptimizer->isolate()->heap()->undefined_value();
-    }
-    SetParameter(i, value);
+int ComputeSourcePosition(Handle<SharedFunctionInfo> shared,
+                          BailoutId node_id) {
+  if (shared->HasBytecodeArray()) {
+    BytecodeArray* bytecodes = shared->bytecode_array();
+    return bytecodes->SourcePosition(node_id.ToInt());
+  } else {
+    Code* non_optimized_code = shared->code();
+    FixedArray* raw_data = non_optimized_code->deoptimization_data();
+    DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
+    unsigned pc_and_state = Deoptimizer::GetOutputInfo(data, node_id, *shared);
+    unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
+    return non_optimized_code->SourcePosition(pc_offset);
   }
 }
 
+}  // namespace
 
-DeoptimizedFrameInfo::~DeoptimizedFrameInfo() {
-  delete[] expression_stack_;
-  delete[] parameters_;
-}
+DeoptimizedFrameInfo::DeoptimizedFrameInfo(TranslatedState* state,
+                                           TranslatedState::iterator frame_it,
+                                           Isolate* isolate) {
+  // If the previous frame is an adaptor frame, we will take the parameters
+  // from there.
+  TranslatedState::iterator parameter_frame = frame_it;
+  if (parameter_frame != state->begin()) {
+    parameter_frame--;
+  }
+  int parameter_count;
+  if (parameter_frame->kind() == TranslatedFrame::kArgumentsAdaptor) {
+    parameter_count = parameter_frame->height() - 1;  // Ignore the receiver.
+  } else {
+    parameter_frame = frame_it;
+    parameter_count =
+        frame_it->shared_info()->internal_formal_parameter_count();
+  }
+  TranslatedFrame::iterator parameter_it = parameter_frame->begin();
+  parameter_it++;  // Skip the function.
+  parameter_it++;  // Skip the receiver.
 
+  // Figure out whether there is a construct stub frame on top of
+  // the parameter frame.
+  has_construct_stub_ =
+      parameter_frame != state->begin() &&
+      (parameter_frame - 1)->kind() == TranslatedFrame::kConstructStub;
 
-void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) {
-  v->VisitPointer(bit_cast<Object**>(&function_));
-  v->VisitPointer(&context_);
-  v->VisitPointers(parameters_, parameters_ + parameters_count_);
-  v->VisitPointers(expression_stack_, expression_stack_ + expression_count_);
+  source_position_ =
+      ComputeSourcePosition(frame_it->shared_info(), frame_it->node_id());
+
+  TranslatedFrame::iterator value_it = frame_it->begin();
+  // Get the function. Note that this might materialize the function.
+  // In case the debugger mutates this value, we should deoptimize
+  // the function and remember the value in the materialized value store.
+  function_ = Handle<JSFunction>::cast(value_it->GetValue());
+
+  parameters_.resize(static_cast<size_t>(parameter_count));
+  for (int i = 0; i < parameter_count; i++) {
+    Handle<Object> parameter = GetValueForDebugger(parameter_it, isolate);
+    SetParameter(i, parameter);
+    parameter_it++;
+  }
+
+  // Skip the function, the receiver and the arguments.
+  int skip_count =
+      frame_it->shared_info()->internal_formal_parameter_count() + 2;
+  TranslatedFrame::iterator stack_it = frame_it->begin();
+  for (int i = 0; i < skip_count; i++) {
+    stack_it++;
+  }
+
+  // Get the context.
+  context_ = GetValueForDebugger(stack_it, isolate);
+  stack_it++;
+
+  // Get the expression stack.
+  int stack_height = frame_it->height();
+  if (frame_it->kind() == TranslatedFrame::kFunction ||
+      frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
+    // For full-code frames, we should not count the context.
+    // For interpreter frames, we should not count the accumulator.
+    // TODO(jarin): Clean up the indexing in translated frames.
+    stack_height--;
+  }
+  expression_stack_.resize(static_cast<size_t>(stack_height));
+  for (int i = 0; i < stack_height; i++) {
+    Handle<Object> expression = GetValueForDebugger(stack_it, isolate);
+    SetExpression(i, expression);
+    stack_it++;
+  }
+
+  // For interpreter frame, skip the accumulator.
+  if (frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
+    stack_it++;
+  }
+  CHECK(stack_it == frame_it->end());
 }
 
 
@@ -2826,6 +2878,10 @@
   }
 }
 
+bool TranslatedValue::IsMaterializableByDebugger() const {
+  // At the moment, we only allow materialization of doubles.
+  return (kind() == kDouble);
+}
 
 int TranslatedValue::GetChildrenCount() const {
   if (kind() == kCapturedObject || kind() == kArgumentsObject) {
@@ -2906,8 +2962,8 @@
     case kInterpretedFunction: {
       int parameter_count =
           raw_shared_info_->internal_formal_parameter_count() + 1;
-      // + 3 for function, context and accumulator.
-      return height_ + parameter_count + 3;
+      // + 2 for function and context.
+      return height_ + parameter_count + 2;
     }
 
     case kGetter:
@@ -3058,7 +3114,6 @@
     case Translation::BOOL_STACK_SLOT:
     case Translation::DOUBLE_STACK_SLOT:
     case Translation::LITERAL:
-    case Translation::JS_FRAME_FUNCTION:
       break;
   }
   FATAL("We should never get here - unexpected deopt info.");
@@ -3261,16 +3316,6 @@
 
       return TranslatedValue::NewTagged(this, value);
     }
-
-    case Translation::JS_FRAME_FUNCTION: {
-      int slot_offset = JavaScriptFrameConstants::kFunctionOffset;
-      intptr_t value = *(reinterpret_cast<intptr_t*>(fp + slot_offset));
-      if (trace_file != nullptr) {
-        PrintF(trace_file, "0x%08" V8PRIxPTR " ; (frame function) ", value);
-        reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
-      }
-      return TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value));
-    }
   }
 
   FATAL("We should never get here - unexpected deopt info.");
@@ -3385,7 +3430,7 @@
 Handle<Object> TranslatedState::MaterializeAt(int frame_index,
                                               int* value_index) {
   TranslatedFrame* frame = &(frames_[frame_index]);
-  DCHECK(static_cast<size_t>(*value_index) < frame->values_.size());
+  CHECK(static_cast<size_t>(*value_index) < frame->values_.size());
 
   TranslatedValue* slot = &(frame->values_[*value_index]);
   (*value_index)++;
@@ -3541,16 +3586,16 @@
       TranslatedState::ObjectPosition pos = object_positions_[object_index];
 
       // Make sure the duplicate is refering to a previous object.
-      DCHECK(pos.frame_index_ < frame_index ||
-             (pos.frame_index_ == frame_index &&
-              pos.value_index_ < *value_index - 1));
+      CHECK(pos.frame_index_ < frame_index ||
+            (pos.frame_index_ == frame_index &&
+             pos.value_index_ < *value_index - 1));
 
       Handle<Object> object =
           frames_[pos.frame_index_].values_[pos.value_index_].GetValue();
 
       // The object should have a (non-sentinel) value.
-      DCHECK(!object.is_null() &&
-             !object.is_identical_to(isolate_->factory()->arguments_marker()));
+      CHECK(!object.is_null() &&
+            !object.is_identical_to(isolate_->factory()->arguments_marker()));
 
       slot->value_ = object;
       return object;
@@ -3583,7 +3628,7 @@
     // recursive functions!)
     Handle<JSFunction> function =
         Handle<JSFunction>::cast(frames_[frame_index].front().GetValue());
-    *result = Handle<JSObject>::cast(Accessors::FunctionGetArguments(function));
+    *result = Accessors::FunctionGetArguments(function);
     return true;
   } else {
     TranslatedFrame* previous_frame = &(frames_[frame_index]);
@@ -3615,7 +3660,8 @@
 TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex(
     int jsframe_index, int* args_count) {
   for (size_t i = 0; i < frames_.size(); i++) {
-    if (frames_[i].kind() == TranslatedFrame::kFunction) {
+    if (frames_[i].kind() == TranslatedFrame::kFunction ||
+        frames_[i].kind() == TranslatedFrame::kInterpretedFunction) {
       if (jsframe_index > 0) {
         jsframe_index--;
       } else {
@@ -3654,7 +3700,7 @@
     new_store = true;
   }
 
-  DCHECK_EQ(length, previously_materialized_objects->length());
+  CHECK_EQ(length, previously_materialized_objects->length());
 
   bool value_changed = false;
   for (int i = 0; i < length; i++) {
@@ -3662,7 +3708,7 @@
     TranslatedValue* value_info =
         &(frames_[pos.frame_index_].values_[pos.value_index_]);
 
-    DCHECK(value_info->IsMaterializedObject());
+    CHECK(value_info->IsMaterializedObject());
 
     Handle<Object> value(value_info->GetRawValue(), isolate_);
 
@@ -3671,14 +3717,15 @@
         previously_materialized_objects->set(i, *value);
         value_changed = true;
       } else {
-        DCHECK(previously_materialized_objects->get(i) == *value);
+        CHECK(previously_materialized_objects->get(i) == *value);
       }
     }
   }
   if (new_store && value_changed) {
     materialized_store->Set(stack_frame_pointer_,
                             previously_materialized_objects);
-    DCHECK_EQ(TranslatedFrame::kFunction, frames_[0].kind());
+    CHECK(frames_[0].kind() == TranslatedFrame::kFunction ||
+          frames_[0].kind() == TranslatedFrame::kInterpretedFunction);
     Object* const function = frames_[0].front().GetRawValue();
     Deoptimizer::DeoptimizeFunction(JSFunction::cast(function));
   }
@@ -3697,7 +3744,7 @@
   Handle<Object> marker = isolate_->factory()->arguments_marker();
 
   int length = static_cast<int>(object_positions_.size());
-  DCHECK_EQ(length, previously_materialized_objects->length());
+  CHECK_EQ(length, previously_materialized_objects->length());
 
   for (int i = 0; i < length; i++) {
     // For a previously materialized objects, inject their value into the
@@ -3706,7 +3753,7 @@
       TranslatedState::ObjectPosition pos = object_positions_[i];
       TranslatedValue* value_info =
           &(frames_[pos.frame_index_].values_[pos.value_index_]);
-      DCHECK(value_info->IsMaterializedObject());
+      CHECK(value_info->IsMaterializedObject());
 
       value_info->value_ =
           Handle<Object>(previously_materialized_objects->get(i), isolate_);