Chromium Code Reviews| Index: src/arm/stub-cache-arm.cc |
| diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc |
| index 4d5f220a2982da97c383aefa7be95fac6cd455ec..5d1957d135a73c793e34a4f125dab1422fd152e3 100644 |
| --- a/src/arm/stub-cache-arm.cc |
| +++ b/src/arm/stub-cache-arm.cc |
| @@ -742,36 +742,6 @@ 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, |
| Register receiver, |
| Register holder, |
| @@ -960,7 +930,7 @@ static void GenerateFastApiCall(MacroAssembler* masm, |
| class CallInterceptorCompiler BASE_EMBEDDED { |
| public: |
| - CallInterceptorCompiler(StubCompiler* stub_compiler, |
| + CallInterceptorCompiler(CallStubCompiler* stub_compiler, |
| const ParameterCount& arguments, |
| Register name, |
| Code::ExtraICState extra_ic_state) |
| @@ -1072,13 +1042,8 @@ class CallInterceptorCompiler BASE_EMBEDDED { |
| GenerateFastApiDirectCall( |
| masm, optimization, arguments_.immediate(), false); |
| } else { |
| - CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| - ? CALL_AS_FUNCTION |
| - : CALL_AS_METHOD; |
| Handle<JSFunction> function = optimization.constant_function(); |
| - ParameterCount expected(function); |
| - __ InvokeFunction(function, expected, arguments_, |
| - JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| + stub_compiler_->GenerateCallFunction(object, function); |
| } |
| // Deferred code for fast API call case---clean preallocated space. |
| @@ -1146,7 +1111,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { |
| __ b(ne, interceptor_succeeded); |
| } |
| - StubCompiler* stub_compiler_; |
| + CallStubCompiler* stub_compiler_; |
| const ParameterCount& arguments_; |
| Register name_; |
| Code::ExtraICState extra_ic_state_; |
| @@ -1549,6 +1514,15 @@ 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( |
| Handle<Cell> cell, |
| Handle<JSFunction> function, |
| @@ -1564,9 +1538,7 @@ void CallStubCompiler::GenerateLoadFunctionFromCell( |
| // the nice side effect that multiple closures based on the same |
| // function can all use this call IC. Before we load through the |
| // function, we have to verify that it still is a function. |
| - __ JumpIfSmi(r1, miss); |
| - __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
| - __ b(ne, miss); |
| + GenerateFunctionCheck(r1, r3, miss); |
| // Check the shared function info. Make sure it hasn't changed. |
| __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); |
| @@ -1598,8 +1570,7 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder), |
| index.translate(holder), Representation::Tagged()); |
| - |
| - GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); |
| + GenerateCallFunction(object, r1, &miss); |
| HandlerFrontendFooter(&miss); |
| @@ -2014,8 +1985,7 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( |
| __ bind(&miss); |
| // Restore function name in r2. |
| __ Move(r2, name); |
| - __ bind(&name_miss); |
| - GenerateMissBranch(); |
| + HandlerFrontendFooter(&name_miss); |
| // Return the generated code. |
| return GetCode(type, name); |
| @@ -2081,8 +2051,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| __ bind(&miss); |
| // Restore function name in r2. |
| __ Move(r2, name); |
| - __ bind(&name_miss); |
| - GenerateMissBranch(); |
| + HandlerFrontendFooter(&name_miss); |
| // Return the generated code. |
| return GetCode(type, name); |
| @@ -2129,12 +2098,10 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| StubRuntimeCallHelper 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); |
| - ParameterCount expected(function); |
| - __ InvokeFunction(function, expected, arguments(), |
| - JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
| + // We do not have to patch the receiver because the function makes no use of |
| + // it. |
| + GenerateCallFunction(Handle<Object>::null(), function); |
|
Igor Sheludko
2013/11/28 13:06:08
Consider introducing different function for such a
Toon Verwaest
2013/11/28 15:24:09
Done.
|
| HandlerFrontendFooter(&miss); |
| @@ -2222,11 +2189,9 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| __ Ret(); |
| __ bind(&slow); |
| - // Tail call the full function. We do not have to patch the receiver |
| - // because the function makes no use of it. |
| - ParameterCount expected(function); |
| - __ InvokeFunction(function, expected, arguments(), |
| - JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
| + // We do not have to patch the receiver because the function makes no use of |
| + // it. |
| + GenerateCallFunction(Handle<Object>::null(), function); |
| HandlerFrontendFooter(&miss); |
| @@ -2304,12 +2269,10 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| __ Drop(argc + 1); |
| __ Ret(); |
| - // Tail call the full function. We do not have to patch the receiver |
| - // because the function makes no use of it. |
| __ bind(&slow); |
| - ParameterCount expected(function); |
| - __ InvokeFunction(function, expected, arguments(), |
| - JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
| + // We do not have to patch the receiver because the function makes no use of |
| + // it. |
| + GenerateCallFunction(Handle<Object>::null(), function); |
| HandlerFrontendFooter(&miss); |
| @@ -2362,8 +2325,7 @@ Handle<Code> CallStubCompiler::CompileFastApiCall( |
| __ bind(&miss); |
| FreeSpaceForFastApiCall(masm()); |
| - __ bind(&miss_before_stack_reserved); |
| - GenerateMissBranch(); |
| + HandlerFrontendFooter(&miss_before_stack_reserved); |
| // Return the generated code. |
| return GetCode(function); |
| @@ -2384,7 +2346,7 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
| void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
| - if (object->IsGlobalObject()) { |
| + if (!object.is_null() && object->IsGlobalObject()) { |
| const int argc = arguments().immediate(); |
| const int receiver_offset = argc * kPointerSize; |
| __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); |
| @@ -2480,39 +2442,18 @@ Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, |
| } |
| -void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { |
| - CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| - ? CALL_AS_FUNCTION |
| - : CALL_AS_METHOD; |
| - ParameterCount expected(function); |
| - __ InvokeFunction(function, 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); |
| +void CallStubCompiler::GenerateCallFunction(Handle<Object> object, |
| + Register function, |
| + Label* miss) { |
| + ASSERT(function.is(r1)); |
| + // Check that the function really is a function. |
| + GenerateFunctionCheck(function, r3, miss); |
| + if (!function.is(r1)) __ mov(r1, function); |
| PatchGlobalProxy(object); |
| - CompileHandlerBackend(function); |
| - HandlerFrontendFooter(&miss); |
| - // Return the generated code. |
| - return GetCode(function); |
| + // Invoke the function. |
| + __ InvokeFunction(r1, arguments(), JUMP_FUNCTION, |
| + NullCallWrapper(), call_kind()); |
| } |
| @@ -2539,11 +2480,9 @@ Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| // Restore receiver. |
| __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
| - GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); |
| + GenerateCallFunction(object, r0, &miss); |
| - // Handle call cache miss. |
| - __ bind(&miss); |
| - GenerateMissBranch(); |
| + HandlerFrontendFooter(&miss); |
| // Return the generated code. |
| return GetCode(Code::FAST, name); |
| @@ -2566,26 +2505,13 @@ Handle<Code> CallStubCompiler::CompileCallGlobal( |
| Label 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); |
| - 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(); |
| __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); |
| - 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); |
| - |
| + GenerateCallFunction(object, r1, function); |
| HandlerFrontendFooter(&miss); |
| // Return the generated code. |