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));
}