Upgrade V8 to 5.1.281.57  DO NOT MERGE

FPIIM-449

Change-Id: Id981b686b4d587ac31697662eb98bb34be42ad90
(cherry picked from commit 3b9bc31999c9787eb726ecdbfd5796bfdec32a18)
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index e00e5ab..b2c5d42 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -38,7 +38,7 @@
 DeoptimizerData::DeoptimizerData(MemoryAllocator* allocator)
     : allocator_(allocator),
       current_(NULL) {
-  for (int i = 0; i < Deoptimizer::kBailoutTypesWithCodeEntry; ++i) {
+  for (int i = 0; i <= Deoptimizer::kLastBailoutType; ++i) {
     deopt_entry_code_entries_[i] = -1;
     deopt_entry_code_[i] = AllocateCodeChunk(allocator);
   }
@@ -46,7 +46,7 @@
 
 
 DeoptimizerData::~DeoptimizerData() {
-  for (int i = 0; i < Deoptimizer::kBailoutTypesWithCodeEntry; ++i) {
+  for (int i = 0; i <= Deoptimizer::kLastBailoutType; ++i) {
     allocator_->Free(deopt_entry_code_[i]);
     deopt_entry_code_[i] = NULL;
   }
@@ -307,7 +307,7 @@
 
   // Move marked code from the optimized code list to the deoptimized
   // code list, collecting them into a ZoneList.
-  Zone zone;
+  Zone zone(isolate->allocator());
   ZoneList<Code*> codes(10, &zone);
 
   // Walk over all optimized code objects in this native context.
@@ -444,7 +444,6 @@
     case EAGER:
     case SOFT:
     case LAZY:
-    case DEBUGGER:
       return (frame_type == StackFrame::STUB)
           ? FLAG_trace_stub_failures
           : FLAG_trace_deopt;
@@ -459,7 +458,6 @@
     case EAGER: return "eager";
     case SOFT: return "soft";
     case LAZY: return "lazy";
-    case DEBUGGER: return "debugger";
   }
   FATAL("Unsupported deopt type");
   return NULL;
@@ -474,7 +472,6 @@
       bailout_type_(type),
       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),
@@ -482,6 +479,12 @@
       output_count_(0),
       jsframe_count_(0),
       output_(nullptr),
+      caller_frame_top_(0),
+      caller_fp_(0),
+      caller_pc_(0),
+      caller_constant_pool_(0),
+      input_frame_context_(0),
+      stack_fp_(0),
       trace_scope_(nullptr) {
   if (isolate->deoptimizer_lazy_throw()) {
     isolate->set_deoptimizer_lazy_throw(false);
@@ -546,9 +549,6 @@
           ? static_cast<Code*>(isolate_->FindCodeObject(from_))
           : compiled_code;
     }
-    case Deoptimizer::DEBUGGER:
-      DCHECK(optimized_code->contains(from_));
-      return optimized_code;
   }
   FATAL("Could not find code for optimized function");
   return NULL;
@@ -601,7 +601,7 @@
     CHECK_EQ(mode, CALCULATE_ENTRY_ADDRESS);
   }
   DeoptimizerData* data = isolate->deoptimizer_data();
-  CHECK_LT(type, kBailoutTypesWithCodeEntry);
+  CHECK_LE(type, kLastBailoutType);
   MemoryChunk* base = data->deopt_entry_code_[type];
   return base->area_start() + (id * table_entry_size_);
 }
@@ -711,16 +711,38 @@
   DeoptimizationInputData* input_data =
       DeoptimizationInputData::cast(compiled_code_->deoptimization_data());
 
+  {
+    // Read caller's PC, caller's FP and caller's constant pool values
+    // from input frame. Compute caller's frame top address.
+
+    Register fp_reg = JavaScriptFrame::fp_register();
+    stack_fp_ = input_->GetRegister(fp_reg.code());
+
+    caller_frame_top_ = stack_fp_ + ComputeInputFrameAboveFpFixedSize();
+
+    Address fp_address = input_->GetFramePointerAddress();
+    caller_fp_ = Memory::intptr_at(fp_address);
+    caller_pc_ =
+        Memory::intptr_at(fp_address + CommonFrameConstants::kCallerPCOffset);
+    input_frame_context_ = Memory::intptr_at(
+        fp_address + CommonFrameConstants::kContextOrFrameTypeOffset);
+
+    if (FLAG_enable_embedded_constant_pool) {
+      caller_constant_pool_ = Memory::intptr_at(
+          fp_address + CommonFrameConstants::kConstantPoolOffset);
+    }
+  }
+
   if (trace_scope_ != NULL) {
     timer.Start();
     PrintF(trace_scope_->file(), "[deoptimizing (DEOPT %s): begin ",
            MessageFor(bailout_type_));
     PrintFunctionName();
     PrintF(trace_scope_->file(),
-           " (opt #%d) @%d, FP to SP delta: %d]\n",
-           input_data->OptimizationId()->value(),
-           bailout_id_,
-           fp_to_sp_delta_);
+           " (opt #%d) @%d, FP to SP delta: %d, caller sp: 0x%08" V8PRIxPTR
+           "]\n",
+           input_data->OptimizationId()->value(), bailout_id_, fp_to_sp_delta_,
+           caller_frame_top_);
     if (bailout_type_ == EAGER || bailout_type_ == SOFT ||
         (compiled_code_->is_hydrogen_stub())) {
       compiled_code_->PrintDeoptLocation(trace_scope_->file(), from_);
@@ -763,39 +785,42 @@
   }
   output_count_ = static_cast<int>(count);
 
-  Register fp_reg = JavaScriptFrame::fp_register();
-  stack_fp_ = reinterpret_cast<Address>(
-      input_->GetRegister(fp_reg.code()) +
-          has_alignment_padding_ * kPointerSize);
-
   // Translate each output frame.
-  for (size_t i = 0; i < count; ++i) {
+  int frame_index = 0;  // output_frame_index
+  for (size_t i = 0; i < count; ++i, ++frame_index) {
     // Read the ast node id, function, and frame height for this output frame.
-    int frame_index = static_cast<int>(i);
-    switch (translated_state_.frames()[i].kind()) {
+    TranslatedFrame* translated_frame = &(translated_state_.frames()[i]);
+    switch (translated_frame->kind()) {
       case TranslatedFrame::kFunction:
-        DoComputeJSFrame(frame_index, deoptimizing_throw_ && i == count - 1);
+        DoComputeJSFrame(translated_frame, frame_index,
+                         deoptimizing_throw_ && i == count - 1);
         jsframe_count_++;
         break;
       case TranslatedFrame::kInterpretedFunction:
-        DoComputeInterpretedFrame(frame_index,
+        DoComputeInterpretedFrame(translated_frame, frame_index,
                                   deoptimizing_throw_ && i == count - 1);
         jsframe_count_++;
         break;
       case TranslatedFrame::kArgumentsAdaptor:
-        DoComputeArgumentsAdaptorFrame(frame_index);
+        DoComputeArgumentsAdaptorFrame(translated_frame, frame_index);
+        break;
+      case TranslatedFrame::kTailCallerFunction:
+        DoComputeTailCallerFrame(translated_frame, frame_index);
+        // Tail caller frame translations do not produce output frames.
+        frame_index--;
+        output_count_--;
         break;
       case TranslatedFrame::kConstructStub:
-        DoComputeConstructStubFrame(frame_index);
+        DoComputeConstructStubFrame(translated_frame, frame_index);
         break;
       case TranslatedFrame::kGetter:
-        DoComputeAccessorStubFrame(frame_index, false);
+        DoComputeAccessorStubFrame(translated_frame, frame_index, false);
         break;
       case TranslatedFrame::kSetter:
-        DoComputeAccessorStubFrame(frame_index, true);
+        DoComputeAccessorStubFrame(translated_frame, frame_index, true);
         break;
       case TranslatedFrame::kCompiledStub:
-        DoComputeCompiledStubFrame(frame_index);
+        DoComputeCompiledStubFrame(translated_frame, frame_index);
         break;
       case TranslatedFrame::kInvalid:
         FATAL("invalid frame");
@@ -811,22 +836,18 @@
            MessageFor(bailout_type_));
     PrintFunctionName();
     PrintF(trace_scope_->file(),
-           " @%d => node=%d, pc=0x%08" V8PRIxPTR ", state=%s, alignment=%s,"
-           " took %0.3f ms]\n",
-           bailout_id_,
-           node_id.ToInt(),
-           output_[index]->GetPc(),
-           FullCodeGenerator::State2String(
-               static_cast<FullCodeGenerator::State>(
-                   output_[index]->GetState()->value())),
-           has_alignment_padding_ ? "with padding" : "no padding",
+           " @%d => node=%d, pc=0x%08" V8PRIxPTR ", caller sp=0x%08" V8PRIxPTR
+           ", state=%s, took %0.3f ms]\n",
+           bailout_id_, node_id.ToInt(), output_[index]->GetPc(),
+           caller_frame_top_, FullCodeGenerator::State2String(
+                                  static_cast<FullCodeGenerator::State>(
+                                      output_[index]->GetState()->value())),
            ms);
   }
 }
 
-void Deoptimizer::DoComputeJSFrame(int frame_index, bool goto_catch_handler) {
-  TranslatedFrame* translated_frame =
-      &(translated_state_.frames()[frame_index]);
+void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame,
+                                   int frame_index, bool goto_catch_handler) {
   SharedFunctionInfo* shared = translated_frame->raw_shared_info();
 
   TranslatedFrame::iterator value_iterator = translated_frame->begin();
@@ -853,8 +874,6 @@
     PrintF(trace_scope_->file(), "  translating frame ");
     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)" : "");
   }
@@ -862,7 +881,6 @@
   // The 'fixed' part of the frame consists of the incoming parameters and
   // the part described by JavaScriptFrameConstants.
   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.
@@ -875,24 +893,11 @@
   CHECK_NULL(output_[frame_index]);
   output_[frame_index] = output_frame;
 
-  // The top address for the bottommost output frame can be computed from
-  // the input frame pointer and the output frame's height.  For all
-  // subsequent output frames, it can be computed from the previous one's
-  // top address and the current frame's size.
-  Register fp_reg = JavaScriptFrame::fp_register();
+  // The top address of the frame is computed from the previous frame's top and
+  // this frame's size.
   intptr_t top_address;
   if (is_bottommost) {
-    // Determine whether the input frame contains alignment padding.
-    has_alignment_padding_ =
-        (!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
-    // is removed. Subtract 2 * kPointerSize for the context and function slots.
-    top_address = input_->GetRegister(fp_reg.code()) -
-        StandardFrameConstants::kFixedFrameSizeFromFp -
-        height_in_bytes + has_alignment_padding_ * kPointerSize;
+    top_address = caller_frame_top_ - output_frame_size;
   } else {
     top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
   }
@@ -900,13 +905,11 @@
 
   // Compute the incoming parameter translation.
   unsigned output_offset = output_frame_size;
-  unsigned input_offset = input_frame_size;
   for (int i = 0; i < parameter_count; ++i) {
     output_offset -= kPointerSize;
     WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
                                  output_offset);
   }
-  input_offset -= (parameter_count * kPointerSize);
 
   // There are no translation commands for the caller's pc and fp, the
   // context, and the function.  Synthesize their values and set them up
@@ -917,10 +920,9 @@
   // previous one.  This frame's pc can be computed from the non-optimized
   // function code and AST id of the bailout.
   output_offset -= kPCOnStackSize;
-  input_offset -= kPCOnStackSize;
   intptr_t value;
   if (is_bottommost) {
-    value = input_->GetFrameSlot(input_offset);
+    value = caller_pc_;
   } else {
     value = output_[frame_index - 1]->GetPc();
   }
@@ -932,30 +934,27 @@
   // read from the previous one.  Also compute and set this frame's frame
   // pointer.
   output_offset -= kFPOnStackSize;
-  input_offset -= kFPOnStackSize;
   if (is_bottommost) {
-    value = input_->GetFrameSlot(input_offset);
+    value = caller_fp_;
   } else {
     value = output_[frame_index - 1]->GetFp();
   }
   output_frame->SetCallerFp(output_offset, value);
   intptr_t fp_value = top_address + output_offset;
-  DCHECK(!is_bottommost || (input_->GetRegister(fp_reg.code()) +
-      has_alignment_padding_ * kPointerSize) == fp_value);
   output_frame->SetFp(fp_value);
-  if (is_topmost) output_frame->SetRegister(fp_reg.code(), fp_value);
+  if (is_topmost) {
+    Register fp_reg = JavaScriptFrame::fp_register();
+    output_frame->SetRegister(fp_reg.code(), fp_value);
+  }
   DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
-  DCHECK(!is_bottommost || !has_alignment_padding_ ||
-         (fp_value & kPointerSize) != 0);
 
   if (FLAG_enable_embedded_constant_pool) {
     // For the bottommost output frame the constant pool pointer can be gotten
     // from the input frame. For subsequent output frames, it can be read from
     // the previous frame.
     output_offset -= kPointerSize;
-    input_offset -= kPointerSize;
     if (is_bottommost) {
-      value = input_->GetFrameSlot(input_offset);
+      value = caller_constant_pool_;
     } else {
       value = output_[frame_index - 1]->GetConstantPool();
     }
@@ -967,9 +966,7 @@
   // For the bottommost output frame the context can be gotten from the input
   // frame. For all subsequent output frames it can be gotten from the function
   // so long as we don't inline functions that need local contexts.
-  Register context_reg = JavaScriptFrame::context_register();
   output_offset -= kPointerSize;
-  input_offset -= kPointerSize;
 
   TranslatedFrame::iterator context_pos = value_iterator;
   int context_input_index = input_index;
@@ -988,14 +985,15 @@
     // If the context was optimized away, just use the context from
     // the activation. This should only apply to Crankshaft code.
     CHECK(!compiled_code_->is_turbofanned());
-    context =
-        is_bottommost
-            ? reinterpret_cast<Object*>(input_->GetFrameSlot(input_offset))
-            : function->context();
+    context = is_bottommost ? reinterpret_cast<Object*>(input_frame_context_)
+                            : function->context();
   }
   value = reinterpret_cast<intptr_t>(context);
   output_frame->SetContext(value);
-  if (is_topmost) output_frame->SetRegister(context_reg.code(), value);
+  if (is_topmost) {
+    Register context_reg = JavaScriptFrame::context_register();
+    output_frame->SetRegister(context_reg.code(), value);
+  }
   WriteValueToOutput(context, context_input_index, frame_index, output_offset,
                      "context    ");
   if (context == isolate_->heap()->arguments_marker()) {
@@ -1009,11 +1007,7 @@
 
   // The function was mentioned explicitly in the BEGIN_FRAME.
   output_offset -= kPointerSize;
-  input_offset -= kPointerSize;
   value = reinterpret_cast<intptr_t>(function);
-  // The function for the bottommost output frame should also agree with the
-  // input frame.
-  DCHECK(!is_bottommost || input_->GetFrameSlot(input_offset) == value);
   WriteValueToOutput(function, 0, frame_index, output_offset, "function    ");
 
   // Translate the rest of the frame.
@@ -1065,7 +1059,7 @@
   output_frame->SetState(Smi::FromInt(state));
 
   // Set the continuation for the topmost frame.
-  if (is_topmost && bailout_type_ != DEBUGGER) {
+  if (is_topmost) {
     Builtins* builtins = isolate_->builtins();
     Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
     if (bailout_type_ == LAZY) {
@@ -1080,10 +1074,9 @@
   }
 }
 
-void Deoptimizer::DoComputeInterpretedFrame(int frame_index,
+void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
+                                            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();
@@ -1110,7 +1103,6 @@
   // The 'fixed' part of the frame consists of the incoming parameters and
   // the part described by InterpreterFrameConstants.
   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.
@@ -1125,18 +1117,11 @@
   CHECK_NULL(output_[frame_index]);
   output_[frame_index] = output_frame;
 
-  // The top address for the bottommost output frame can be computed from
-  // the input frame pointer and the output frame's height.  For all
-  // subsequent output frames, it can be computed from the previous one's
-  // top address and the current frame's size.
-  Register fp_reg = InterpretedFrame::fp_register();
+  // The top address of the frame is computed from the previous frame's top and
+  // this frame's size.
   intptr_t top_address;
   if (is_bottommost) {
-    // Subtract interpreter fixed frame size for the context function slots,
-    // new,target and bytecode offset.
-    top_address = input_->GetRegister(fp_reg.code()) -
-                  InterpreterFrameConstants::kFixedFrameSizeFromFp -
-                  height_in_bytes;
+    top_address = caller_frame_top_ - output_frame_size;
   } else {
     top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
   }
@@ -1144,13 +1129,11 @@
 
   // Compute the incoming parameter translation.
   unsigned output_offset = output_frame_size;
-  unsigned input_offset = input_frame_size;
   for (int i = 0; i < parameter_count; ++i) {
     output_offset -= kPointerSize;
     WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
                                  output_offset);
   }
-  input_offset -= (parameter_count * kPointerSize);
 
   // There are no translation commands for the caller's pc and fp, the
   // context, the function, new.target and the bytecode offset.  Synthesize
@@ -1162,10 +1145,9 @@
   // previous one.  This frame's pc can be computed from the non-optimized
   // function code and AST id of the bailout.
   output_offset -= kPCOnStackSize;
-  input_offset -= kPCOnStackSize;
   intptr_t value;
   if (is_bottommost) {
-    value = input_->GetFrameSlot(input_offset);
+    value = caller_pc_;
   } else {
     value = output_[frame_index - 1]->GetPc();
   }
@@ -1177,31 +1159,27 @@
   // read from the previous one.  Also compute and set this frame's frame
   // pointer.
   output_offset -= kFPOnStackSize;
-  input_offset -= kFPOnStackSize;
   if (is_bottommost) {
-    value = input_->GetFrameSlot(input_offset);
+    value = caller_fp_;
   } else {
     value = output_[frame_index - 1]->GetFp();
   }
   output_frame->SetCallerFp(output_offset, value);
   intptr_t fp_value = top_address + output_offset;
-  DCHECK(!is_bottommost ||
-         (input_->GetRegister(fp_reg.code()) +
-          has_alignment_padding_ * kPointerSize) == fp_value);
   output_frame->SetFp(fp_value);
-  if (is_topmost) output_frame->SetRegister(fp_reg.code(), fp_value);
+  if (is_topmost) {
+    Register fp_reg = InterpretedFrame::fp_register();
+    output_frame->SetRegister(fp_reg.code(), fp_value);
+  }
   DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
-  DCHECK(!is_bottommost || !has_alignment_padding_ ||
-         (fp_value & kPointerSize) != 0);
 
   if (FLAG_enable_embedded_constant_pool) {
     // For the bottommost output frame the constant pool pointer can be gotten
     // from the input frame. For subsequent output frames, it can be read from
     // the previous frame.
     output_offset -= kPointerSize;
-    input_offset -= kPointerSize;
     if (is_bottommost) {
-      value = input_->GetFrameSlot(input_offset);
+      value = caller_constant_pool_;
     } else {
       value = output_[frame_index - 1]->GetConstantPool();
     }
@@ -1215,7 +1193,6 @@
   // so long as we don't inline functions that need local contexts.
   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.
@@ -1243,31 +1220,24 @@
 
   // The function was mentioned explicitly in the BEGIN_FRAME.
   output_offset -= kPointerSize;
-  input_offset -= kPointerSize;
   value = reinterpret_cast<intptr_t>(function);
-  // The function for the bottommost output frame should also agree with the
-  // input frame.
-  DCHECK(!is_bottommost || input_->GetFrameSlot(input_offset) == value);
   WriteValueToOutput(function, 0, frame_index, output_offset, "function    ");
 
   // 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;
   Smi* smi_bytecode_offset = Smi::FromInt(raw_bytecode_offset);
@@ -1317,7 +1287,7 @@
   }
 
   // Set the continuation for the topmost frame.
-  if (is_topmost && bailout_type_ != DEBUGGER) {
+  if (is_topmost) {
     Code* continuation =
         builtins->builtin(Builtins::kInterpreterNotifyDeoptimized);
     if (bailout_type_ == LAZY) {
@@ -1334,11 +1304,10 @@
   }
 }
 
-
-void Deoptimizer::DoComputeArgumentsAdaptorFrame(int frame_index) {
-  TranslatedFrame* translated_frame =
-      &(translated_state_.frames()[frame_index]);
+void Deoptimizer::DoComputeArgumentsAdaptorFrame(
+    TranslatedFrame* translated_frame, int frame_index) {
   TranslatedFrame::iterator value_iterator = translated_frame->begin();
+  bool is_bottommost = (0 == frame_index);
   int input_index = 0;
 
   unsigned height = translated_frame->height();
@@ -1351,7 +1320,7 @@
            "  translating arguments adaptor => height=%d\n", height_in_bytes);
   }
 
-  unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
+  unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFixedFrameSize;
   unsigned output_frame_size = height_in_bytes + fixed_frame_size;
 
   // Allocate and store the output frame description.
@@ -1360,15 +1329,19 @@
       FrameDescription(output_frame_size, parameter_count);
   output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR);
 
-  // Arguments adaptor can not be topmost or bottommost.
-  CHECK(frame_index > 0 && frame_index < output_count_ - 1);
+  // Arguments adaptor can not be topmost.
+  CHECK(frame_index < output_count_ - 1);
   CHECK(output_[frame_index] == NULL);
   output_[frame_index] = output_frame;
 
-  // The top address of the frame is computed from the previous
-  // frame's top and this frame's size.
+  // The top address of the frame is computed from the previous frame's top and
+  // this frame's size.
   intptr_t top_address;
-  top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
+  if (is_bottommost) {
+    top_address = caller_frame_top_ - output_frame_size;
+  } else {
+    top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
+  }
   output_frame->SetTop(top_address);
 
   // Compute the incoming parameter translation.
@@ -1381,13 +1354,22 @@
 
   // Read caller's PC from the previous frame.
   output_offset -= kPCOnStackSize;
-  intptr_t callers_pc = output_[frame_index - 1]->GetPc();
-  output_frame->SetCallerPc(output_offset, callers_pc);
-  DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n");
+  intptr_t value;
+  if (is_bottommost) {
+    value = caller_pc_;
+  } else {
+    value = output_[frame_index - 1]->GetPc();
+  }
+  output_frame->SetCallerPc(output_offset, value);
+  DebugPrintOutputSlot(value, frame_index, output_offset, "caller's pc\n");
 
   // Read caller's FP from the previous frame, and set this frame's FP.
   output_offset -= kFPOnStackSize;
-  intptr_t value = output_[frame_index - 1]->GetFp();
+  if (is_bottommost) {
+    value = caller_fp_;
+  } else {
+    value = output_[frame_index - 1]->GetFp();
+  }
   output_frame->SetCallerFp(output_offset, value);
   intptr_t fp_value = top_address + output_offset;
   output_frame->SetFp(fp_value);
@@ -1396,7 +1378,11 @@
   if (FLAG_enable_embedded_constant_pool) {
     // Read the caller's constant pool from the previous frame.
     output_offset -= kPointerSize;
-    value = output_[frame_index - 1]->GetConstantPool();
+    if (is_bottommost) {
+      value = caller_constant_pool_;
+    } else {
+      value = output_[frame_index - 1]->GetConstantPool();
+    }
     output_frame->SetCallerConstantPool(output_offset, value);
     DebugPrintOutputSlot(value, frame_index, output_offset,
                          "caller's constant_pool\n");
@@ -1440,17 +1426,94 @@
   }
 }
 
+void Deoptimizer::DoComputeTailCallerFrame(TranslatedFrame* translated_frame,
+                                           int frame_index) {
+  SharedFunctionInfo* shared = translated_frame->raw_shared_info();
 
-void Deoptimizer::DoComputeConstructStubFrame(int frame_index) {
-  TranslatedFrame* translated_frame =
-      &(translated_state_.frames()[frame_index]);
+  bool is_bottommost = (0 == frame_index);
+  // Tail caller frame can't be topmost.
+  CHECK_NE(output_count_ - 1, frame_index);
+
+  if (trace_scope_ != NULL) {
+    PrintF(trace_scope_->file(), "  translating tail caller frame ");
+    base::SmartArrayPointer<char> name = shared->DebugName()->ToCString();
+    PrintF(trace_scope_->file(), "%s\n", name.get());
+  }
+
+  if (!is_bottommost) return;
+
+  // Drop arguments adaptor frame below current frame if it exsits.
+  Address fp_address = input_->GetFramePointerAddress();
+  Address adaptor_fp_address =
+      Memory::Address_at(fp_address + CommonFrameConstants::kCallerFPOffset);
+
+  if (Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR) !=
+      Memory::Object_at(adaptor_fp_address +
+                        CommonFrameConstants::kContextOrFrameTypeOffset)) {
+    return;
+  }
+
+  int caller_params_count =
+      Smi::cast(
+          Memory::Object_at(adaptor_fp_address +
+                            ArgumentsAdaptorFrameConstants::kLengthOffset))
+          ->value();
+
+  int callee_params_count =
+      function_->shared()->internal_formal_parameter_count();
+
+  // Both caller and callee parameters count do not include receiver.
+  int offset = (caller_params_count - callee_params_count) * kPointerSize;
+  intptr_t new_stack_fp =
+      reinterpret_cast<intptr_t>(adaptor_fp_address) + offset;
+
+  intptr_t new_caller_frame_top = new_stack_fp +
+                                  (callee_params_count + 1) * kPointerSize +
+                                  CommonFrameConstants::kFixedFrameSizeAboveFp;
+
+  intptr_t adaptor_caller_pc = Memory::intptr_at(
+      adaptor_fp_address + CommonFrameConstants::kCallerPCOffset);
+  intptr_t adaptor_caller_fp = Memory::intptr_at(
+      adaptor_fp_address + CommonFrameConstants::kCallerFPOffset);
+
+  if (trace_scope_ != NULL) {
+    PrintF(trace_scope_->file(),
+           "    dropping caller arguments adaptor frame: offset=%d, "
+           "fp: 0x%08" V8PRIxPTR " -> 0x%08" V8PRIxPTR
+           ", "
+           "caller sp: 0x%08" V8PRIxPTR " -> 0x%08" V8PRIxPTR "\n",
+           offset, stack_fp_, new_stack_fp, caller_frame_top_,
+           new_caller_frame_top);
+  }
+  caller_frame_top_ = new_caller_frame_top;
+  caller_fp_ = adaptor_caller_fp;
+  caller_pc_ = adaptor_caller_pc;
+}
+
+void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
+                                              int frame_index) {
   TranslatedFrame::iterator value_iterator = translated_frame->begin();
+  bool is_topmost = (output_count_ - 1 == frame_index);
+  // The construct frame could become topmost only if we inlined a constructor
+  // call which does a tail call (otherwise the tail callee's frame would be
+  // the topmost one). So it could only be the LAZY case.
+  CHECK(!is_topmost || bailout_type_ == LAZY);
   int input_index = 0;
 
   Builtins* builtins = isolate_->builtins();
   Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
   unsigned height = translated_frame->height();
   unsigned height_in_bytes = height * kPointerSize;
+
+  // If the construct frame appears to be topmost we should ensure that the
+  // value of result register is preserved during continuation execution.
+  // We do this here by "pushing" the result of the constructor function to the
+  // top of the reconstructed stack and then using the
+  // FullCodeGenerator::TOS_REG machinery.
+  if (is_topmost) {
+    height_in_bytes += kPointerSize;
+  }
+
   // Skip function.
   value_iterator++;
   input_index++;
@@ -1459,7 +1522,7 @@
            "  translating construct stub => height=%d\n", height_in_bytes);
   }
 
-  unsigned fixed_frame_size = ConstructFrameConstants::kFrameSize;
+  unsigned fixed_frame_size = ConstructFrameConstants::kFixedFrameSize;
   unsigned output_frame_size = height_in_bytes + fixed_frame_size;
 
   // Allocate and store the output frame description.
@@ -1467,13 +1530,13 @@
       new (output_frame_size) FrameDescription(output_frame_size);
   output_frame->SetFrameType(StackFrame::CONSTRUCT);
 
-  // Construct stub can not be topmost or bottommost.
-  DCHECK(frame_index > 0 && frame_index < output_count_ - 1);
+  // Construct stub can not be topmost.
+  DCHECK(frame_index > 0 && frame_index < output_count_);
   DCHECK(output_[frame_index] == NULL);
   output_[frame_index] = output_frame;
 
-  // The top address of the frame is computed from the previous
-  // frame's top and this frame's size.
+  // The top address of the frame is computed from the previous frame's top and
+  // this frame's size.
   intptr_t top_address;
   top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
   output_frame->SetTop(top_address);
@@ -1503,6 +1566,10 @@
   output_frame->SetCallerFp(output_offset, value);
   intptr_t fp_value = top_address + output_offset;
   output_frame->SetFp(fp_value);
+  if (is_topmost) {
+    Register fp_reg = JavaScriptFrame::fp_register();
+    output_frame->SetRegister(fp_reg.code(), fp_value);
+  }
   DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
 
   if (FLAG_enable_embedded_constant_pool) {
@@ -1514,24 +1581,22 @@
                          "caller's constant_pool\n");
   }
 
-  // The context can be gotten from the previous frame.
-  output_offset -= kPointerSize;
-  value = output_[frame_index - 1]->GetContext();
-  output_frame->SetFrameSlot(output_offset, value);
-  DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
-
-  // A marker value is used in place of the function.
+  // A marker value is used to mark the frame.
   output_offset -= kPointerSize;
   value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT));
   output_frame->SetFrameSlot(output_offset, value);
   DebugPrintOutputSlot(value, frame_index, output_offset,
-                       "function (construct sentinel)\n");
+                       "typed frame marker\n");
 
-  // The output frame reflects a JSConstructStubGeneric frame.
+  // The context can be gotten from the previous frame.
   output_offset -= kPointerSize;
-  value = reinterpret_cast<intptr_t>(construct_stub);
+  value = output_[frame_index - 1]->GetContext();
   output_frame->SetFrameSlot(output_offset, value);
-  DebugPrintOutputSlot(value, frame_index, output_offset, "code object\n");
+  if (is_topmost) {
+    Register context_reg = JavaScriptFrame::context_register();
+    output_frame->SetRegister(context_reg.code(), value);
+  }
+  DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
 
   // The allocation site.
   output_offset -= kPointerSize;
@@ -1556,6 +1621,18 @@
   DebugPrintOutputSlot(value, frame_index, output_offset,
                        "allocated receiver\n");
 
+  if (is_topmost) {
+    // Ensure the result is restored back when we return to the stub.
+    output_offset -= kPointerSize;
+    Register result_reg = FullCodeGenerator::result_register();
+    value = input_->GetRegister(result_reg.code());
+    output_frame->SetFrameSlot(output_offset, value);
+    DebugPrintOutputSlot(value, frame_index, output_offset,
+                         "constructor result\n");
+
+    output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG));
+  }
+
   CHECK_EQ(0u, output_offset);
 
   intptr_t pc = reinterpret_cast<intptr_t>(
@@ -1566,15 +1643,32 @@
     intptr_t constant_pool_value =
         reinterpret_cast<intptr_t>(construct_stub->constant_pool());
     output_frame->SetConstantPool(constant_pool_value);
+    if (is_topmost) {
+      Register constant_pool_reg =
+          JavaScriptFrame::constant_pool_pointer_register();
+      output_frame->SetRegister(constant_pool_reg.code(), fp_value);
+    }
+  }
+
+  // Set the continuation for the topmost frame.
+  if (is_topmost) {
+    Builtins* builtins = isolate_->builtins();
+    DCHECK_EQ(LAZY, bailout_type_);
+    Code* continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
+    output_frame->SetContinuation(
+        reinterpret_cast<intptr_t>(continuation->entry()));
   }
 }
 
-
-void Deoptimizer::DoComputeAccessorStubFrame(int frame_index,
+void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
+                                             int frame_index,
                                              bool is_setter_stub_frame) {
-  TranslatedFrame* translated_frame =
-      &(translated_state_.frames()[frame_index]);
   TranslatedFrame::iterator value_iterator = translated_frame->begin();
+  bool is_topmost = (output_count_ - 1 == frame_index);
+  // The accessor frame could become topmost only if we inlined an accessor
+  // call which does a tail call (otherwise the tail callee's frame would be
+  // the topmost one). So it could only be the LAZY case.
+  CHECK(!is_topmost || bailout_type_ == LAZY);
   int input_index = 0;
 
   // Skip accessor.
@@ -1585,6 +1679,19 @@
   // frame. This means that we have to use a height of 0.
   unsigned height = 0;
   unsigned height_in_bytes = height * kPointerSize;
+
+  // If the accessor frame appears to be topmost we should ensure that the
+  // value of result register is preserved during continuation execution.
+  // We do this here by "pushing" the result of the accessor function to the
+  // top of the reconstructed stack and then using the
+  // FullCodeGenerator::TOS_REG machinery.
+  // We don't need to restore the result in case of a setter call because we
+  // have to return the stored value but not the result of the setter function.
+  bool should_preserve_result = is_topmost && !is_setter_stub_frame;
+  if (should_preserve_result) {
+    height_in_bytes += kPointerSize;
+  }
+
   const char* kind = is_setter_stub_frame ? "setter" : "getter";
   if (trace_scope_ != NULL) {
     PrintF(trace_scope_->file(),
@@ -1592,7 +1699,7 @@
   }
 
   // We need 1 stack entry for the return address and enough entries for the
-  // StackFrame::INTERNAL (FP, context, frame type, code object and constant
+  // StackFrame::INTERNAL (FP, frame type, context, code object and constant
   // pool (if enabled)- see MacroAssembler::EnterFrame).
   // For a setter stub frame we need one additional entry for the implicit
   // return value, see StoreStubCompiler::CompileStoreViaSetter.
@@ -1607,8 +1714,8 @@
       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.
-  CHECK(frame_index > 0 && frame_index < output_count_ - 1);
+  // A frame for an accessor stub can not be bottommost.
+  CHECK(frame_index > 0 && frame_index < output_count_);
   CHECK_NULL(output_[frame_index]);
   output_[frame_index] = output_frame;
 
@@ -1631,6 +1738,10 @@
   output_frame->SetCallerFp(output_offset, value);
   intptr_t fp_value = top_address + output_offset;
   output_frame->SetFp(fp_value);
+  if (is_topmost) {
+    Register fp_reg = JavaScriptFrame::fp_register();
+    output_frame->SetRegister(fp_reg.code(), fp_value);
+  }
   DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
 
   if (FLAG_enable_embedded_constant_pool) {
@@ -1642,17 +1753,11 @@
                          "caller's constant_pool\n");
   }
 
-  // The context can be gotten from the previous frame.
-  output_offset -= kPointerSize;
-  value = output_[frame_index - 1]->GetContext();
-  output_frame->SetFrameSlot(output_offset, value);
-  DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
-
-  // A marker value is used in place of the function.
+  // Set the frame type.
   output_offset -= kPointerSize;
   value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::INTERNAL));
   output_frame->SetFrameSlot(output_offset, value);
-  DebugPrintOutputSlot(value, frame_index, output_offset, "function ");
+  DebugPrintOutputSlot(value, frame_index, output_offset, "frame type ");
   if (trace_scope_ != nullptr) {
     PrintF(trace_scope_->file(), "(%s sentinel)\n", kind);
   }
@@ -1667,6 +1772,16 @@
   output_frame->SetFrameSlot(output_offset, value);
   DebugPrintOutputSlot(value, frame_index, output_offset, "code object\n");
 
+  // The context can be gotten from the previous frame.
+  output_offset -= kPointerSize;
+  value = output_[frame_index - 1]->GetContext();
+  output_frame->SetFrameSlot(output_offset, value);
+  if (is_topmost) {
+    Register context_reg = JavaScriptFrame::context_register();
+    output_frame->SetRegister(context_reg.code(), value);
+  }
+  DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
+
   // Skip receiver.
   value_iterator++;
   input_index++;
@@ -1679,6 +1794,20 @@
                                  output_offset);
   }
 
+  if (should_preserve_result) {
+    // Ensure the result is restored back when we return to the stub.
+    output_offset -= kPointerSize;
+    Register result_reg = FullCodeGenerator::result_register();
+    value = input_->GetRegister(result_reg.code());
+    output_frame->SetFrameSlot(output_offset, value);
+    DebugPrintOutputSlot(value, frame_index, output_offset,
+                         "accessor result\n");
+
+    output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG));
+  } else {
+    output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS));
+  }
+
   CHECK_EQ(0u, output_offset);
 
   Smi* offset = is_setter_stub_frame ?
@@ -1691,11 +1820,25 @@
     intptr_t constant_pool_value =
         reinterpret_cast<intptr_t>(accessor_stub->constant_pool());
     output_frame->SetConstantPool(constant_pool_value);
+    if (is_topmost) {
+      Register constant_pool_reg =
+          JavaScriptFrame::constant_pool_pointer_register();
+      output_frame->SetRegister(constant_pool_reg.code(), fp_value);
+    }
+  }
+
+  // Set the continuation for the topmost frame.
+  if (is_topmost) {
+    Builtins* builtins = isolate_->builtins();
+    DCHECK_EQ(LAZY, bailout_type_);
+    Code* continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
+    output_frame->SetContinuation(
+        reinterpret_cast<intptr_t>(continuation->entry()));
   }
 }
 
-
-void Deoptimizer::DoComputeCompiledStubFrame(int frame_index) {
+void Deoptimizer::DoComputeCompiledStubFrame(TranslatedFrame* translated_frame,
+                                             int frame_index) {
   //
   //               FROM                                  TO
   //    |          ....           |          |          ....           |
@@ -1731,8 +1874,6 @@
   // and then, if the descriptor specifies a constant number of stack
   // parameters, the stack parameters as well.
 
-  TranslatedFrame* translated_frame =
-      &(translated_state_.frames()[frame_index]);
   TranslatedFrame::iterator value_iterator = translated_frame->begin();
   int input_index = 0;
 
@@ -1751,10 +1892,8 @@
   CHECK_EQ(translated_frame->height(), param_count + 1);
   CHECK_GE(param_count, 0);
 
-  int height_in_bytes = kPointerSize * (param_count + stack_param_count) +
-                        sizeof(Arguments) + kPointerSize;
-  int fixed_frame_size = StandardFrameConstants::kFixedFrameSize;
-  int input_frame_size = input_->GetFrameSize();
+  int height_in_bytes = kPointerSize * (param_count + stack_param_count);
+  int fixed_frame_size = StubFailureTrampolineFrameConstants::kFixedFrameSize;
   int output_frame_size = height_in_bytes + fixed_frame_size;
   if (trace_scope_ != NULL) {
     PrintF(trace_scope_->file(),
@@ -1770,28 +1909,24 @@
   CHECK_EQ(frame_index, 0);
   output_[frame_index] = output_frame;
 
-  // The top address for the output frame can be computed from the input
-  // frame pointer and the output frame's height. Subtract space for the
-  // context and function slots.
-  Register fp_reg = StubFailureTrampolineFrame::fp_register();
-  intptr_t top_address = input_->GetRegister(fp_reg.code()) -
-      StandardFrameConstants::kFixedFrameSizeFromFp - height_in_bytes;
+  // The top address of the frame is computed from the previous frame's top and
+  // this frame's size.
+  intptr_t top_address = caller_frame_top_ - output_frame_size;
   output_frame->SetTop(top_address);
 
-  // Read caller's PC (JSFunction continuation) from the input frame.
-  unsigned input_frame_offset = input_frame_size - kPCOnStackSize;
+  // Set caller's PC (JSFunction continuation).
   unsigned output_frame_offset = output_frame_size - kFPOnStackSize;
-  intptr_t value = input_->GetFrameSlot(input_frame_offset);
+  intptr_t value = caller_pc_;
   output_frame->SetCallerPc(output_frame_offset, value);
   DebugPrintOutputSlot(value, frame_index, output_frame_offset,
                        "caller's pc\n");
 
   // Read caller's FP from the input frame, and set this frame's FP.
-  input_frame_offset -= kFPOnStackSize;
-  value = input_->GetFrameSlot(input_frame_offset);
+  value = caller_fp_;
   output_frame_offset -= kFPOnStackSize;
   output_frame->SetCallerFp(output_frame_offset, value);
-  intptr_t frame_ptr = input_->GetRegister(fp_reg.code());
+  intptr_t frame_ptr = top_address + output_frame_offset;
+  Register fp_reg = StubFailureTrampolineFrame::fp_register();
   output_frame->SetRegister(fp_reg.code(), frame_ptr);
   output_frame->SetFp(frame_ptr);
   DebugPrintOutputSlot(value, frame_index, output_frame_offset,
@@ -1799,20 +1934,14 @@
 
   if (FLAG_enable_embedded_constant_pool) {
     // Read the caller's constant pool from the input frame.
-    input_frame_offset -= kPointerSize;
-    value = input_->GetFrameSlot(input_frame_offset);
+    value = caller_constant_pool_;
     output_frame_offset -= kPointerSize;
     output_frame->SetCallerConstantPool(output_frame_offset, value);
     DebugPrintOutputSlot(value, frame_index, output_frame_offset,
                          "caller's constant_pool\n");
   }
 
-  // Remember where the context will need to be written back from the deopt
-  // translation.
-  output_frame_offset -= kPointerSize;
-  unsigned context_frame_offset = output_frame_offset;
-
-  // A marker value is used in place of the function.
+  // The marker for the typed stack frame
   output_frame_offset -= kPointerSize;
   value = reinterpret_cast<intptr_t>(
       Smi::FromInt(StackFrame::STUB_FAILURE_TRAMPOLINE));
@@ -1873,8 +2002,6 @@
   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
@@ -1942,14 +2069,13 @@
 
 
 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
-  DCHECK_NE(DEBUGGER, bailout_type_);
-
   // Walk to the last JavaScript output frame to find out if it has
   // adapted arguments.
   for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
     if (frame_index != 0) it->Advance();
   }
-  translated_state_.Prepare(it->frame()->has_adapted_arguments(), stack_fp_);
+  translated_state_.Prepare(it->frame()->has_adapted_arguments(),
+                            reinterpret_cast<Address>(stack_fp_));
 
   for (auto& materialization : values_to_materialize_) {
     Handle<Object> value = materialization.value_->GetValue();
@@ -1966,7 +2092,8 @@
         reinterpret_cast<intptr_t>(*value);
   }
 
-  isolate_->materialized_object_store()->Remove(stack_fp_);
+  isolate_->materialized_object_store()->Remove(
+      reinterpret_cast<Address>(stack_fp_));
 }
 
 
@@ -2024,25 +2151,26 @@
   }
 }
 
-
-unsigned Deoptimizer::ComputeInputFrameSize() const {
-  unsigned fixed_size = StandardFrameConstants::kFixedFrameSize;
+unsigned Deoptimizer::ComputeInputFrameAboveFpFixedSize() const {
+  unsigned fixed_size = CommonFrameConstants::kFixedFrameSizeAboveFp;
   if (!function_->IsSmi()) {
     fixed_size += ComputeIncomingArgumentSize(function_->shared());
-  } else {
-    CHECK_EQ(Smi::cast(function_), Smi::FromInt(StackFrame::STUB));
   }
+  return fixed_size;
+}
+
+unsigned Deoptimizer::ComputeInputFrameSize() const {
   // 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_ -
-                    StandardFrameConstants::kFixedFrameSizeFromFp;
+  unsigned fixed_size_above_fp = ComputeInputFrameAboveFpFixedSize();
+  unsigned result = fixed_size_above_fp + fp_to_sp_delta_;
   if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
     unsigned stack_slots = compiled_code_->stack_slots();
     unsigned outgoing_size =
         ComputeOutgoingArgumentSize(compiled_code_, bailout_id_);
-    CHECK(result ==
-          fixed_size + (stack_slots * kPointerSize) -
-              StandardFrameConstants::kFixedFrameSize + outgoing_size);
+    CHECK_EQ(fixed_size_above_fp + (stack_slots * kPointerSize) -
+                 CommonFrameConstants::kFixedFrameSizeAboveFp + outgoing_size,
+             result);
   }
   return result;
 }
@@ -2240,6 +2368,10 @@
   buffer_->Add(height, zone());
 }
 
+void Translation::BeginTailCallerFrame(int literal_id) {
+  buffer_->Add(TAIL_CALLER_FRAME, zone());
+  buffer_->Add(literal_id, zone());
+}
 
 void Translation::BeginJSFrame(BailoutId node_id,
                                int literal_id,
@@ -2362,7 +2494,7 @@
 
 void Translation::StoreJSFrameFunction() {
   StoreStackSlot((StandardFrameConstants::kCallerPCOffset -
-                  StandardFrameConstants::kMarkerOffset) /
+                  StandardFrameConstants::kFunctionOffset) /
                  kPointerSize);
 }
 
@@ -2385,6 +2517,7 @@
     case DOUBLE_STACK_SLOT:
     case LITERAL:
     case COMPILED_STUB_FRAME:
+    case TAIL_CALLER_FRAME:
       return 1;
     case BEGIN:
     case ARGUMENTS_ADAPTOR_FRAME:
@@ -2510,7 +2643,9 @@
                           BailoutId node_id) {
   if (shared->HasBytecodeArray()) {
     BytecodeArray* bytecodes = shared->bytecode_array();
-    return bytecodes->SourcePosition(node_id.ToInt());
+    // BailoutId points to the next bytecode in the bytecode aray. Subtract
+    // 1 to get the end of current bytecode.
+    return bytecodes->SourcePosition(node_id.ToInt() - 1);
   } else {
     Code* non_optimized_code = shared->code();
     FixedArray* raw_data = non_optimized_code->deoptimization_data();
@@ -2942,6 +3077,11 @@
                          shared_info, height);
 }
 
+TranslatedFrame TranslatedFrame::TailCallerFrame(
+    SharedFunctionInfo* shared_info) {
+  return TranslatedFrame(kTailCallerFunction, shared_info->GetIsolate(),
+                         shared_info, 0);
+}
 
 TranslatedFrame TranslatedFrame::ConstructStubFrame(
     SharedFunctionInfo* shared_info, int height) {
@@ -2976,6 +3116,9 @@
     case kConstructStub:
       return 1 + height_;
 
+    case kTailCallerFunction:
+      return 1;  // Function.
+
     case kCompiledStub:
       return height_;
 
@@ -3052,6 +3195,18 @@
       return TranslatedFrame::ArgumentsAdaptorFrame(shared_info, height);
     }
 
+    case Translation::TAIL_CALLER_FRAME: {
+      SharedFunctionInfo* shared_info =
+          SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
+      if (trace_file != nullptr) {
+        base::SmartArrayPointer<char> name =
+            shared_info->DebugName()->ToCString();
+        PrintF(trace_file, "  reading tail caller frame marker %s\n",
+               name.get());
+      }
+      return TranslatedFrame::TailCallerFrame(shared_info);
+    }
+
     case Translation::CONSTRUCT_STUB_FRAME: {
       SharedFunctionInfo* shared_info =
           SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
@@ -3152,6 +3307,7 @@
     case Translation::JS_FRAME:
     case Translation::INTERPRETED_FRAME:
     case Translation::ARGUMENTS_ADAPTOR_FRAME:
+    case Translation::TAIL_CALLER_FRAME:
     case Translation::CONSTRUCT_STUB_FRAME:
     case Translation::GETTER_STUB_FRAME:
     case Translation::SETTER_STUB_FRAME:
@@ -3725,7 +3881,8 @@
     materialized_store->Set(stack_frame_pointer_,
                             previously_materialized_objects);
     CHECK(frames_[0].kind() == TranslatedFrame::kFunction ||
-          frames_[0].kind() == TranslatedFrame::kInterpretedFunction);
+          frames_[0].kind() == TranslatedFrame::kInterpretedFunction ||
+          frames_[0].kind() == TranslatedFrame::kTailCallerFunction);
     Object* const function = frames_[0].front().GetRawValue();
     Deoptimizer::DeoptimizeFunction(JSFunction::cast(function));
   }