Commit 4de11a7b authored by vegorov@chromium.org's avatar vegorov@chromium.org

MIPS: Allow call-known-global and call-constant-function to be used

for call-sites with mismatched number of arguments.

Port r10424 (92a05c9c).

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

BUG=
TEST=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10456 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5c92e4f1
......@@ -2716,7 +2716,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
this, pointers, Safepoint::kLazyDeopt);
// The number of arguments is stored in receiver which is a0, as expected
// by InvokeFunction.
v8::internal::ParameterCount actual(receiver);
ParameterCount actual(receiver);
__ InvokeFunction(function, actual, CALL_FUNCTION,
safepoint_generator, CALL_AS_METHOD);
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
......@@ -2772,31 +2772,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) {
__ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
}
// Set a0 to arguments count if adaption is not needed. Assumes that a0
// is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
__ li(a0, 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(t1, call_kind);
__ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
__ Call(at);
if (can_invoke_directly) {
__ LoadHeapObject(a1, function);
// Change context if needed.
bool change_context =
(info()->closure()->context() != function->context()) ||
scope()->contains_with() ||
(scope()->num_heap_slots() > 0);
if (change_context) {
__ lw(cp, FieldMemOperand(a1, 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()) {
__ li(a0, Operand(arity));
}
// Invoke function.
__ SetCallKind(t1, call_kind);
__ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
__ Call(at);
// 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.
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
......@@ -2806,7 +2816,6 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
ASSERT(ToRegister(instr->result()).is(v0));
__ mov(a0, v0);
__ LoadHeapObject(a1, instr->function());
CallKnownFunction(instr->function(), instr->arity(), instr, CALL_AS_METHOD);
}
......@@ -3249,7 +3258,6 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
ASSERT(ToRegister(instr->result()).is(v0));
__ LoadHeapObject(a1, instr->target());
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
}
......
......@@ -3432,10 +3432,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,
......@@ -3466,6 +3468,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
// arguments.
definitely_matches = true;
} else {
*definitely_mismatches = true;
li(a2, Operand(expected.immediate()));
}
}
......@@ -3489,7 +3492,9 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
SetCallKind(t1, call_kind);
Call(adaptor);
call_wrapper.AfterCall();
jmp(done);
if (!*definitely_mismatches) {
Branch(done);
}
} else {
SetCallKind(t1, call_kind);
Jump(adaptor, RelocInfo::CODE_TARGET);
......@@ -3510,21 +3515,25 @@ void MacroAssembler::InvokeCode(Register code,
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(t1, call_kind);
Call(code);
call_wrapper.AfterCall();
} else {
ASSERT(flag == JUMP_FUNCTION);
SetCallKind(t1, call_kind);
Jump(code);
if (!definitely_mismatches) {
if (flag == CALL_FUNCTION) {
call_wrapper.BeforeCall(CallSize(code));
SetCallKind(t1, call_kind);
Call(code);
call_wrapper.AfterCall();
} else {
ASSERT(flag == JUMP_FUNCTION);
SetCallKind(t1, 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);
}
......@@ -3539,18 +3548,22 @@ void MacroAssembler::InvokeCode(Handle<Code> code,
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(t1, call_kind);
Call(code, rmode);
} else {
SetCallKind(t1, call_kind);
Jump(code, rmode);
if (!definitely_mismatches) {
if (flag == CALL_FUNCTION) {
SetCallKind(t1, call_kind);
Call(code, rmode);
} else {
SetCallKind(t1, 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);
}
......@@ -3583,6 +3596,7 @@ void MacroAssembler::InvokeFunction(Register function,
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());
......@@ -3596,7 +3610,7 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
// allow recompilation to take effect without changing any of the
// call sites.
lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
InvokeCode(a3, expected, actual, flag, NullCallWrapper(), call_kind);
InvokeCode(a3, expected, actual, flag, call_wrapper, call_kind);
}
......
......@@ -820,6 +820,7 @@ class MacroAssembler: public Assembler {
void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind);
......@@ -1359,6 +1360,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);
......
......@@ -747,7 +747,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.
......@@ -1934,7 +1934,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);
// a2: function name.
......@@ -2067,7 +2068,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);
// a2: function name.
......@@ -2167,7 +2169,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);
// a2: function name.
......@@ -2346,7 +2349,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);
......
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