Simplify invocation sequence at monomorphic function invocation sites.
Provide known target as a hint to HInvokeFunction instruction so that it can statically determine if arguments adaptation is required. R=fschneider@chromium.org BUG=v8:2079 Review URL: https://chromiumcodereview.appspot.com/10116021 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11364 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
5713859c99
commit
fd9bd722bc
@ -1473,6 +1473,7 @@ class LInvokeFunction: public LTemplateInstruction<1, 1, 0> {
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
|
||||
int arity() const { return hydrogen()->argument_count() - 1; }
|
||||
Handle<JSFunction> known_function() { return hydrogen()->known_function(); }
|
||||
};
|
||||
|
||||
|
||||
|
@ -2962,7 +2962,8 @@ void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
|
||||
void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
||||
int arity,
|
||||
LInstruction* instr,
|
||||
CallKind call_kind) {
|
||||
CallKind call_kind,
|
||||
R1State r1_state) {
|
||||
bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
|
||||
function->shared()->formal_parameter_count() == arity;
|
||||
|
||||
@ -2970,7 +2971,10 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
||||
RecordPosition(pointers->position());
|
||||
|
||||
if (can_invoke_directly) {
|
||||
__ LoadHeapObject(r1, function);
|
||||
if (r1_state == R1_UNINITIALIZED) {
|
||||
__ LoadHeapObject(r1, function);
|
||||
}
|
||||
|
||||
// Change context if needed.
|
||||
bool change_context =
|
||||
(info()->closure()->context() != function->context()) ||
|
||||
@ -3009,7 +3013,8 @@ void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
|
||||
CallKnownFunction(instr->function(),
|
||||
instr->arity(),
|
||||
instr,
|
||||
CALL_AS_METHOD);
|
||||
CALL_AS_METHOD,
|
||||
R1_UNINITIALIZED);
|
||||
}
|
||||
|
||||
|
||||
@ -3434,12 +3439,21 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
|
||||
ASSERT(ToRegister(instr->function()).is(r1));
|
||||
ASSERT(instr->HasPointerMap());
|
||||
ASSERT(instr->HasDeoptimizationEnvironment());
|
||||
LPointerMap* pointers = instr->pointer_map();
|
||||
RecordPosition(pointers->position());
|
||||
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
|
||||
ParameterCount count(instr->arity());
|
||||
__ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
|
||||
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
|
||||
if (instr->known_function().is_null()) {
|
||||
LPointerMap* pointers = instr->pointer_map();
|
||||
RecordPosition(pointers->position());
|
||||
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
|
||||
ParameterCount count(instr->arity());
|
||||
__ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
|
||||
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
} else {
|
||||
CallKnownFunction(instr->known_function(),
|
||||
instr->arity(),
|
||||
instr,
|
||||
CALL_AS_METHOD,
|
||||
R1_CONTAINS_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3494,7 +3508,11 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
|
||||
|
||||
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(r0));
|
||||
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
|
||||
CallKnownFunction(instr->target(),
|
||||
instr->arity(),
|
||||
instr,
|
||||
CALL_AS_FUNCTION,
|
||||
R1_UNINITIALIZED);
|
||||
}
|
||||
|
||||
|
||||
|
@ -215,12 +215,18 @@ class LCodeGen BASE_EMBEDDED {
|
||||
int argc,
|
||||
LInstruction* instr);
|
||||
|
||||
enum R1State {
|
||||
R1_UNINITIALIZED,
|
||||
R1_CONTAINS_TARGET
|
||||
};
|
||||
|
||||
// Generate a direct call to a known function. Expects the function
|
||||
// to be in r1.
|
||||
void CallKnownFunction(Handle<JSFunction> function,
|
||||
int arity,
|
||||
LInstruction* instr,
|
||||
CallKind call_kind);
|
||||
CallKind call_kind,
|
||||
R1State r1_state);
|
||||
|
||||
void LoadHeapObject(Register result, Handle<HeapObject> object);
|
||||
|
||||
|
@ -1644,14 +1644,26 @@ class HInvokeFunction: public HBinaryCall {
|
||||
: HBinaryCall(context, function, argument_count) {
|
||||
}
|
||||
|
||||
HInvokeFunction(HValue* context,
|
||||
HValue* function,
|
||||
Handle<JSFunction> known_function,
|
||||
int argument_count)
|
||||
: HBinaryCall(context, function, argument_count),
|
||||
known_function_(known_function) {
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
return Representation::Tagged();
|
||||
}
|
||||
|
||||
HValue* context() { return first(); }
|
||||
HValue* function() { return second(); }
|
||||
Handle<JSFunction> known_function() { return known_function_; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
|
||||
|
||||
private:
|
||||
Handle<JSFunction> known_function_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -6165,9 +6165,11 @@ void HGraphBuilder::VisitCall(Call* expr) {
|
||||
if (TryInlineCall(expr, true)) { // Drop function from environment.
|
||||
return;
|
||||
} else {
|
||||
call = PreProcessCall(new(zone()) HInvokeFunction(context,
|
||||
function,
|
||||
argument_count));
|
||||
call = PreProcessCall(
|
||||
new(zone()) HInvokeFunction(context,
|
||||
function,
|
||||
expr->target(),
|
||||
argument_count));
|
||||
Drop(1); // The function.
|
||||
}
|
||||
|
||||
|
@ -2738,7 +2738,8 @@ void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
|
||||
void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
||||
int arity,
|
||||
LInstruction* instr,
|
||||
CallKind call_kind) {
|
||||
CallKind call_kind,
|
||||
EDIState edi_state) {
|
||||
bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
|
||||
function->shared()->formal_parameter_count() == arity;
|
||||
|
||||
@ -2746,7 +2747,9 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
||||
RecordPosition(pointers->position());
|
||||
|
||||
if (can_invoke_directly) {
|
||||
__ LoadHeapObject(edi, function);
|
||||
if (edi_state == EDI_UNINITIALIZED) {
|
||||
__ LoadHeapObject(edi, function);
|
||||
}
|
||||
|
||||
// Change context if needed.
|
||||
bool change_context =
|
||||
@ -2789,7 +2792,8 @@ void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
|
||||
CallKnownFunction(instr->function(),
|
||||
instr->arity(),
|
||||
instr,
|
||||
CALL_AS_METHOD);
|
||||
CALL_AS_METHOD,
|
||||
EDI_UNINITIALIZED);
|
||||
}
|
||||
|
||||
|
||||
@ -3236,12 +3240,21 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
|
||||
ASSERT(ToRegister(instr->function()).is(edi));
|
||||
ASSERT(instr->HasPointerMap());
|
||||
ASSERT(instr->HasDeoptimizationEnvironment());
|
||||
LPointerMap* pointers = instr->pointer_map();
|
||||
RecordPosition(pointers->position());
|
||||
SafepointGenerator generator(
|
||||
this, pointers, Safepoint::kLazyDeopt);
|
||||
ParameterCount count(instr->arity());
|
||||
__ InvokeFunction(edi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
|
||||
|
||||
if (instr->known_function().is_null()) {
|
||||
LPointerMap* pointers = instr->pointer_map();
|
||||
RecordPosition(pointers->position());
|
||||
SafepointGenerator generator(
|
||||
this, pointers, Safepoint::kLazyDeopt);
|
||||
ParameterCount count(instr->arity());
|
||||
__ InvokeFunction(edi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
|
||||
} else {
|
||||
CallKnownFunction(instr->known_function(),
|
||||
instr->arity(),
|
||||
instr,
|
||||
CALL_AS_METHOD,
|
||||
EDI_CONTAINS_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3296,7 +3309,11 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
|
||||
|
||||
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(eax));
|
||||
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
|
||||
CallKnownFunction(instr->target(),
|
||||
instr->arity(),
|
||||
instr,
|
||||
CALL_AS_FUNCTION,
|
||||
EDI_UNINITIALIZED);
|
||||
}
|
||||
|
||||
|
||||
|
@ -206,12 +206,18 @@ class LCodeGen BASE_EMBEDDED {
|
||||
LInstruction* instr,
|
||||
LOperand* context);
|
||||
|
||||
enum EDIState {
|
||||
EDI_UNINITIALIZED,
|
||||
EDI_CONTAINS_TARGET
|
||||
};
|
||||
|
||||
// Generate a direct call to a known function. Expects the function
|
||||
// to be in edi.
|
||||
void CallKnownFunction(Handle<JSFunction> function,
|
||||
int arity,
|
||||
LInstruction* instr,
|
||||
CallKind call_kind);
|
||||
CallKind call_kind,
|
||||
EDIState edi_state);
|
||||
|
||||
void RecordSafepointWithLazyDeopt(LInstruction* instr,
|
||||
SafepointMode safepoint_mode);
|
||||
|
@ -1502,6 +1502,7 @@ class LInvokeFunction: public LTemplateInstruction<1, 2, 0> {
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
|
||||
int arity() const { return hydrogen()->argument_count() - 1; }
|
||||
Handle<JSFunction> known_function() { return hydrogen()->known_function(); }
|
||||
};
|
||||
|
||||
|
||||
|
@ -2848,7 +2848,8 @@ void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
|
||||
void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
||||
int arity,
|
||||
LInstruction* instr,
|
||||
CallKind call_kind) {
|
||||
CallKind call_kind,
|
||||
A1State a1_state) {
|
||||
bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
|
||||
function->shared()->formal_parameter_count() == arity;
|
||||
|
||||
@ -2856,7 +2857,10 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
||||
RecordPosition(pointers->position());
|
||||
|
||||
if (can_invoke_directly) {
|
||||
__ LoadHeapObject(a1, function);
|
||||
if (a1_state == A1_UNINITIALIZED) {
|
||||
__ LoadHeapObject(a1, function);
|
||||
}
|
||||
|
||||
// Change context if needed.
|
||||
bool change_context =
|
||||
(info()->closure()->context() != function->context()) ||
|
||||
@ -2893,7 +2897,11 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
||||
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(v0));
|
||||
__ mov(a0, v0);
|
||||
CallKnownFunction(instr->function(), instr->arity(), instr, CALL_AS_METHOD);
|
||||
CallKnownFunction(instr->function(),
|
||||
instr->arity(),
|
||||
instr,
|
||||
CALL_AS_METHOD,
|
||||
A1_UNINITIALIZED);
|
||||
}
|
||||
|
||||
|
||||
@ -3330,12 +3338,21 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
|
||||
ASSERT(ToRegister(instr->function()).is(a1));
|
||||
ASSERT(instr->HasPointerMap());
|
||||
ASSERT(instr->HasDeoptimizationEnvironment());
|
||||
LPointerMap* pointers = instr->pointer_map();
|
||||
RecordPosition(pointers->position());
|
||||
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
|
||||
ParameterCount count(instr->arity());
|
||||
__ InvokeFunction(a1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
|
||||
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
|
||||
if (instr->known_function().is_null()) {
|
||||
LPointerMap* pointers = instr->pointer_map();
|
||||
RecordPosition(pointers->position());
|
||||
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
|
||||
ParameterCount count(instr->arity());
|
||||
__ InvokeFunction(a1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
|
||||
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
} else {
|
||||
CallKnownFunction(instr->known_function(),
|
||||
instr->arity(),
|
||||
instr,
|
||||
CALL_AS_METHOD,
|
||||
A1_CONTAINS_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3390,7 +3407,11 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
|
||||
|
||||
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(v0));
|
||||
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
|
||||
CallKnownFunction(instr->target(),
|
||||
instr->arity(),
|
||||
instr,
|
||||
CALL_AS_FUNCTION,
|
||||
A1_UNINITIALIZED);
|
||||
}
|
||||
|
||||
|
||||
|
@ -212,12 +212,18 @@ class LCodeGen BASE_EMBEDDED {
|
||||
int argc,
|
||||
LInstruction* instr);
|
||||
|
||||
enum A1State {
|
||||
A1_UNINITIALIZED,
|
||||
A1_CONTAINS_TARGET
|
||||
};
|
||||
|
||||
// Generate a direct call to a known function. Expects the function
|
||||
// to be in a1.
|
||||
void CallKnownFunction(Handle<JSFunction> function,
|
||||
int arity,
|
||||
LInstruction* instr,
|
||||
CallKind call_kind);
|
||||
CallKind call_kind,
|
||||
A1State a1_state);
|
||||
|
||||
void LoadHeapObject(Register result, Handle<HeapObject> object);
|
||||
|
||||
|
@ -1453,6 +1453,7 @@ class LInvokeFunction: public LTemplateInstruction<1, 1, 0> {
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
|
||||
int arity() const { return hydrogen()->argument_count() - 1; }
|
||||
Handle<JSFunction> known_function() { return hydrogen()->known_function(); }
|
||||
};
|
||||
|
||||
|
||||
|
@ -2693,7 +2693,8 @@ void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
|
||||
void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
||||
int arity,
|
||||
LInstruction* instr,
|
||||
CallKind call_kind) {
|
||||
CallKind call_kind,
|
||||
RDIState rdi_state) {
|
||||
bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
|
||||
function->shared()->formal_parameter_count() == arity;
|
||||
|
||||
@ -2701,7 +2702,9 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
||||
RecordPosition(pointers->position());
|
||||
|
||||
if (can_invoke_directly) {
|
||||
__ LoadHeapObject(rdi, function);
|
||||
if (rdi_state == RDI_UNINITIALIZED) {
|
||||
__ LoadHeapObject(rdi, function);
|
||||
}
|
||||
|
||||
// Change context if needed.
|
||||
bool change_context =
|
||||
@ -2746,7 +2749,8 @@ void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
|
||||
CallKnownFunction(instr->function(),
|
||||
instr->arity(),
|
||||
instr,
|
||||
CALL_AS_METHOD);
|
||||
CALL_AS_METHOD,
|
||||
RDI_UNINITIALIZED);
|
||||
}
|
||||
|
||||
|
||||
@ -3184,12 +3188,21 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
|
||||
ASSERT(ToRegister(instr->function()).is(rdi));
|
||||
ASSERT(instr->HasPointerMap());
|
||||
ASSERT(instr->HasDeoptimizationEnvironment());
|
||||
LPointerMap* pointers = instr->pointer_map();
|
||||
RecordPosition(pointers->position());
|
||||
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
|
||||
ParameterCount count(instr->arity());
|
||||
__ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
|
||||
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
||||
|
||||
if (instr->known_function().is_null()) {
|
||||
LPointerMap* pointers = instr->pointer_map();
|
||||
RecordPosition(pointers->position());
|
||||
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
|
||||
ParameterCount count(instr->arity());
|
||||
__ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
|
||||
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
||||
} else {
|
||||
CallKnownFunction(instr->known_function(),
|
||||
instr->arity(),
|
||||
instr,
|
||||
CALL_AS_METHOD,
|
||||
RDI_CONTAINS_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3243,7 +3256,11 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
|
||||
|
||||
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(rax));
|
||||
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
|
||||
CallKnownFunction(instr->target(),
|
||||
instr->arity(),
|
||||
instr,
|
||||
CALL_AS_FUNCTION,
|
||||
RDI_UNINITIALIZED);
|
||||
}
|
||||
|
||||
|
||||
|
@ -196,12 +196,18 @@ class LCodeGen BASE_EMBEDDED {
|
||||
int argc,
|
||||
LInstruction* instr);
|
||||
|
||||
enum RDIState {
|
||||
RDI_UNINITIALIZED,
|
||||
RDI_CONTAINS_TARGET
|
||||
};
|
||||
|
||||
// Generate a direct call to a known function. Expects the function
|
||||
// to be in rdi.
|
||||
void CallKnownFunction(Handle<JSFunction> function,
|
||||
int arity,
|
||||
LInstruction* instr,
|
||||
CallKind call_kind);
|
||||
CallKind call_kind,
|
||||
RDIState rdi_state);
|
||||
|
||||
|
||||
void RecordSafepointWithLazyDeopt(LInstruction* instr,
|
||||
|
@ -1447,6 +1447,7 @@ class LInvokeFunction: public LTemplateInstruction<1, 1, 0> {
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
|
||||
int arity() const { return hydrogen()->argument_count() - 1; }
|
||||
Handle<JSFunction> known_function() { return hydrogen()->known_function(); }
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user