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

Allow call-known-global and call-constant-function to be used for call-sites...

Allow call-known-global and call-constant-function to be used for call-sites with mismatched number of arguments.

Adjust InvokeFunction to avoid generating dead code when number when arity mismatch is detected in compile time.

R=fschneider@google.com

Review URL: https://chromiumcodereview.appspot.com/9178017

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10424 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 188d7a9e
......@@ -2828,7 +2828,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
this, pointers, Safepoint::kLazyDeopt);
// The number of arguments is stored in receiver which is r0, as expected
// by InvokeFunction.
v8::internal::ParameterCount actual(receiver);
ParameterCount actual(receiver);
__ InvokeFunction(function, actual, CALL_FUNCTION,
safepoint_generator, CALL_AS_METHOD);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
......@@ -2883,31 +2883,41 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
int arity,
LInstruction* instr,
CallKind call_kind) {
// Change context if needed.
bool change_context =
(info()->closure()->context() != function->context()) ||
scope()->contains_with() ||
(scope()->num_heap_slots() > 0);
if (change_context) {
__ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
}
// Set r0 to arguments count if adaption is not needed. Assumes that r0
// is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
__ mov(r0, Operand(arity));
}
bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
function->shared()->formal_parameter_count() == arity;
LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position());
// Invoke function.
__ SetCallKind(r5, call_kind);
__ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
__ Call(ip);
if (can_invoke_directly) {
__ LoadHeapObject(r1, function);
// Change context if needed.
bool change_context =
(info()->closure()->context() != function->context()) ||
scope()->contains_with() ||
(scope()->num_heap_slots() > 0);
if (change_context) {
__ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
}
// Set up deoptimization.
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
// Set r0 to arguments count if adaption is not needed. Assumes that r0
// is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
__ mov(r0, Operand(arity));
}
// Invoke function.
__ SetCallKind(r5, call_kind);
__ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
__ Call(ip);
// Set up deoptimization.
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
} else {
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
ParameterCount count(arity);
__ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind);
}
// Restore context.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
......@@ -2916,7 +2926,6 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
ASSERT(ToRegister(instr->result()).is(r0));
__ LoadHeapObject(r1, instr->function());
CallKnownFunction(instr->function(),
instr->arity(),
instr,
......@@ -3351,7 +3360,6 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
ASSERT(ToRegister(instr->result()).is(r0));
__ LoadHeapObject(r1, instr->target());
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
}
......
......@@ -957,10 +957,12 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
Handle<Code> code_constant,
Register code_reg,
Label* done,
bool* definitely_mismatches,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind) {
bool definitely_matches = false;
*definitely_mismatches = false;
Label regular_invoke;
// Check whether the expected and actual arguments count match. If not,
......@@ -991,6 +993,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
// arguments.
definitely_matches = true;
} else {
*definitely_mismatches = true;
mov(r2, Operand(expected.immediate()));
}
}
......@@ -1018,7 +1021,9 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
SetCallKind(r5, call_kind);
Call(adaptor);
call_wrapper.AfterCall();
b(done);
if (!*definitely_mismatches) {
b(done);
}
} else {
SetCallKind(r5, call_kind);
Jump(adaptor, RelocInfo::CODE_TARGET);
......@@ -1038,23 +1043,26 @@ void MacroAssembler::InvokeCode(Register code,
ASSERT(flag == JUMP_FUNCTION || has_frame());
Label done;
InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag,
bool definitely_mismatches = false;
InvokePrologue(expected, actual, Handle<Code>::null(), code,
&done, &definitely_mismatches, flag,
call_wrapper, call_kind);
if (flag == CALL_FUNCTION) {
call_wrapper.BeforeCall(CallSize(code));
SetCallKind(r5, call_kind);
Call(code);
call_wrapper.AfterCall();
} else {
ASSERT(flag == JUMP_FUNCTION);
SetCallKind(r5, call_kind);
Jump(code);
}
if (!definitely_mismatches) {
if (flag == CALL_FUNCTION) {
call_wrapper.BeforeCall(CallSize(code));
SetCallKind(r5, call_kind);
Call(code);
call_wrapper.AfterCall();
} else {
ASSERT(flag == JUMP_FUNCTION);
SetCallKind(r5, call_kind);
Jump(code);
}
// Continue here if InvokePrologue does handle the invocation due to
// mismatched parameter counts.
bind(&done);
// Continue here if InvokePrologue does handle the invocation due to
// mismatched parameter counts.
bind(&done);
}
}
......@@ -1068,20 +1076,23 @@ void MacroAssembler::InvokeCode(Handle<Code> code,
ASSERT(flag == JUMP_FUNCTION || has_frame());
Label done;
InvokePrologue(expected, actual, code, no_reg, &done, flag,
bool definitely_mismatches = false;
InvokePrologue(expected, actual, code, no_reg,
&done, &definitely_mismatches, flag,
NullCallWrapper(), call_kind);
if (flag == CALL_FUNCTION) {
SetCallKind(r5, call_kind);
Call(code, rmode);
} else {
SetCallKind(r5, call_kind);
Jump(code, rmode);
}
if (!definitely_mismatches) {
if (flag == CALL_FUNCTION) {
SetCallKind(r5, call_kind);
Call(code, rmode);
} else {
SetCallKind(r5, call_kind);
Jump(code, rmode);
}
// Continue here if InvokePrologue does handle the invocation due to
// mismatched parameter counts.
bind(&done);
// Continue here if InvokePrologue does handle the invocation due to
// mismatched parameter counts.
bind(&done);
}
}
......@@ -1116,6 +1127,7 @@ void MacroAssembler::InvokeFunction(Register fun,
void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind) {
// You can't call a function without a valid frame.
ASSERT(flag == JUMP_FUNCTION || has_frame());
......@@ -1129,7 +1141,7 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
// allow recompilation to take effect without changing any of the
// call sites.
ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
InvokeCode(r3, expected, actual, flag, NullCallWrapper(), call_kind);
InvokeCode(r3, expected, actual, flag, call_wrapper, call_kind);
}
......
......@@ -539,6 +539,7 @@ class MacroAssembler: public Assembler {
void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind);
void IsObjectJSObjectType(Register heap_object,
......@@ -1248,6 +1249,7 @@ class MacroAssembler: public Assembler {
Handle<Code> code_constant,
Register code_reg,
Label* done,
bool* definitely_mismatches,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind);
......
......@@ -738,7 +738,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(optimization.constant_function(), arguments_,
JUMP_FUNCTION, call_kind);
JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
// Deferred code for fast API call case---clean preallocated space.
......@@ -1904,7 +1904,8 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD);
__ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// r2: function name.
......@@ -2049,7 +2050,8 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
__ bind(&slow);
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD);
__ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// r2: function name.
......@@ -2147,7 +2149,8 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD);
__ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// r2: function name.
......@@ -2325,7 +2328,8 @@ Handle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object,
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind);
__ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind);
// Handle call cache miss.
__ bind(&miss);
......
......@@ -724,16 +724,6 @@ void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
}
static bool CanCallWithoutIC(Handle<JSFunction> target, int arity) {
SharedFunctionInfo* info = target->shared();
// If the number of formal parameters of the target function does
// not match the number of arguments we're passing, we don't want to
// deal with it. Otherwise, we can call it directly.
return !target->NeedsArgumentsAdaption() ||
info->formal_parameter_count() == arity;
}
bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) {
if (check_type_ == RECEIVER_MAP_CHECK) {
// For primitive checks the holder is set up to point to the
......@@ -754,7 +744,7 @@ bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) {
type = Handle<Map>(holder()->map());
} else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
target_ = Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type));
return CanCallWithoutIC(target_, arguments()->length());
return true;
} else {
return false;
}
......@@ -774,8 +764,7 @@ bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
// If the function is in new space we assume it's more likely to
// change and thus prefer the general IC code.
if (!HEAP->InNewSpace(*candidate) &&
CanCallWithoutIC(candidate, arguments()->length())) {
if (!HEAP->InNewSpace(*candidate)) {
target_ = candidate;
return true;
}
......
......@@ -2701,41 +2701,53 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
int arity,
LInstruction* instr,
CallKind call_kind) {
// Change context if needed.
bool change_context =
(info()->closure()->context() != function->context()) ||
scope()->contains_with() ||
(scope()->num_heap_slots() > 0);
if (change_context) {
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
} else {
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
// Set eax to arguments count if adaption is not needed. Assumes that eax
// is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
__ mov(eax, arity);
}
bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
function->shared()->formal_parameter_count() == arity;
LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position());
// Invoke function.
__ SetCallKind(ecx, call_kind);
if (*function == *info()->closure()) {
__ CallSelf();
if (can_invoke_directly) {
__ LoadHeapObject(edi, function);
// Change context if needed.
bool change_context =
(info()->closure()->context() != function->context()) ||
scope()->contains_with() ||
(scope()->num_heap_slots() > 0);
if (change_context) {
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
} else {
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
// Set eax to arguments count if adaption is not needed. Assumes that eax
// is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
__ mov(eax, arity);
}
// Invoke function directly.
__ SetCallKind(ecx, call_kind);
if (*function == *info()->closure()) {
__ CallSelf();
} else {
__ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
}
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
} else {
__ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
// We need to adapt arguments.
SafepointGenerator generator(
this, pointers, Safepoint::kLazyDeopt);
ParameterCount count(arity);
__ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind);
}
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
}
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
ASSERT(ToRegister(instr->result()).is(eax));
__ LoadHeapObject(edi, instr->function());
CallKnownFunction(instr->function(),
instr->arity(),
instr,
......@@ -3190,7 +3202,6 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
ASSERT(ToRegister(instr->result()).is(eax));
__ LoadHeapObject(edi, instr->target());
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
}
......
......@@ -1933,11 +1933,13 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
Handle<Code> code_constant,
const Operand& code_operand,
Label* done,
bool* definitely_mismatches,
InvokeFlag flag,
Label::Distance done_near,
const CallWrapper& call_wrapper,
CallKind call_kind) {
bool definitely_matches = false;
*definitely_mismatches = false;
Label invoke;
if (expected.is_immediate()) {
ASSERT(actual.is_immediate());
......@@ -1953,6 +1955,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
// arguments.
definitely_matches = true;
} else {
*definitely_mismatches = true;
mov(ebx, expected.immediate());
}
}
......@@ -1990,7 +1993,9 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
SetCallKind(ecx, call_kind);
call(adaptor, RelocInfo::CODE_TARGET);
call_wrapper.AfterCall();
jmp(done, done_near);
if (!*definitely_mismatches) {
jmp(done, done_near);
}
} else {
SetCallKind(ecx, call_kind);
jmp(adaptor, RelocInfo::CODE_TARGET);
......@@ -2010,20 +2015,23 @@ void MacroAssembler::InvokeCode(const Operand& code,
ASSERT(flag == JUMP_FUNCTION || has_frame());
Label done;
bool definitely_mismatches = false;
InvokePrologue(expected, actual, Handle<Code>::null(), code,
&done, flag, Label::kNear, call_wrapper,
call_kind);
if (flag == CALL_FUNCTION) {
call_wrapper.BeforeCall(CallSize(code));
SetCallKind(ecx, call_kind);
call(code);
call_wrapper.AfterCall();
} else {
ASSERT(flag == JUMP_FUNCTION);
SetCallKind(ecx, call_kind);
jmp(code);
&done, &definitely_mismatches, flag, Label::kNear,
call_wrapper, call_kind);
if (!definitely_mismatches) {
if (flag == CALL_FUNCTION) {
call_wrapper.BeforeCall(CallSize(code));
SetCallKind(ecx, call_kind);
call(code);
call_wrapper.AfterCall();
} else {
ASSERT(flag == JUMP_FUNCTION);
SetCallKind(ecx, call_kind);
jmp(code);
}
bind(&done);
}
bind(&done);
}
......@@ -2039,19 +2047,22 @@ void MacroAssembler::InvokeCode(Handle<Code> code,
Label done;
Operand dummy(eax, 0);
InvokePrologue(expected, actual, code, dummy, &done, flag, Label::kNear,
call_wrapper, call_kind);
if (flag == CALL_FUNCTION) {
call_wrapper.BeforeCall(CallSize(code, rmode));
SetCallKind(ecx, call_kind);
call(code, rmode);
call_wrapper.AfterCall();
} else {
ASSERT(flag == JUMP_FUNCTION);
SetCallKind(ecx, call_kind);
jmp(code, rmode);
bool definitely_mismatches = false;
InvokePrologue(expected, actual, code, dummy, &done, &definitely_mismatches,
flag, Label::kNear, call_wrapper, call_kind);
if (!definitely_mismatches) {
if (flag == CALL_FUNCTION) {
call_wrapper.BeforeCall(CallSize(code, rmode));
SetCallKind(ecx, call_kind);
call(code, rmode);
call_wrapper.AfterCall();
} else {
ASSERT(flag == JUMP_FUNCTION);
SetCallKind(ecx, call_kind);
jmp(code, rmode);
}
bind(&done);
}
bind(&done);
}
......
......@@ -827,6 +827,7 @@ class MacroAssembler: public Assembler {
Handle<Code> code_constant,
const Operand& code_operand,
Label* done,
bool* definitely_mismatches,
InvokeFlag flag,
Label::Distance done_distance,
const CallWrapper& call_wrapper = NullCallWrapper(),
......
......@@ -2565,7 +2565,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
RecordPosition(pointers->position());
SafepointGenerator safepoint_generator(
this, pointers, Safepoint::kLazyDeopt);
v8::internal::ParameterCount actual(rax);
ParameterCount actual(rax);
__ InvokeFunction(function, actual, CALL_FUNCTION,
safepoint_generator, CALL_AS_METHOD);
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
......@@ -2615,35 +2615,48 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
int arity,
LInstruction* instr,
CallKind call_kind) {
// Change context if needed.
bool change_context =
(info()->closure()->context() != function->context()) ||
scope()->contains_with() ||
(scope()->num_heap_slots() > 0);
if (change_context) {
__ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
}
// Set rax to arguments count if adaption is not needed. Assumes that rax
// is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
__ Set(rax, arity);
}
bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
function->shared()->formal_parameter_count() == arity;
LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position());
// Invoke function.
__ SetCallKind(rcx, call_kind);
if (*function == *info()->closure()) {
__ CallSelf();
if (can_invoke_directly) {
__ LoadHeapObject(rdi, function);
// Change context if needed.
bool change_context =
(info()->closure()->context() != function->context()) ||
scope()->contains_with() ||
(scope()->num_heap_slots() > 0);
if (change_context) {
__ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
}
// Set rax to arguments count if adaption is not needed. Assumes that rax
// is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
__ Set(rax, arity);
}
// Invoke function.
__ SetCallKind(rcx, call_kind);
if (*function == *info()->closure()) {
__ CallSelf();
} else {
__ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset));
}
// Set up deoptimization.
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0);
} else {
__ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset));
// We need to adapt arguments.
SafepointGenerator generator(
this, pointers, Safepoint::kLazyDeopt);
ParameterCount count(arity);
__ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind);
}
// Set up deoptimization.
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0);
// Restore context.
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
}
......@@ -2651,7 +2664,6 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
ASSERT(ToRegister(instr->result()).is(rax));
__ LoadHeapObject(rdi, instr->function());
CallKnownFunction(instr->function(),
instr->arity(),
instr,
......@@ -3094,7 +3106,6 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
ASSERT(ToRegister(instr->result()).is(rax));
__ LoadHeapObject(rdi, instr->target());
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
}
......
......@@ -3030,26 +3030,30 @@ void MacroAssembler::InvokeCode(Register code,
ASSERT(flag == JUMP_FUNCTION || has_frame());
Label done;
bool definitely_mismatches = false;
InvokePrologue(expected,
actual,
Handle<Code>::null(),
code,
&done,
&definitely_mismatches,
flag,
Label::kNear,
call_wrapper,
call_kind);
if (flag == CALL_FUNCTION) {
call_wrapper.BeforeCall(CallSize(code));
SetCallKind(rcx, call_kind);
call(code);
call_wrapper.AfterCall();
} else {
ASSERT(flag == JUMP_FUNCTION);
SetCallKind(rcx, call_kind);
jmp(code);
if (!definitely_mismatches) {
if (flag == CALL_FUNCTION) {
call_wrapper.BeforeCall(CallSize(code));
SetCallKind(rcx, call_kind);
call(code);
call_wrapper.AfterCall();
} else {
ASSERT(flag == JUMP_FUNCTION);
SetCallKind(rcx, call_kind);
jmp(code);
}
bind(&done);
}
bind(&done);
}
......@@ -3064,27 +3068,31 @@ void MacroAssembler::InvokeCode(Handle<Code> code,
ASSERT(flag == JUMP_FUNCTION || has_frame());
Label done;
bool definitely_mismatches = false;
Register dummy = rax;
InvokePrologue(expected,
actual,
code,
dummy,
&done,
&definitely_mismatches,
flag,
Label::kNear,
call_wrapper,
call_kind);
if (flag == CALL_FUNCTION) {
call_wrapper.BeforeCall(CallSize(code));
SetCallKind(rcx, call_kind);
Call(code, rmode);
call_wrapper.AfterCall();
} else {
ASSERT(flag == JUMP_FUNCTION);
SetCallKind(rcx, call_kind);
Jump(code, rmode);
if (!definitely_mismatches) {
if (flag == CALL_FUNCTION) {
call_wrapper.BeforeCall(CallSize(code));
SetCallKind(rcx, call_kind);
Call(code, rmode);
call_wrapper.AfterCall();
} else {
ASSERT(flag == JUMP_FUNCTION);
SetCallKind(rcx, call_kind);
Jump(code, rmode);
}
bind(&done);
}
bind(&done);
}
......@@ -3136,11 +3144,13 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
Handle<Code> code_constant,
Register code_register,
Label* done,
bool* definitely_mismatches,
InvokeFlag flag,
Label::Distance near_jump,
const CallWrapper& call_wrapper,
CallKind call_kind) {
bool definitely_matches = false;
*definitely_mismatches = false;
Label invoke;
if (expected.is_immediate()) {
ASSERT(actual.is_immediate());
......@@ -3156,6 +3166,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
// arguments.
definitely_matches = true;
} else {
*definitely_mismatches = true;
Set(rbx, expected.immediate());
}
}
......@@ -3192,7 +3203,9 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
SetCallKind(rcx, call_kind);
Call(adaptor, RelocInfo::CODE_TARGET);
call_wrapper.AfterCall();
jmp(done, near_jump);
if (!*definitely_mismatches) {
jmp(done, near_jump);
}
} else {
SetCallKind(rcx, call_kind);
Jump(adaptor, RelocInfo::CODE_TARGET);
......
......@@ -1309,6 +1309,7 @@ class MacroAssembler: public Assembler {
Handle<Code> code_constant,
Register code_register,
Label* done,
bool* definitely_mismatches,
InvokeFlag flag,
Label::Distance near_jump = Label::kFar,
const CallWrapper& call_wrapper = NullCallWrapper(),
......
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