Land Kevin's patch for supporting %_CallFunction in Crankshaft.

Original code review: http://codereview.chromium.org/6838018/

TBR=ager@chromium.org
Review URL: http://codereview.chromium.org/6869005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7624 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
fschneider@chromium.org 2011-04-15 07:58:22 +00:00
parent 348501ae01
commit ef24af119e
18 changed files with 228 additions and 48 deletions

View File

@ -3161,15 +3161,14 @@ void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
ASSERT(args->length() >= 2);
int arg_count = args->length() - 2; // For receiver and function.
VisitForStackValue(args->at(0)); // Receiver.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i + 1));
int arg_count = args->length() - 2; // 2 ~ receiver and function.
for (int i = 0; i < arg_count + 1; i++) {
VisitForStackValue(args->at(i));
}
VisitForAccumulatorValue(args->at(arg_count + 1)); // Function.
VisitForAccumulatorValue(args->last()); // Function.
// InvokeFunction requires function in r1. Move it in there.
if (!result_register().is(r1)) __ mov(r1, result_register());
// InvokeFunction requires the function in r1. Move it in there.
__ mov(r1, result_register());
ParameterCount count(arg_count);
__ InvokeFunction(r1, count, CALL_FUNCTION);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));

View File

@ -300,6 +300,13 @@ void LStoreContextSlot::PrintDataTo(StringStream* stream) {
}
void LInvokeFunction::PrintDataTo(StringStream* stream) {
stream->Add("= ");
InputAt(0)->PrintTo(stream);
stream->Add(" #%d / ", arity());
}
void LCallKeyed::PrintDataTo(StringStream* stream) {
stream->Add("[r2] #%d / ", arity());
}
@ -1211,6 +1218,14 @@ LInstruction* LChunkBuilder::DoCallConstantFunction(
}
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
LOperand* function = UseFixed(instr->function(), r1);
argument_count_ -= instr->argument_count();
LInvokeFunction* result = new LInvokeFunction(function);
return MarkAsCall(DefineFixed(result, r0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
}
LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
BuiltinFunctionId op = instr->op();
if (op == kMathLog || op == kMathSin || op == kMathCos) {

View File

@ -106,6 +106,7 @@ class LCodeGen;
V(InstanceOfAndBranch) \
V(InstanceOfKnownGlobal) \
V(Integer32ToDouble) \
V(InvokeFunction) \
V(IsNull) \
V(IsNullAndBranch) \
V(IsObject) \
@ -1413,6 +1414,23 @@ class LCallConstantFunction: public LTemplateInstruction<1, 0, 0> {
};
class LInvokeFunction: public LTemplateInstruction<1, 1, 0> {
public:
LInvokeFunction(LOperand* function) {
inputs_[0] = function;
}
DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
LOperand* function() { return inputs_[0]; }
virtual void PrintDataTo(StringStream* stream);
int arity() const { return hydrogen()->argument_count() - 1; }
};
class LCallKeyed: public LTemplateInstruction<1, 1, 0> {
public:
explicit LCallKeyed(LOperand* key) {

View File

@ -91,7 +91,7 @@ bool LCodeGen::GenerateCode() {
void LCodeGen::FinishCode(Handle<Code> code) {
ASSERT(is_done());
code->set_stack_slots(StackSlotCount());
code->set_stack_slots(GetStackSlotCount());
code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
PopulateDeoptimizationData(code);
Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
@ -149,7 +149,7 @@ bool LCodeGen::GeneratePrologue() {
__ add(fp, sp, Operand(2 * kPointerSize)); // Adjust FP to point to saved FP.
// Reserve space for the stack slots needed by the code.
int slots = StackSlotCount();
int slots = GetStackSlotCount();
if (slots > 0) {
if (FLAG_debug_code) {
__ mov(r0, Operand(slots));
@ -263,7 +263,7 @@ bool LCodeGen::GenerateDeferredCode() {
bool LCodeGen::GenerateSafepointTable() {
ASSERT(is_done());
safepoints_.Emit(masm(), StackSlotCount());
safepoints_.Emit(masm(), GetStackSlotCount());
return !is_aborted();
}
@ -459,7 +459,7 @@ void LCodeGen::AddToTranslation(Translation* translation,
translation->StoreDoubleStackSlot(op->index());
} else if (op->IsArgument()) {
ASSERT(is_tagged);
int src_index = StackSlotCount() + op->index();
int src_index = GetStackSlotCount() + op->index();
translation->StoreStackSlot(src_index);
} else if (op->IsRegister()) {
Register reg = ToRegister(op);
@ -2180,7 +2180,7 @@ void LCodeGen::DoReturn(LReturn* instr) {
__ push(r0);
__ CallRuntime(Runtime::kTraceExit, 1);
}
int32_t sp_delta = (ParameterCount() + 1) * kPointerSize;
int32_t sp_delta = (GetParameterCount() + 1) * kPointerSize;
__ mov(sp, fp);
__ ldm(ia_w, sp, fp.bit() | lr.bit());
__ add(sp, sp, Operand(sp_delta));
@ -3025,6 +3025,21 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
}
void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
ASSERT(ToRegister(instr->function()).is(r1));
ASSERT(instr->HasPointerMap());
ASSERT(instr->HasDeoptimizationEnvironment());
LPointerMap* pointers = instr->pointer_map();
LEnvironment* env = instr->deoptimization_environment();
RecordPosition(pointers->position());
RegisterEnvironmentForDeoptimization(env);
SafepointGenerator generator(this, pointers, env->deoptimization_index());
ParameterCount count(instr->arity());
__ InvokeFunction(r1, count, CALL_FUNCTION, &generator);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
}
void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
ASSERT(ToRegister(instr->result()).is(r0));

View File

@ -158,8 +158,8 @@ class LCodeGen BASE_EMBEDDED {
Register temporary,
Register temporary2);
int StackSlotCount() const { return chunk()->spill_slot_count(); }
int ParameterCount() const { return scope()->num_parameters(); }
int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
int GetParameterCount() const { return scope()->num_parameters(); }
void Abort(const char* format, ...);
void Comment(const char* format, ...);

View File

@ -114,6 +114,7 @@ class LChunkBuilder;
V(HasCachedArrayIndex) \
V(InstanceOf) \
V(InstanceOfKnownGlobal) \
V(InvokeFunction) \
V(IsNull) \
V(IsObject) \
V(IsSmi) \
@ -1244,6 +1245,23 @@ class HBinaryCall: public HCall<2> {
};
class HInvokeFunction: public HBinaryCall {
public:
HInvokeFunction(HValue* context, HValue* function, int argument_count)
: HBinaryCall(context, function, argument_count) {
}
virtual Representation RequiredInputRepresentation(int index) const {
return Representation::Tagged();
}
HValue* context() { return first(); }
HValue* function() { return second(); }
DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke_function")
};
class HCallConstantFunction: public HCall<0> {
public:
HCallConstantFunction(Handle<JSFunction> function, int argument_count)

View File

@ -5540,7 +5540,21 @@ void HGraphBuilder::GenerateSwapElements(CallRuntime* call) {
// Fast call for custom callbacks.
void HGraphBuilder::GenerateCallFunction(CallRuntime* call) {
return Bailout("inlined runtime function: CallFunction");
// 1 ~ The function to call is not itself an argument to the call.
int arg_count = call->arguments()->length() - 1;
ASSERT(arg_count >= 1); // There's always at least a receiver.
for (int i = 0; i < arg_count; ++i) {
CHECK_ALIVE(VisitArgument(call->arguments()->at(i)));
}
CHECK_ALIVE(VisitForValue(call->arguments()->last()));
HValue* function = Pop();
HContext* context = new HContext;
AddInstruction(context);
HInvokeFunction* result =
new(zone()) HInvokeFunction(context, function, arg_count);
Drop(arg_count);
ast_context()->ReturnInstruction(result, call->id());
}

View File

@ -3087,15 +3087,14 @@ void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
ASSERT(args->length() >= 2);
int arg_count = args->length() - 2; // For receiver and function.
VisitForStackValue(args->at(0)); // Receiver.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i + 1));
int arg_count = args->length() - 2; // 2 ~ receiver and function.
for (int i = 0; i < arg_count + 1; ++i) {
VisitForStackValue(args->at(i));
}
VisitForAccumulatorValue(args->at(arg_count + 1)); // Function.
VisitForAccumulatorValue(args->last()); // Function.
// InvokeFunction requires function in edi. Move it in there.
if (!result_register().is(edi)) __ mov(edi, result_register());
// InvokeFunction requires the function in edi. Move it in there.
__ mov(edi, result_register());
ParameterCount count(arg_count);
__ InvokeFunction(edi, count, CALL_FUNCTION);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));

View File

@ -77,7 +77,7 @@ bool LCodeGen::GenerateCode() {
void LCodeGen::FinishCode(Handle<Code> code) {
ASSERT(is_done());
code->set_stack_slots(StackSlotCount());
code->set_stack_slots(GetStackSlotCount());
code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
PopulateDeoptimizationData(code);
Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
@ -132,7 +132,7 @@ bool LCodeGen::GeneratePrologue() {
__ push(edi); // Callee's JS function.
// Reserve space for the stack slots needed by the code.
int slots = StackSlotCount();
int slots = GetStackSlotCount();
if (slots > 0) {
if (FLAG_debug_code) {
__ mov(Operand(eax), Immediate(slots));
@ -254,7 +254,7 @@ bool LCodeGen::GenerateDeferredCode() {
bool LCodeGen::GenerateSafepointTable() {
ASSERT(is_done());
safepoints_.Emit(masm(), StackSlotCount());
safepoints_.Emit(masm(), GetStackSlotCount());
return !is_aborted();
}
@ -386,7 +386,7 @@ void LCodeGen::AddToTranslation(Translation* translation,
translation->StoreDoubleStackSlot(op->index());
} else if (op->IsArgument()) {
ASSERT(is_tagged);
int src_index = StackSlotCount() + op->index();
int src_index = GetStackSlotCount() + op->index();
translation->StoreStackSlot(src_index);
} else if (op->IsRegister()) {
Register reg = ToRegister(op);
@ -2057,7 +2057,7 @@ void LCodeGen::DoReturn(LReturn* instr) {
}
__ mov(esp, ebp);
__ pop(ebp);
__ Ret((ParameterCount() + 1) * kPointerSize, ecx);
__ Ret((GetParameterCount() + 1) * kPointerSize, ecx);
}
@ -2493,7 +2493,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
SafepointGenerator safepoint_generator(this,
pointers,
env->deoptimization_index());
v8::internal::ParameterCount actual(eax);
ParameterCount actual(eax);
__ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
}
@ -2905,6 +2905,21 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
}
void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->function()).is(edi));
ASSERT(instr->HasPointerMap());
ASSERT(instr->HasDeoptimizationEnvironment());
LPointerMap* pointers = instr->pointer_map();
LEnvironment* env = instr->deoptimization_environment();
RecordPosition(pointers->position());
RegisterEnvironmentForDeoptimization(env);
SafepointGenerator generator(this, pointers, env->deoptimization_index());
ParameterCount count(instr->arity());
__ InvokeFunction(edi, count, CALL_FUNCTION, &generator);
}
void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->key()).is(ecx));

View File

@ -147,8 +147,8 @@ class LCodeGen BASE_EMBEDDED {
Register temporary,
Register temporary2);
int StackSlotCount() const { return chunk()->spill_slot_count(); }
int ParameterCount() const { return scope()->num_parameters(); }
int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
int GetParameterCount() const { return scope()->num_parameters(); }
void Abort(const char* format, ...);
void Comment(const char* format, ...);

View File

@ -302,6 +302,15 @@ void LStoreContextSlot::PrintDataTo(StringStream* stream) {
}
void LInvokeFunction::PrintDataTo(StringStream* stream) {
stream->Add("= ");
InputAt(0)->PrintTo(stream);
stream->Add(" ");
InputAt(1)->PrintTo(stream);
stream->Add(" #%d / ", arity());
}
void LCallKeyed::PrintDataTo(StringStream* stream) {
stream->Add("[ecx] #%d / ", arity());
}
@ -1221,6 +1230,15 @@ LInstruction* LChunkBuilder::DoCallConstantFunction(
}
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
LOperand* context = UseFixed(instr->context(), esi);
LOperand* function = UseFixed(instr->function(), edi);
argument_count_ -= instr->argument_count();
LInvokeFunction* result = new LInvokeFunction(context, function);
return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
}
LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
BuiltinFunctionId op = instr->op();
if (op == kMathLog) {

View File

@ -107,6 +107,7 @@ class LCodeGen;
V(InstanceOfAndBranch) \
V(InstanceOfKnownGlobal) \
V(Integer32ToDouble) \
V(InvokeFunction) \
V(IsNull) \
V(IsNullAndBranch) \
V(IsObject) \
@ -1452,6 +1453,25 @@ class LCallConstantFunction: public LTemplateInstruction<1, 0, 0> {
};
class LInvokeFunction: public LTemplateInstruction<1, 2, 0> {
public:
LInvokeFunction(LOperand* context, LOperand* function) {
inputs_[0] = context;
inputs_[1] = function;
}
DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
LOperand* context() { return inputs_[0]; }
LOperand* function() { return inputs_[1]; }
virtual void PrintDataTo(StringStream* stream);
int arity() const { return hydrogen()->argument_count() - 1; }
};
class LCallKeyed: public LTemplateInstruction<1, 2, 0> {
public:
LCallKeyed(LOperand* context, LOperand* key) {

View File

@ -1,4 +1,4 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -153,6 +153,7 @@ void RuntimeProfiler::Optimize(JSFunction* function, bool eager, int delay) {
if (FLAG_trace_opt) {
PrintF("[marking (%s) ", eager ? "eagerly" : "lazily");
function->PrintName();
PrintF(" 0x%" V8PRIxPTR, reinterpret_cast<intptr_t>(function->address()));
PrintF(" for recompilation");
if (delay > 0) {
PrintF(" (delayed %0.3f ms)", static_cast<double>(delay) / 1000);

View File

@ -3043,15 +3043,14 @@ void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
ASSERT(args->length() >= 2);
int arg_count = args->length() - 2; // For receiver and function.
VisitForStackValue(args->at(0)); // Receiver.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i + 1));
int arg_count = args->length() - 2; // 2 ~ receiver and function.
for (int i = 0; i < arg_count + 1; i++) {
VisitForStackValue(args->at(i));
}
VisitForAccumulatorValue(args->at(arg_count + 1)); // Function.
VisitForAccumulatorValue(args->last()); // Function.
// InvokeFunction requires function in rdi. Move it in there.
if (!result_register().is(rdi)) __ movq(rdi, result_register());
// InvokeFunction requires the function in rdi. Move it in there.
__ movq(rdi, result_register());
ParameterCount count(arg_count);
__ InvokeFunction(rdi, count, CALL_FUNCTION);
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));

View File

@ -91,7 +91,7 @@ bool LCodeGen::GenerateCode() {
void LCodeGen::FinishCode(Handle<Code> code) {
ASSERT(is_done());
code->set_stack_slots(StackSlotCount());
code->set_stack_slots(GetStackSlotCount());
code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
PopulateDeoptimizationData(code);
Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
@ -146,7 +146,7 @@ bool LCodeGen::GeneratePrologue() {
__ push(rdi); // Callee's JS function.
// Reserve space for the stack slots needed by the code.
int slots = StackSlotCount();
int slots = GetStackSlotCount();
if (slots > 0) {
if (FLAG_debug_code) {
__ Set(rax, slots);
@ -290,7 +290,7 @@ bool LCodeGen::GenerateSafepointTable() {
while (byte_count-- > 0) {
__ int3();
}
safepoints_.Emit(masm(), StackSlotCount());
safepoints_.Emit(masm(), GetStackSlotCount());
return !is_aborted();
}
@ -418,7 +418,7 @@ void LCodeGen::AddToTranslation(Translation* translation,
translation->StoreDoubleStackSlot(op->index());
} else if (op->IsArgument()) {
ASSERT(is_tagged);
int src_index = StackSlotCount() + op->index();
int src_index = GetStackSlotCount() + op->index();
translation->StoreStackSlot(src_index);
} else if (op->IsRegister()) {
Register reg = ToRegister(op);
@ -2058,7 +2058,7 @@ void LCodeGen::DoReturn(LReturn* instr) {
}
__ movq(rsp, rbp);
__ pop(rbp);
__ Ret((ParameterCount() + 1) * kPointerSize, rcx);
__ Ret((GetParameterCount() + 1) * kPointerSize, rcx);
}
@ -2507,6 +2507,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
env->deoptimization_index());
v8::internal::ParameterCount actual(rax);
__ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
}
@ -2518,7 +2519,7 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) {
void LCodeGen::DoContext(LContext* instr) {
Register result = ToRegister(instr->result());
__ movq(result, Operand(rbp, StandardFrameConstants::kContextOffset));
__ movq(result, rsi);
}
@ -2900,6 +2901,21 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
}
void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
ASSERT(ToRegister(instr->function()).is(rdi));
ASSERT(instr->HasPointerMap());
ASSERT(instr->HasDeoptimizationEnvironment());
LPointerMap* pointers = instr->pointer_map();
LEnvironment* env = instr->deoptimization_environment();
RecordPosition(pointers->position());
RegisterEnvironmentForDeoptimization(env);
SafepointGenerator generator(this, pointers, env->deoptimization_index());
ParameterCount count(instr->arity());
__ InvokeFunction(rdi, count, CALL_FUNCTION, &generator);
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
}
void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
ASSERT(ToRegister(instr->key()).is(rcx));
ASSERT(ToRegister(instr->result()).is(rax));

View File

@ -141,8 +141,8 @@ class LCodeGen BASE_EMBEDDED {
Register input,
Register temporary);
int StackSlotCount() const { return chunk()->spill_slot_count(); }
int ParameterCount() const { return scope()->num_parameters(); }
int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
int GetParameterCount() const { return scope()->num_parameters(); }
void Abort(const char* format, ...);
void Comment(const char* format, ...);

View File

@ -302,6 +302,13 @@ void LStoreContextSlot::PrintDataTo(StringStream* stream) {
}
void LInvokeFunction::PrintDataTo(StringStream* stream) {
stream->Add("= ");
InputAt(0)->PrintTo(stream);
stream->Add(" #%d / ", arity());
}
void LCallKeyed::PrintDataTo(StringStream* stream) {
stream->Add("[rcx] #%d / ", arity());
}
@ -1210,6 +1217,14 @@ LInstruction* LChunkBuilder::DoCallConstantFunction(
}
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
LOperand* function = UseFixed(instr->function(), rdi);
argument_count_ -= instr->argument_count();
LInvokeFunction* result = new LInvokeFunction(function);
return MarkAsCall(DefineFixed(result, rax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
}
LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
BuiltinFunctionId op = instr->op();
if (op == kMathLog || op == kMathSin || op == kMathCos) {

View File

@ -98,14 +98,15 @@ class LCodeGen;
V(GlobalObject) \
V(GlobalReceiver) \
V(Goto) \
V(HasInstanceType) \
V(HasInstanceTypeAndBranch) \
V(HasCachedArrayIndex) \
V(HasCachedArrayIndexAndBranch) \
V(HasInstanceType) \
V(HasInstanceTypeAndBranch) \
V(InstanceOf) \
V(InstanceOfAndBranch) \
V(InstanceOfKnownGlobal) \
V(Integer32ToDouble) \
V(InvokeFunction) \
V(IsNull) \
V(IsNullAndBranch) \
V(IsObject) \
@ -1394,6 +1395,23 @@ class LCallConstantFunction: public LTemplateInstruction<1, 0, 0> {
};
class LInvokeFunction: public LTemplateInstruction<1, 1, 0> {
public:
LInvokeFunction(LOperand* function) {
inputs_[0] = function;
}
DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
LOperand* function() { return inputs_[0]; }
virtual void PrintDataTo(StringStream* stream);
int arity() const { return hydrogen()->argument_count() - 1; }
};
class LCallKeyed: public LTemplateInstruction<1, 1, 0> {
public:
explicit LCallKeyed(LOperand* key) {