Commit c712ecfd authored by vegorov@chromium.org's avatar vegorov@chromium.org

MIPS: Support inlining at call-sites with mismatched number of arguments.

Port r10483 (8785a3ef)

BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/9271068
Patch from Daniel Kalmar <kalmard@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10512 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d6f476dd
...@@ -1800,6 +1800,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ...@@ -1800,6 +1800,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
__ Call(a3); __ Call(a3);
masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
// Exit frame and return. // Exit frame and return.
LeaveArgumentsAdaptorFrame(masm); LeaveArgumentsAdaptorFrame(masm);
__ Ret(); __ Ret();
......
...@@ -218,12 +218,13 @@ void Deoptimizer::DoComputeOsrOutputFrame() { ...@@ -218,12 +218,13 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
ASSERT(Translation::BEGIN == opcode); ASSERT(Translation::BEGIN == opcode);
USE(opcode); USE(opcode);
int count = iterator.Next(); int count = iterator.Next();
iterator.Skip(1); // Drop JS frame count.
ASSERT(count == 1); ASSERT(count == 1);
USE(count); USE(count);
opcode = static_cast<Translation::Opcode>(iterator.Next()); opcode = static_cast<Translation::Opcode>(iterator.Next());
USE(opcode); USE(opcode);
ASSERT(Translation::FRAME == opcode); ASSERT(Translation::JS_FRAME == opcode);
unsigned node_id = iterator.Next(); unsigned node_id = iterator.Next();
USE(node_id); USE(node_id);
ASSERT(node_id == ast_id); ASSERT(node_id == ast_id);
...@@ -259,9 +260,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() { ...@@ -259,9 +260,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
output_ = new FrameDescription*[1]; output_ = new FrameDescription*[1];
output_[0] = new(output_frame_size) FrameDescription( output_[0] = new(output_frame_size) FrameDescription(
output_frame_size, function_); output_frame_size, function_);
#ifdef DEBUG output_[0]->SetFrameType(StackFrame::JAVA_SCRIPT);
output_[0]->SetKind(Code::OPTIMIZED_FUNCTION);
#endif
// Clear the incoming parameters in the optimized frame to avoid // Clear the incoming parameters in the optimized frame to avoid
// confusing the garbage collector. // confusing the garbage collector.
...@@ -349,15 +348,115 @@ void Deoptimizer::DoComputeOsrOutputFrame() { ...@@ -349,15 +348,115 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
} }
void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
int frame_index) {
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
unsigned height = iterator->Next();
unsigned height_in_bytes = height * kPointerSize;
if (FLAG_trace_deopt) {
PrintF(" translating arguments adaptor => height=%d\n", height_in_bytes);
}
unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
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);
output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR);
// Arguments adaptor can not be topmost or bottommost.
ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
ASSERT(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.
uint32_t top_address;
top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
output_frame->SetTop(top_address);
// Compute the incoming parameter translation.
int parameter_count = height;
unsigned output_offset = output_frame_size;
unsigned input_offset = input_frame_size;
for (int i = 0; i < parameter_count; ++i) {
output_offset -= kPointerSize;
DoTranslateCommand(iterator, frame_index, output_offset);
}
input_offset -= (parameter_count * kPointerSize);
// Read caller's PC from the previous frame.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
intptr_t callers_pc = output_[frame_index - 1]->GetPc();
output_frame->SetFrameSlot(output_offset, callers_pc);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's pc\n",
top_address + output_offset, output_offset, callers_pc);
}
// Read caller's FP from the previous frame, and set this frame's FP.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
intptr_t value = output_[frame_index - 1]->GetFp();
output_frame->SetFrameSlot(output_offset, value);
intptr_t fp_value = top_address + output_offset;
output_frame->SetFp(fp_value);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n",
fp_value, output_offset, value);
}
// A marker value is used in place of the context.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
intptr_t context = reinterpret_cast<intptr_t>(
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
output_frame->SetFrameSlot(output_offset, context);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context (adaptor sentinel)\n",
top_address + output_offset, output_offset, context);
}
// The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
value = reinterpret_cast<intptr_t>(function);
output_frame->SetFrameSlot(output_offset, value);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function\n",
top_address + output_offset, output_offset, value);
}
// Number of incoming arguments.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1));
output_frame->SetFrameSlot(output_offset, value);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; argc (%d)\n",
top_address + output_offset, output_offset, value, height - 1);
}
ASSERT(0 == output_offset);
Builtins* builtins = isolate_->builtins();
Code* adaptor_trampoline =
builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
uint32_t pc = reinterpret_cast<uint32_t>(
adaptor_trampoline->instruction_start() +
isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
output_frame->SetPc(pc);
}
// This code is very similar to ia32/arm code, but relies on register names // This code is very similar to ia32/arm code, but relies on register names
// (fp, sp) and how the frame is laid out. // (fp, sp) and how the frame is laid out.
void Deoptimizer::DoComputeFrame(TranslationIterator* iterator, void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
int frame_index) { int frame_index) {
// Read the ast node id, function, and frame height for this output frame. // Read the ast node id, function, and frame height for this output frame.
Translation::Opcode opcode =
static_cast<Translation::Opcode>(iterator->Next());
USE(opcode);
ASSERT(Translation::FRAME == opcode);
int node_id = iterator->Next(); int node_id = iterator->Next();
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
unsigned height = iterator->Next(); unsigned height = iterator->Next();
...@@ -377,9 +476,7 @@ void Deoptimizer::DoComputeFrame(TranslationIterator* iterator, ...@@ -377,9 +476,7 @@ void Deoptimizer::DoComputeFrame(TranslationIterator* iterator,
// Allocate and store the output frame description. // Allocate and store the output frame description.
FrameDescription* output_frame = FrameDescription* output_frame =
new(output_frame_size) FrameDescription(output_frame_size, function); new(output_frame_size) FrameDescription(output_frame_size, function);
#ifdef DEBUG output_frame->SetFrameType(StackFrame::JAVA_SCRIPT);
output_frame->SetKind(Code::FUNCTION);
#endif
bool is_bottommost = (0 == frame_index); bool is_bottommost = (0 == frame_index);
bool is_topmost = (output_count_ - 1 == frame_index); bool is_topmost = (output_count_ - 1 == frame_index);
......
...@@ -195,6 +195,9 @@ class ExitFrameConstants : public AllStatic { ...@@ -195,6 +195,9 @@ class ExitFrameConstants : public AllStatic {
class StandardFrameConstants : public AllStatic { class StandardFrameConstants : public AllStatic {
public: public:
// Fixed part of the frame consists of return address, caller fp,
// context and function.
static const int kFixedFrameSize = 4 * kPointerSize;
static const int kExpressionsOffset = -3 * kPointerSize; static const int kExpressionsOffset = -3 * kPointerSize;
static const int kMarkerOffset = -2 * kPointerSize; static const int kMarkerOffset = -2 * kPointerSize;
static const int kContextOffset = -1 * kPointerSize; static const int kContextOffset = -1 * kPointerSize;
...@@ -230,6 +233,8 @@ class JavaScriptFrameConstants : public AllStatic { ...@@ -230,6 +233,8 @@ class JavaScriptFrameConstants : public AllStatic {
class ArgumentsAdaptorFrameConstants : public AllStatic { class ArgumentsAdaptorFrameConstants : public AllStatic {
public: public:
static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset; static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
static const int kFrameSize =
StandardFrameConstants::kFixedFrameSize + kPointerSize;
}; };
......
...@@ -447,7 +447,11 @@ void LCodeGen::WriteTranslation(LEnvironment* environment, ...@@ -447,7 +447,11 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
WriteTranslation(environment->outer(), translation); WriteTranslation(environment->outer(), translation);
int closure_id = DefineDeoptimizationLiteral(environment->closure()); int closure_id = DefineDeoptimizationLiteral(environment->closure());
translation->BeginFrame(environment->ast_id(), closure_id, height); if (environment->is_arguments_adaptor()) {
translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
} else {
translation->BeginJSFrame(environment->ast_id(), closure_id, height);
}
for (int i = 0; i < translation_size; ++i) { for (int i = 0; i < translation_size; ++i) {
LOperand* value = environment->values()->at(i); LOperand* value = environment->values()->at(i);
// spilled_registers_ and spilled_double_registers_ are either // spilled_registers_ and spilled_double_registers_ are either
...@@ -573,10 +577,14 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, ...@@ -573,10 +577,14 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
// |>------------ translation_size ------------<| // |>------------ translation_size ------------<|
int frame_count = 0; int frame_count = 0;
int jsframe_count = 0;
for (LEnvironment* e = environment; e != NULL; e = e->outer()) { for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
++frame_count; ++frame_count;
if (!e->is_arguments_adaptor()) {
++jsframe_count;
}
} }
Translation translation(&translations_, frame_count); Translation translation(&translations_, frame_count, jsframe_count);
WriteTranslation(environment, &translation); WriteTranslation(environment, &translation);
int deoptimization_index = deoptimizations_.length(); int deoptimization_index = deoptimizations_.length();
int pc_offset = masm()->pc_offset(); int pc_offset = masm()->pc_offset();
......
...@@ -1005,14 +1005,16 @@ LEnvironment* LChunkBuilder::CreateEnvironment( ...@@ -1005,14 +1005,16 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
LEnvironment* outer = LEnvironment* outer =
CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator); CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
int ast_id = hydrogen_env->ast_id(); int ast_id = hydrogen_env->ast_id();
ASSERT(ast_id != AstNode::kNoNumber); ASSERT(ast_id != AstNode::kNoNumber || hydrogen_env->is_arguments_adaptor());
int value_count = hydrogen_env->length(); int value_count = hydrogen_env->length();
LEnvironment* result = new LEnvironment(hydrogen_env->closure(), LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
hydrogen_env->is_arguments_adaptor(),
ast_id, ast_id,
hydrogen_env->parameter_count(), hydrogen_env->parameter_count(),
argument_count_, argument_count_,
value_count, value_count,
outer); outer);
int argument_index = *argument_index_accumulator;
for (int i = 0; i < value_count; ++i) { for (int i = 0; i < value_count; ++i) {
if (hydrogen_env->is_special_index(i)) continue; if (hydrogen_env->is_special_index(i)) continue;
...@@ -1021,13 +1023,17 @@ LEnvironment* LChunkBuilder::CreateEnvironment( ...@@ -1021,13 +1023,17 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
if (value->IsArgumentsObject()) { if (value->IsArgumentsObject()) {
op = NULL; op = NULL;
} else if (value->IsPushArgument()) { } else if (value->IsPushArgument()) {
op = new LArgument((*argument_index_accumulator)++); op = new LArgument(argument_index++);
} else { } else {
op = UseAny(value); op = UseAny(value);
} }
result->AddValue(op, value->representation()); result->AddValue(op, value->representation());
} }
if (!hydrogen_env->is_arguments_adaptor()) {
*argument_index_accumulator = argument_index;
}
return result; return result;
} }
...@@ -2247,6 +2253,7 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) { ...@@ -2247,6 +2253,7 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
HEnvironment* outer = current_block_->last_environment(); HEnvironment* outer = current_block_->last_environment();
HConstant* undefined = graph()->GetConstantUndefined(); HConstant* undefined = graph()->GetConstantUndefined();
HEnvironment* inner = outer->CopyForInlining(instr->closure(), HEnvironment* inner = outer->CopyForInlining(instr->closure(),
instr->arguments_count(),
instr->function(), instr->function(),
undefined, undefined,
instr->call_kind()); instr->call_kind());
...@@ -2257,7 +2264,8 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) { ...@@ -2257,7 +2264,8 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
HEnvironment* outer = current_block_->last_environment()->outer(); HEnvironment* outer = current_block_->last_environment()->
DiscardInlined(false);
current_block_->UpdateEnvironment(outer); current_block_->UpdateEnvironment(outer);
return NULL; return NULL;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment