Commit 09c63bc9 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Revert r18131 and r18139 "Clean up in the CallStubCompiler".

and "Fix register usage."

TBR=verwaest@chromium.org

Review URL: https://codereview.chromium.org/96573002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18146 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d778f708
...@@ -1229,7 +1229,7 @@ void MacroAssembler::InvokeFunction(Register fun, ...@@ -1229,7 +1229,7 @@ void MacroAssembler::InvokeFunction(Register fun,
} }
void MacroAssembler::InvokeFunction(Register function, void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected, const ParameterCount& expected,
const ParameterCount& actual, const ParameterCount& actual,
InvokeFlag flag, InvokeFlag flag,
...@@ -1238,10 +1238,8 @@ void MacroAssembler::InvokeFunction(Register function, ...@@ -1238,10 +1238,8 @@ void MacroAssembler::InvokeFunction(Register function,
// You can't call a function without a valid frame. // You can't call a function without a valid frame.
ASSERT(flag == JUMP_FUNCTION || has_frame()); ASSERT(flag == JUMP_FUNCTION || has_frame());
// Contract with called JS functions requires that function is passed in r1.
ASSERT(function.is(r1));
// Get the function and setup the context. // Get the function and setup the context.
Move(r1, function);
ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
// We call indirectly through the code field in the function to // We call indirectly through the code field in the function to
...@@ -1252,17 +1250,6 @@ void MacroAssembler::InvokeFunction(Register function, ...@@ -1252,17 +1250,6 @@ void MacroAssembler::InvokeFunction(Register function,
} }
void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind) {
Move(r1, function);
InvokeFunction(r1, expected, actual, flag, call_wrapper, call_kind);
}
void MacroAssembler::IsObjectJSObjectType(Register heap_object, void MacroAssembler::IsObjectJSObjectType(Register heap_object,
Register map, Register map,
Register scratch, Register scratch,
......
...@@ -613,13 +613,6 @@ class MacroAssembler: public Assembler { ...@@ -613,13 +613,6 @@ class MacroAssembler: public Assembler {
const CallWrapper& call_wrapper, const CallWrapper& call_wrapper,
CallKind call_kind); CallKind call_kind);
void InvokeFunction(Register function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind);
void InvokeFunction(Handle<JSFunction> function, void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected, const ParameterCount& expected,
const ParameterCount& actual, const ParameterCount& actual,
......
...@@ -742,6 +742,36 @@ void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, ...@@ -742,6 +742,36 @@ void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
} }
static void GenerateCallFunction(MacroAssembler* masm,
Handle<Object> object,
const ParameterCount& arguments,
Label* miss,
Code::ExtraICState extra_ic_state) {
// ----------- S t a t e -------------
// -- r0: receiver
// -- r1: function to call
// -----------------------------------
// Check that the function really is a function.
__ JumpIfSmi(r1, miss);
__ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
__ b(ne, miss);
if (object->IsGlobalObject()) {
const int argc = arguments.immediate();
const int receiver_offset = argc * kPointerSize;
__ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
__ str(r3, MemOperand(sp, receiver_offset));
}
// Invoke the function.
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
static void PushInterceptorArguments(MacroAssembler* masm, static void PushInterceptorArguments(MacroAssembler* masm,
Register receiver, Register receiver,
Register holder, Register holder,
...@@ -925,7 +955,7 @@ static void GenerateFastApiCall(MacroAssembler* masm, ...@@ -925,7 +955,7 @@ static void GenerateFastApiCall(MacroAssembler* masm,
class CallInterceptorCompiler BASE_EMBEDDED { class CallInterceptorCompiler BASE_EMBEDDED {
public: public:
CallInterceptorCompiler(CallStubCompiler* stub_compiler, CallInterceptorCompiler(StubCompiler* stub_compiler,
const ParameterCount& arguments, const ParameterCount& arguments,
Register name, Register name,
ExtraICState extra_ic_state) ExtraICState extra_ic_state)
...@@ -1037,8 +1067,13 @@ class CallInterceptorCompiler BASE_EMBEDDED { ...@@ -1037,8 +1067,13 @@ class CallInterceptorCompiler BASE_EMBEDDED {
GenerateFastApiDirectCall( GenerateFastApiDirectCall(
masm, optimization, arguments_.immediate(), false); masm, optimization, arguments_.immediate(), false);
} else { } else {
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
Handle<JSFunction> function = optimization.constant_function(); Handle<JSFunction> function = optimization.constant_function();
stub_compiler_->GenerateJumpFunction(object, function); ParameterCount expected(function);
__ InvokeFunction(function, expected, arguments_,
JUMP_FUNCTION, NullCallWrapper(), call_kind);
} }
// Deferred code for fast API call case---clean preallocated space. // Deferred code for fast API call case---clean preallocated space.
...@@ -1104,7 +1139,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { ...@@ -1104,7 +1139,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
__ b(ne, interceptor_succeeded); __ b(ne, interceptor_succeeded);
} }
CallStubCompiler* stub_compiler_; StubCompiler* stub_compiler_;
const ParameterCount& arguments_; const ParameterCount& arguments_;
Register name_; Register name_;
ExtraICState extra_ic_state_; ExtraICState extra_ic_state_;
...@@ -1506,15 +1541,6 @@ void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { ...@@ -1506,15 +1541,6 @@ void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
} }
void CallStubCompiler::GenerateFunctionCheck(Register function,
Register scratch,
Label* miss) {
__ JumpIfSmi(function, miss);
__ CompareObjectType(function, scratch, scratch, JS_FUNCTION_TYPE);
__ b(ne, miss);
}
void CallStubCompiler::GenerateLoadFunctionFromCell( void CallStubCompiler::GenerateLoadFunctionFromCell(
Handle<Cell> cell, Handle<Cell> cell,
Handle<JSFunction> function, Handle<JSFunction> function,
...@@ -1530,7 +1556,9 @@ void CallStubCompiler::GenerateLoadFunctionFromCell( ...@@ -1530,7 +1556,9 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(
// the nice side effect that multiple closures based on the same // the nice side effect that multiple closures based on the same
// function can all use this call IC. Before we load through the // function can all use this call IC. Before we load through the
// function, we have to verify that it still is a function. // function, we have to verify that it still is a function.
GenerateFunctionCheck(r1, r3, miss); __ JumpIfSmi(r1, miss);
__ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
__ b(ne, miss);
// Check the shared function info. Make sure it hasn't changed. // Check the shared function info. Make sure it hasn't changed.
__ Move(r3, Handle<SharedFunctionInfo>(function->shared())); __ Move(r3, Handle<SharedFunctionInfo>(function->shared()));
...@@ -1562,7 +1590,8 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, ...@@ -1562,7 +1590,8 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
object, holder, name, RECEIVER_MAP_CHECK, &miss); object, holder, name, RECEIVER_MAP_CHECK, &miss);
GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder), GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder),
index.translate(holder), Representation::Tagged()); index.translate(holder), Representation::Tagged());
GenerateJumpFunction(object, r1, &miss);
GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
...@@ -1977,7 +2006,8 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( ...@@ -1977,7 +2006,8 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
__ bind(&miss); __ bind(&miss);
// Restore function name in r2. // Restore function name in r2.
__ Move(r2, name); __ Move(r2, name);
HandlerFrontendFooter(&name_miss); __ bind(&name_miss);
GenerateMissBranch();
// Return the generated code. // Return the generated code.
return GetCode(type, name); return GetCode(type, name);
...@@ -2043,7 +2073,8 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall( ...@@ -2043,7 +2073,8 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
__ bind(&miss); __ bind(&miss);
// Restore function name in r2. // Restore function name in r2.
__ Move(r2, name); __ Move(r2, name);
HandlerFrontendFooter(&name_miss); __ bind(&name_miss);
GenerateMissBranch();
// Return the generated code. // Return the generated code.
return GetCode(type, name); return GetCode(type, name);
...@@ -2090,10 +2121,12 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( ...@@ -2090,10 +2121,12 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
StubRuntimeCallHelper call_helper; StubRuntimeCallHelper call_helper;
generator.GenerateSlow(masm(), call_helper); generator.GenerateSlow(masm(), call_helper);
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow); __ bind(&slow);
// We do not have to patch the receiver because the function makes no use of ParameterCount expected(function);
// it. __ InvokeFunction(function, expected, arguments(),
GenerateJumpFunctionIgnoreReceiver(function); JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
...@@ -2181,9 +2214,11 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall( ...@@ -2181,9 +2214,11 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
__ Ret(); __ Ret();
__ bind(&slow); __ bind(&slow);
// We do not have to patch the receiver because the function makes no use of // Tail call the full function. We do not have to patch the receiver
// it. // because the function makes no use of it.
GenerateJumpFunctionIgnoreReceiver(function); ParameterCount expected(function);
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
...@@ -2261,10 +2296,12 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall( ...@@ -2261,10 +2296,12 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
__ Drop(argc + 1); __ Drop(argc + 1);
__ Ret(); __ Ret();
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow); __ bind(&slow);
// We do not have to patch the receiver because the function makes no use of ParameterCount expected(function);
// it. __ InvokeFunction(function, expected, arguments(),
GenerateJumpFunctionIgnoreReceiver(function); JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
...@@ -2317,7 +2354,8 @@ Handle<Code> CallStubCompiler::CompileFastApiCall( ...@@ -2317,7 +2354,8 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
__ bind(&miss); __ bind(&miss);
FreeSpaceForFastApiCall(masm()); FreeSpaceForFastApiCall(masm());
HandlerFrontendFooter(&miss_before_stack_reserved); __ bind(&miss_before_stack_reserved);
GenerateMissBranch();
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
...@@ -2338,7 +2376,7 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { ...@@ -2338,7 +2376,7 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
if (!object.is_null() && object->IsGlobalObject()) { if (object->IsGlobalObject()) {
const int argc = arguments().immediate(); const int argc = arguments().immediate();
const int receiver_offset = argc * kPointerSize; const int receiver_offset = argc * kPointerSize;
__ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
...@@ -2434,18 +2472,39 @@ Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, ...@@ -2434,18 +2472,39 @@ Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
} }
void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) {
Register function, CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
Label* miss) { ? CALL_AS_FUNCTION
ASSERT(function.is(r1)); : CALL_AS_METHOD;
// Check that the function really is a function. ParameterCount expected(function);
GenerateFunctionCheck(function, r3, miss); __ InvokeFunction(function, expected, arguments(),
if (!function.is(r1)) __ mov(r1, function); JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
Handle<Code> CallStubCompiler::CompileCallConstant(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check,
Handle<JSFunction> function) {
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
Handle<Cell>::null(),
function, Handle<String>::cast(name),
Code::FAST);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
Label miss;
HandlerFrontendHeader(object, holder, name, check, &miss);
PatchGlobalProxy(object); PatchGlobalProxy(object);
CompileHandlerBackend(function);
HandlerFrontendFooter(&miss);
// Invoke the function. // Return the generated code.
__ InvokeFunction(r1, arguments(), JUMP_FUNCTION, return GetCode(function);
NullCallWrapper(), call_kind());
} }
...@@ -2472,9 +2531,11 @@ Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, ...@@ -2472,9 +2531,11 @@ Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
// Restore receiver. // Restore receiver.
__ ldr(r0, MemOperand(sp, argc * kPointerSize)); __ ldr(r0, MemOperand(sp, argc * kPointerSize));
GenerateJumpFunction(object, r1, &miss); GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
HandlerFrontendFooter(&miss); // Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
// Return the generated code. // Return the generated code.
return GetCode(Code::FAST, name); return GetCode(Code::FAST, name);
...@@ -2497,13 +2558,26 @@ Handle<Code> CallStubCompiler::CompileCallGlobal( ...@@ -2497,13 +2558,26 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
Label miss; Label miss;
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
// Potentially loads a closure that matches the shared function info of the
// function, rather than function.
GenerateLoadFunctionFromCell(cell, function, &miss); GenerateLoadFunctionFromCell(cell, function, &miss);
PatchGlobalProxy(object);
// Set up the context (function already in r1).
__ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
// Jump to the cached code (tail call).
Counters* counters = isolate()->counters(); Counters* counters = isolate()->counters();
__ IncrementCounter(counters->call_global_inline(), 1, r3, r4); __ IncrementCounter(counters->call_global_inline(), 1, r3, r4);
GenerateJumpFunction(object, r1, function); ParameterCount expected(function->shared()->formal_parameter_count());
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
// We call indirectly through the code field in the function to
// allow recompilation to take effect without changing any of the
// call sites.
__ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
__ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
// Return the generated code. // Return the generated code.
......
...@@ -2636,7 +2636,7 @@ void MacroAssembler::InvokeFunction(Register fun, ...@@ -2636,7 +2636,7 @@ void MacroAssembler::InvokeFunction(Register fun,
} }
void MacroAssembler::InvokeFunction(Register fun, void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected, const ParameterCount& expected,
const ParameterCount& actual, const ParameterCount& actual,
InvokeFlag flag, InvokeFlag flag,
...@@ -2645,25 +2645,18 @@ void MacroAssembler::InvokeFunction(Register fun, ...@@ -2645,25 +2645,18 @@ void MacroAssembler::InvokeFunction(Register fun,
// You can't call a function without a valid frame. // You can't call a function without a valid frame.
ASSERT(flag == JUMP_FUNCTION || has_frame()); ASSERT(flag == JUMP_FUNCTION || has_frame());
ASSERT(fun.is(edi)); // Get the function and setup the context.
LoadHeapObject(edi, function);
mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
// We call indirectly through the code field in the function to
// allow recompilation to take effect without changing any of the
// call sites.
InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
expected, actual, flag, call_wrapper, call_kind); expected, actual, flag, call_wrapper, call_kind);
} }
void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind) {
LoadHeapObject(edi, function);
InvokeFunction(edi, expected, actual, flag, call_wrapper, call_kind);
}
void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper) { const CallWrapper& call_wrapper) {
......
...@@ -349,13 +349,6 @@ class MacroAssembler: public Assembler { ...@@ -349,13 +349,6 @@ class MacroAssembler: public Assembler {
const CallWrapper& call_wrapper, const CallWrapper& call_wrapper,
CallKind call_kind); CallKind call_kind);
void InvokeFunction(Register function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind);
void InvokeFunction(Handle<JSFunction> function, void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected, const ParameterCount& expected,
const ParameterCount& actual, const ParameterCount& actual,
......
...@@ -645,7 +645,7 @@ static void GenerateFastApiCallBody(MacroAssembler* masm, ...@@ -645,7 +645,7 @@ static void GenerateFastApiCallBody(MacroAssembler* masm,
class CallInterceptorCompiler BASE_EMBEDDED { class CallInterceptorCompiler BASE_EMBEDDED {
public: public:
CallInterceptorCompiler(CallStubCompiler* stub_compiler, CallInterceptorCompiler(StubCompiler* stub_compiler,
const ParameterCount& arguments, const ParameterCount& arguments,
Register name, Register name,
ExtraICState extra_state) ExtraICState extra_state)
...@@ -756,8 +756,13 @@ class CallInterceptorCompiler BASE_EMBEDDED { ...@@ -756,8 +756,13 @@ class CallInterceptorCompiler BASE_EMBEDDED {
if (can_do_fast_api_call) { if (can_do_fast_api_call) {
GenerateFastApiCall(masm, optimization, arguments_.immediate()); GenerateFastApiCall(masm, optimization, arguments_.immediate());
} else { } else {
Handle<JSFunction> fun = optimization.constant_function(); CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
stub_compiler_->GenerateJumpFunction(object, fun); ? CALL_AS_FUNCTION
: CALL_AS_METHOD;
Handle<JSFunction> function = optimization.constant_function();
ParameterCount expected(function);
__ InvokeFunction(function, expected, arguments_,
JUMP_FUNCTION, NullCallWrapper(), call_kind);
} }
// Deferred code for fast API call case---clean preallocated space. // Deferred code for fast API call case---clean preallocated space.
...@@ -825,7 +830,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { ...@@ -825,7 +830,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
__ j(not_equal, interceptor_succeeded); __ j(not_equal, interceptor_succeeded);
} }
CallStubCompiler* stub_compiler_; StubCompiler* stub_compiler_;
const ParameterCount& arguments_; const ParameterCount& arguments_;
Register name_; Register name_;
ExtraICState extra_state_; ExtraICState extra_state_;
...@@ -1597,15 +1602,6 @@ void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { ...@@ -1597,15 +1602,6 @@ void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
} }
void CallStubCompiler::GenerateFunctionCheck(Register function,
Register scratch,
Label* miss) {
__ JumpIfSmi(function, miss);
__ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
__ j(not_equal, miss);
}
void CallStubCompiler::GenerateLoadFunctionFromCell( void CallStubCompiler::GenerateLoadFunctionFromCell(
Handle<Cell> cell, Handle<Cell> cell,
Handle<JSFunction> function, Handle<JSFunction> function,
...@@ -1625,7 +1621,9 @@ void CallStubCompiler::GenerateLoadFunctionFromCell( ...@@ -1625,7 +1621,9 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(
// the nice side effect that multiple closures based on the same // the nice side effect that multiple closures based on the same
// function can all use this call IC. Before we load through the // function can all use this call IC. Before we load through the
// function, we have to verify that it still is a function. // function, we have to verify that it still is a function.
GenerateFunctionCheck(edi, ebx, miss); __ JumpIfSmi(edi, miss);
__ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
__ j(not_equal, miss);
// Check the shared function info. Make sure it hasn't changed. // Check the shared function info. Make sure it hasn't changed.
__ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset),
...@@ -1658,7 +1656,20 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, ...@@ -1658,7 +1656,20 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
GenerateFastPropertyLoad( GenerateFastPropertyLoad(
masm(), edi, reg, index.is_inobject(holder), masm(), edi, reg, index.is_inobject(holder),
index.translate(holder), Representation::Tagged()); index.translate(holder), Representation::Tagged());
GenerateJumpFunction(object, edi, &miss);
// Check that the function really is a function.
__ JumpIfSmi(edi, &miss);
__ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
__ j(not_equal, &miss);
PatchGlobalProxy(object);
// Invoke the function.
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
...@@ -2070,7 +2081,8 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( ...@@ -2070,7 +2081,8 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
__ bind(&miss); __ bind(&miss);
// Restore function name in ecx. // Restore function name in ecx.
__ Set(ecx, Immediate(name)); __ Set(ecx, Immediate(name));
HandlerFrontendFooter(&name_miss); __ bind(&name_miss);
GenerateMissBranch();
// Return the generated code. // Return the generated code.
return GetCode(type, name); return GetCode(type, name);
...@@ -2138,7 +2150,8 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall( ...@@ -2138,7 +2150,8 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
__ bind(&miss); __ bind(&miss);
// Restore function name in ecx. // Restore function name in ecx.
__ Set(ecx, Immediate(name)); __ Set(ecx, Immediate(name));
HandlerFrontendFooter(&name_miss); __ bind(&name_miss);
GenerateMissBranch();
// Return the generated code. // Return the generated code.
return GetCode(type, name); return GetCode(type, name);
...@@ -2187,10 +2200,15 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( ...@@ -2187,10 +2200,15 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
StubRuntimeCallHelper call_helper; StubRuntimeCallHelper call_helper;
generator.GenerateSlow(masm(), call_helper); generator.GenerateSlow(masm(), call_helper);
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow); __ bind(&slow);
// We do not have to patch the receiver because the function makes no use of CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
// it. ? CALL_AS_FUNCTION
GenerateJumpFunctionIgnoreReceiver(function); : CALL_AS_METHOD;
ParameterCount expected(function);
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
...@@ -2297,10 +2315,12 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall( ...@@ -2297,10 +2315,12 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
__ mov(eax, Operand(esp, 1 * kPointerSize)); __ mov(eax, Operand(esp, 1 * kPointerSize));
__ ret(2 * kPointerSize); __ ret(2 * kPointerSize);
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow); __ bind(&slow);
// We do not have to patch the receiver because the function makes no use of ParameterCount expected(function);
// it. __ InvokeFunction(function, expected, arguments(),
GenerateJumpFunctionIgnoreReceiver(function); JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
...@@ -2384,10 +2404,12 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall( ...@@ -2384,10 +2404,12 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
__ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
__ ret(2 * kPointerSize); __ ret(2 * kPointerSize);
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow); __ bind(&slow);
// We do not have to patch the receiver because the function makes no use of ParameterCount expected(function);
// it. __ InvokeFunction(function, expected, arguments(),
GenerateJumpFunctionIgnoreReceiver(function); JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
...@@ -2447,7 +2469,8 @@ Handle<Code> CallStubCompiler::CompileFastApiCall( ...@@ -2447,7 +2469,8 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
__ bind(&miss); __ bind(&miss);
__ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); __ add(esp, Immediate(kFastApiCallArguments * kPointerSize));
HandlerFrontendFooter(&miss_before_stack_reserved); __ bind(&miss_before_stack_reserved);
GenerateMissBranch();
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
...@@ -2466,7 +2489,7 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { ...@@ -2466,7 +2489,7 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
if (!object.is_null() && object->IsGlobalObject()) { if (object->IsGlobalObject()) {
const int argc = arguments().immediate(); const int argc = arguments().immediate();
const int receiver_offset = (argc + 1) * kPointerSize; const int receiver_offset = (argc + 1) * kPointerSize;
__ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
...@@ -2556,18 +2579,40 @@ Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, ...@@ -2556,18 +2579,40 @@ Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
} }
void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) {
Register function, CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
Label* miss) { ? CALL_AS_FUNCTION
// Check that the function really is a function. : CALL_AS_METHOD;
GenerateFunctionCheck(function, ebx, miss); ParameterCount expected(function);
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
if (!function.is(edi)) __ mov(edi, function); Handle<Code> CallStubCompiler::CompileCallConstant(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check,
Handle<JSFunction> function) {
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
Handle<Cell>::null(),
function, Handle<String>::cast(name),
Code::FAST);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
Label miss;
HandlerFrontendHeader(object, holder, name, check, &miss);
PatchGlobalProxy(object); PatchGlobalProxy(object);
CompileHandlerBackend(function);
HandlerFrontendFooter(&miss);
// Invoke the function. // Return the generated code.
__ InvokeFunction(edi, arguments(), JUMP_FUNCTION, return GetCode(function);
NullCallWrapper(), call_kind());
} }
...@@ -2594,9 +2639,29 @@ Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, ...@@ -2594,9 +2639,29 @@ Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
// Restore receiver. // Restore receiver.
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
GenerateJumpFunction(object, eax, &miss); // Check that the function really is a function.
__ JumpIfSmi(eax, &miss);
__ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
__ j(not_equal, &miss);
HandlerFrontendFooter(&miss); // Patch the receiver on the stack with the global proxy if
// necessary.
if (object->IsGlobalObject()) {
__ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
__ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
}
// Invoke the function.
__ mov(edi, eax);
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
// Handle load cache miss.
__ bind(&miss);
GenerateMissBranch();
// Return the generated code. // Return the generated code.
return GetCode(Code::FAST, name); return GetCode(Code::FAST, name);
...@@ -2619,10 +2684,25 @@ Handle<Code> CallStubCompiler::CompileCallGlobal( ...@@ -2619,10 +2684,25 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
Label miss; Label miss;
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
// Potentially loads a closure that matches the shared function info of the
// function, rather than function.
GenerateLoadFunctionFromCell(cell, function, &miss); GenerateLoadFunctionFromCell(cell, function, &miss);
GenerateJumpFunction(object, edi, function); PatchGlobalProxy(object);
// Set up the context (function already in edi).
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
// Jump to the cached code (tail call).
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->call_global_inline(), 1);
ParameterCount expected(function->shared()->formal_parameter_count());
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
// We call indirectly through the code field in the function to
// allow recompilation to take effect without changing any of the
// call sites.
__ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
expected, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
......
...@@ -1128,69 +1128,12 @@ void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder, ...@@ -1128,69 +1128,12 @@ void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
#define __ ACCESS_MASM(masm()) #define __ ACCESS_MASM(masm())
CallKind CallStubCompiler::call_kind() {
return CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
}
void CallStubCompiler::HandlerFrontendFooter(Label* miss) { void CallStubCompiler::HandlerFrontendFooter(Label* miss) {
__ bind(miss); __ bind(miss);
GenerateMissBranch(); GenerateMissBranch();
} }
void CallStubCompiler::GenerateJumpFunctionIgnoreReceiver(
Handle<JSFunction> function) {
ParameterCount expected(function);
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind());
}
void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
Handle<JSFunction> function) {
PatchGlobalProxy(object);
GenerateJumpFunctionIgnoreReceiver(function);
}
void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
Register actual_closure,
Handle<JSFunction> function) {
PatchGlobalProxy(object);
ParameterCount expected(function);
__ InvokeFunction(actual_closure, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind());
}
Handle<Code> CallStubCompiler::CompileCallConstant(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check,
Handle<JSFunction> function) {
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
Handle<Cell>::null(),
function, Handle<String>::cast(name),
Code::FAST);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
Label miss;
HandlerFrontendHeader(object, holder, name, check, &miss);
GenerateJumpFunction(object, function);
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(function);
}
Register LoadStubCompiler::HandlerFrontendHeader( Register LoadStubCompiler::HandlerFrontendHeader(
Handle<Type> type, Handle<Type> type,
Register object_reg, Register object_reg,
......
...@@ -919,17 +919,7 @@ class CallStubCompiler: public StubCompiler { ...@@ -919,17 +919,7 @@ class CallStubCompiler: public StubCompiler {
Label* miss); Label* miss);
void HandlerFrontendFooter(Label* miss); void HandlerFrontendFooter(Label* miss);
void GenerateJumpFunctionIgnoreReceiver(Handle<JSFunction> function); void CompileHandlerBackend(Handle<JSFunction> function);
void GenerateJumpFunction(Handle<Object> object,
Handle<JSFunction> function);
void GenerateJumpFunction(Handle<Object> object,
Register function,
Label* miss);
// Use to call |actual_closure|, a closure with the same shared function info
// as |function|.
void GenerateJumpFunction(Handle<Object> object,
Register actual_closure,
Handle<JSFunction> function);
Handle<Code> CompileCallConstant(Handle<Object> object, Handle<Code> CompileCallConstant(Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
...@@ -978,8 +968,6 @@ class CallStubCompiler: public StubCompiler { ...@@ -978,8 +968,6 @@ class CallStubCompiler: public StubCompiler {
Handle<JSFunction> function, Handle<JSFunction> function,
Handle<String> name); Handle<String> name);
CallKind call_kind();
Handle<Code> GetCode(Code::StubType type, Handle<Name> name); Handle<Code> GetCode(Code::StubType type, Handle<Name> name);
Handle<Code> GetCode(Handle<JSFunction> function); Handle<Code> GetCode(Handle<JSFunction> function);
...@@ -993,8 +981,6 @@ class CallStubCompiler: public StubCompiler { ...@@ -993,8 +981,6 @@ class CallStubCompiler: public StubCompiler {
Handle<JSFunction> function, Handle<JSFunction> function,
Label* miss); Label* miss);
void GenerateFunctionCheck(Register function, Register scratch, Label* miss);
// Generates a jump to CallIC miss stub. // Generates a jump to CallIC miss stub.
void GenerateMissBranch(); void GenerateMissBranch();
......
...@@ -3601,7 +3601,7 @@ void MacroAssembler::InvokeFunction(Register function, ...@@ -3601,7 +3601,7 @@ void MacroAssembler::InvokeFunction(Register function,
} }
void MacroAssembler::InvokeFunction(Register function, void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected, const ParameterCount& expected,
const ParameterCount& actual, const ParameterCount& actual,
InvokeFlag flag, InvokeFlag flag,
...@@ -3610,27 +3610,18 @@ void MacroAssembler::InvokeFunction(Register function, ...@@ -3610,27 +3610,18 @@ void MacroAssembler::InvokeFunction(Register function,
// You can't call a function without a valid frame. // You can't call a function without a valid frame.
ASSERT(flag == JUMP_FUNCTION || has_frame()); ASSERT(flag == JUMP_FUNCTION || has_frame());
ASSERT(function.is(rdi)); // Get the function and setup the context.
movq(rsi, FieldOperand(function, JSFunction::kContextOffset)); Move(rdi, function);
// Advances rdx to the end of the Code object header, to the start of movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
// the executable code.
movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
// We call indirectly through the code field in the function to
// allow recompilation to take effect without changing any of the
// call sites.
movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind); InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind);
} }
void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind) {
Move(rdi, function);
InvokeFunction(rdi, expected, actual, flag, call_wrapper, call_kind);
}
void MacroAssembler::InvokePrologue(const ParameterCount& expected, void MacroAssembler::InvokePrologue(const ParameterCount& expected,
const ParameterCount& actual, const ParameterCount& actual,
Handle<Code> code_constant, Handle<Code> code_constant,
......
...@@ -371,13 +371,6 @@ class MacroAssembler: public Assembler { ...@@ -371,13 +371,6 @@ class MacroAssembler: public Assembler {
const CallWrapper& call_wrapper, const CallWrapper& call_wrapper,
CallKind call_kind); CallKind call_kind);
void InvokeFunction(Register function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind);
void InvokeFunction(Handle<JSFunction> function, void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected, const ParameterCount& expected,
const ParameterCount& actual, const ParameterCount& actual,
......
...@@ -637,7 +637,7 @@ static void GenerateFastApiCallBody(MacroAssembler* masm, ...@@ -637,7 +637,7 @@ static void GenerateFastApiCallBody(MacroAssembler* masm,
class CallInterceptorCompiler BASE_EMBEDDED { class CallInterceptorCompiler BASE_EMBEDDED {
public: public:
CallInterceptorCompiler(CallStubCompiler* stub_compiler, CallInterceptorCompiler(StubCompiler* stub_compiler,
const ParameterCount& arguments, const ParameterCount& arguments,
Register name, Register name,
ExtraICState extra_ic_state) ExtraICState extra_ic_state)
...@@ -748,8 +748,13 @@ class CallInterceptorCompiler BASE_EMBEDDED { ...@@ -748,8 +748,13 @@ class CallInterceptorCompiler BASE_EMBEDDED {
if (can_do_fast_api_call) { if (can_do_fast_api_call) {
GenerateFastApiCall(masm, optimization, arguments_.immediate()); GenerateFastApiCall(masm, optimization, arguments_.immediate());
} else { } else {
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
Handle<JSFunction> fun = optimization.constant_function(); Handle<JSFunction> fun = optimization.constant_function();
stub_compiler_->GenerateJumpFunction(object, fun); ParameterCount expected(fun);
__ InvokeFunction(fun, expected, arguments_,
JUMP_FUNCTION, NullCallWrapper(), call_kind);
} }
// Deferred code for fast API call case---clean preallocated space. // Deferred code for fast API call case---clean preallocated space.
...@@ -817,7 +822,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { ...@@ -817,7 +822,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
__ j(not_equal, interceptor_succeeded); __ j(not_equal, interceptor_succeeded);
} }
CallStubCompiler* stub_compiler_; StubCompiler* stub_compiler_;
const ParameterCount& arguments_; const ParameterCount& arguments_;
Register name_; Register name_;
ExtraICState extra_ic_state_; ExtraICState extra_ic_state_;
...@@ -1532,15 +1537,6 @@ void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { ...@@ -1532,15 +1537,6 @@ void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
} }
void CallStubCompiler::GenerateFunctionCheck(Register function,
Register scratch,
Label* miss) {
__ JumpIfSmi(function, miss);
__ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
__ j(not_equal, miss);
}
void CallStubCompiler::GenerateLoadFunctionFromCell( void CallStubCompiler::GenerateLoadFunctionFromCell(
Handle<Cell> cell, Handle<Cell> cell,
Handle<JSFunction> function, Handle<JSFunction> function,
...@@ -1556,7 +1552,9 @@ void CallStubCompiler::GenerateLoadFunctionFromCell( ...@@ -1556,7 +1552,9 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(
// the nice side effect that multiple closures based on the same // the nice side effect that multiple closures based on the same
// function can all use this call IC. Before we load through the // function can all use this call IC. Before we load through the
// function, we have to verify that it still is a function. // function, we have to verify that it still is a function.
GenerateFunctionCheck(rdi, rax, miss); __ JumpIfSmi(rdi, miss);
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax);
__ j(not_equal, miss);
// Check the shared function info. Make sure it hasn't changed. // Check the shared function info. Make sure it hasn't changed.
__ Move(rax, Handle<SharedFunctionInfo>(function->shared())); __ Move(rax, Handle<SharedFunctionInfo>(function->shared()));
...@@ -1588,7 +1586,20 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, ...@@ -1588,7 +1586,20 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder),
index.translate(holder), Representation::Tagged()); index.translate(holder), Representation::Tagged());
GenerateJumpFunction(object, rdi, &miss);
// Check that the function really is a function.
__ JumpIfSmi(rdi, &miss);
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx);
__ j(not_equal, &miss);
PatchGlobalProxy(object);
// Invoke the function.
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
...@@ -2003,7 +2014,8 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( ...@@ -2003,7 +2014,8 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
__ bind(&miss); __ bind(&miss);
// Restore function name in rcx. // Restore function name in rcx.
__ Move(rcx, name); __ Move(rcx, name);
HandlerFrontendFooter(&name_miss); __ bind(&name_miss);
GenerateMissBranch();
// Return the generated code. // Return the generated code.
return GetCode(type, name); return GetCode(type, name);
...@@ -2068,7 +2080,8 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall( ...@@ -2068,7 +2080,8 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
__ bind(&miss); __ bind(&miss);
// Restore function name in rcx. // Restore function name in rcx.
__ Move(rcx, name); __ Move(rcx, name);
HandlerFrontendFooter(&name_miss); __ bind(&name_miss);
GenerateMissBranch();
// Return the generated code. // Return the generated code.
return GetCode(type, name); return GetCode(type, name);
...@@ -2114,10 +2127,15 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( ...@@ -2114,10 +2127,15 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
StubRuntimeCallHelper call_helper; StubRuntimeCallHelper call_helper;
generator.GenerateSlow(masm(), call_helper); generator.GenerateSlow(masm(), call_helper);
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow); __ bind(&slow);
// We do not have to patch the receiver because the function makes no use of CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
// it. ? CALL_AS_FUNCTION
GenerateJumpFunctionIgnoreReceiver(function); : CALL_AS_METHOD;
ParameterCount expected(function);
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
...@@ -2220,10 +2238,12 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall( ...@@ -2220,10 +2238,12 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
__ movq(rax, args.GetArgumentOperand(1)); __ movq(rax, args.GetArgumentOperand(1));
__ ret(2 * kPointerSize); __ ret(2 * kPointerSize);
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow); __ bind(&slow);
// We do not have to patch the receiver because the function makes no use of ParameterCount expected(function);
// it. __ InvokeFunction(function, expected, arguments(),
GenerateJumpFunctionIgnoreReceiver(function); JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
...@@ -2304,10 +2324,15 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall( ...@@ -2304,10 +2324,15 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
__ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), rbx); __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), rbx);
__ ret(2 * kPointerSize); __ ret(2 * kPointerSize);
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow); __ bind(&slow);
// We do not have to patch the receiver because the function makes no use of CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
// it. ? CALL_AS_FUNCTION
GenerateJumpFunctionIgnoreReceiver(function); : CALL_AS_METHOD;
ParameterCount expected(function);
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
...@@ -2365,7 +2390,8 @@ Handle<Code> CallStubCompiler::CompileFastApiCall( ...@@ -2365,7 +2390,8 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
__ bind(&miss); __ bind(&miss);
__ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
HandlerFrontendFooter(&miss_before_stack_reserved); __ bind(&miss_before_stack_reserved);
GenerateMissBranch();
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
...@@ -2384,7 +2410,7 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { ...@@ -2384,7 +2410,7 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
if (!object.is_null() && object->IsGlobalObject()) { if (object->IsGlobalObject()) {
StackArgumentsAccessor args(rsp, arguments()); StackArgumentsAccessor args(rsp, arguments());
__ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
__ movq(args.GetReceiverOperand(), rdx); __ movq(args.GetReceiverOperand(), rdx);
...@@ -2473,18 +2499,39 @@ Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, ...@@ -2473,18 +2499,39 @@ Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
} }
void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) {
Register function, CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
Label* miss) { ? CALL_AS_FUNCTION
// Check that the function really is a function. : CALL_AS_METHOD;
GenerateFunctionCheck(function, rbx, miss); ParameterCount expected(function);
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
if (!function.is(rdi)) __ movq(rdi, function); Handle<Code> CallStubCompiler::CompileCallConstant(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check,
Handle<JSFunction> function) {
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
Handle<PropertyCell>::null(),
function, Handle<String>::cast(name),
Code::FAST);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
Label miss;
HandlerFrontendHeader(object, holder, name, check, &miss);
PatchGlobalProxy(object); PatchGlobalProxy(object);
CompileHandlerBackend(function);
HandlerFrontendFooter(&miss);
// Invoke the function. // Return the generated code.
__ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, return GetCode(function);
NullCallWrapper(), call_kind());
} }
...@@ -2508,9 +2555,29 @@ Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, ...@@ -2508,9 +2555,29 @@ Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
// Restore receiver. // Restore receiver.
__ movq(rdx, args.GetReceiverOperand()); __ movq(rdx, args.GetReceiverOperand());
GenerateJumpFunction(object, rax, &miss); // Check that the function really is a function.
__ JumpIfSmi(rax, &miss);
__ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
__ j(not_equal, &miss);
HandlerFrontendFooter(&miss); // Patch the receiver on the stack with the global proxy if
// necessary.
if (object->IsGlobalObject()) {
__ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
__ movq(args.GetReceiverOperand(), rdx);
}
// Invoke the function.
__ movq(rdi, rax);
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
// Handle load cache miss.
__ bind(&miss);
GenerateMissBranch();
// Return the generated code. // Return the generated code.
return GetCode(Code::FAST, name); return GetCode(Code::FAST, name);
...@@ -2533,12 +2600,26 @@ Handle<Code> CallStubCompiler::CompileCallGlobal( ...@@ -2533,12 +2600,26 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
Label miss; Label miss;
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
// Potentially loads a closure that matches the shared function info of the
// function, rather than function.
GenerateLoadFunctionFromCell(cell, function, &miss); GenerateLoadFunctionFromCell(cell, function, &miss);
PatchGlobalProxy(object);
// Set up the context (function already in rdi).
__ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
// Jump to the cached code (tail call).
Counters* counters = isolate()->counters(); Counters* counters = isolate()->counters();
__ IncrementCounter(counters->call_global_inline(), 1); __ IncrementCounter(counters->call_global_inline(), 1);
GenerateJumpFunction(object, rdi, function); ParameterCount expected(function->shared()->formal_parameter_count());
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
// We call indirectly through the code field in the function to
// allow recompilation to take effect without changing any of the
// call sites.
__ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
__ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
HandlerFrontendFooter(&miss); HandlerFrontendFooter(&miss);
// Return the generated code. // Return the generated code.
......
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