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