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:
parent
348501ae01
commit
ef24af119e
@ -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));
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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, ...);
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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, ...);
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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, ...);
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user