diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index 703fe75436..04aa9c9715 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -3728,7 +3728,7 @@ void MacroAssembler::InvokeFunction(Register function, } -void MacroAssembler::InvokeFunction(Register function, +void MacroAssembler::InvokeFunction(Handle function, const ParameterCount& expected, const ParameterCount& actual, InvokeFlag flag, @@ -3737,10 +3737,8 @@ void MacroAssembler::InvokeFunction(Register function, // You can't call a function without a valid frame. ASSERT(flag == JUMP_FUNCTION || has_frame()); - // Contract with called JS functions requires that function is passed in a1. - ASSERT(function.is(a1)); - // Get the function and setup the context. + li(a1, function); lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); // We call indirectly through the code field in the function to @@ -3751,17 +3749,6 @@ void MacroAssembler::InvokeFunction(Register function, } -void MacroAssembler::InvokeFunction(Handle function, - const ParameterCount& expected, - const ParameterCount& actual, - InvokeFlag flag, - const CallWrapper& call_wrapper, - CallKind call_kind) { - li(a1, function); - InvokeFunction(a1, expected, actual, flag, call_wrapper, call_kind); -} - - void MacroAssembler::IsObjectJSObjectType(Register heap_object, Register map, Register scratch, diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h index 4bf3e89133..e4187c0fb4 100644 --- a/src/mips/macro-assembler-mips.h +++ b/src/mips/macro-assembler-mips.h @@ -917,13 +917,6 @@ class MacroAssembler: public Assembler { const CallWrapper& call_wrapper, 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 function, const ParameterCount& expected, const ParameterCount& actual, diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc index 4190e628c0..748a783c51 100644 --- a/src/mips/stub-cache-mips.cc +++ b/src/mips/stub-cache-mips.cc @@ -732,6 +732,35 @@ void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, } +static void GenerateCallFunction(MacroAssembler* masm, + Handle object, + const ParameterCount& arguments, + Label* miss, + ExtraICState extra_ic_state) { + // ----------- S t a t e ------------- + // -- a0: receiver + // -- a1: function to call + // ----------------------------------- + // Check that the function really is a function. + __ JumpIfSmi(a1, miss); + __ GetObjectType(a1, a3, a3); + __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); + + if (object->IsGlobalObject()) { + const int argc = arguments.immediate(); + const int receiver_offset = argc * kPointerSize; + __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); + __ sw(a3, MemOperand(sp, receiver_offset)); + } + + // Invoke the function. + CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) + ? CALL_AS_FUNCTION + : CALL_AS_METHOD; + __ InvokeFunction(a1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); +} + + static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, Register holder, @@ -913,7 +942,7 @@ static void GenerateFastApiCall(MacroAssembler* masm, class CallInterceptorCompiler BASE_EMBEDDED { public: - CallInterceptorCompiler(CallStubCompiler* stub_compiler, + CallInterceptorCompiler(StubCompiler* stub_compiler, const ParameterCount& arguments, Register name, ExtraICState extra_ic_state) @@ -1025,8 +1054,13 @@ 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 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. @@ -1092,7 +1126,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { __ Branch(interceptor_succeeded, ne, v0, Operand(scratch)); } - CallStubCompiler* stub_compiler_; + StubCompiler* stub_compiler_; const ParameterCount& arguments_; Register name_; ExtraICState extra_ic_state_; @@ -1493,15 +1527,6 @@ void CallStubCompiler::GenerateNameCheck(Handle name, Label* miss) { } -void CallStubCompiler::GenerateFunctionCheck(Register function, - Register scratch, - Label* miss) { - __ JumpIfSmi(function, miss); - __ GetObjectType(function, scratch, scratch); - __ Branch(miss, ne, scratch, Operand(JS_FUNCTION_TYPE)); -} - - void CallStubCompiler::GenerateLoadFunctionFromCell( Handle cell, Handle function, @@ -1517,7 +1542,9 @@ 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. - GenerateFunctionCheck(a1, a3, miss); + __ JumpIfSmi(a1, miss); + __ GetObjectType(a1, a3, a3); + __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); // Check the shared function info. Make sure it hasn't changed. __ li(a3, Handle(function->shared())); @@ -1548,7 +1575,8 @@ Handle CallStubCompiler::CompileCallField(Handle object, object, holder, name, RECEIVER_MAP_CHECK, &miss); GenerateFastPropertyLoad(masm(), a1, reg, index.is_inobject(holder), index.translate(holder), Representation::Tagged()); - GenerateJumpFunction(object, a1, &miss); + + GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); HandlerFrontendFooter(&miss); @@ -1960,7 +1988,8 @@ Handle CallStubCompiler::CompileStringCharCodeAtCall( __ bind(&miss); // Restore function name in a2. __ li(a2, name); - HandlerFrontendFooter(&name_miss); + __ bind(&name_miss); + GenerateMissBranch(); // Return the generated code. return GetCode(type, name); @@ -2024,7 +2053,8 @@ Handle CallStubCompiler::CompileStringCharAtCall( __ bind(&miss); // Restore function name in a2. __ li(a2, name); - HandlerFrontendFooter(&name_miss); + __ bind(&name_miss); + GenerateMissBranch(); // Return the generated code. return GetCode(type, name); @@ -2070,10 +2100,12 @@ Handle 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); - // We do not have to patch the receiver 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); @@ -2179,9 +2211,11 @@ Handle CallStubCompiler::CompileMathFloorCall( __ ctc1(a3, FCSR); __ bind(&slow); - // We do not have to patch the receiver because the function makes no use of - // it. - GenerateJumpFunctionIgnoreReceiver(function); + // 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); HandlerFrontendFooter(&miss); @@ -2258,10 +2292,12 @@ Handle CallStubCompiler::CompileMathAbsCall( __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); __ DropAndRet(argc + 1); + // Tail call the full function. We do not have to patch the receiver + // because the function makes no use of it. __ bind(&slow); - // We do not have to patch the receiver 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); @@ -2316,7 +2352,8 @@ Handle CallStubCompiler::CompileFastApiCall( __ bind(&miss); FreeSpaceForFastApiCall(masm()); - HandlerFrontendFooter(&miss_before_stack_reserved); + __ bind(&miss_before_stack_reserved); + GenerateMissBranch(); // Return the generated code. return GetCode(function); @@ -2335,7 +2372,7 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { void CallStubCompiler::PatchGlobalProxy(Handle object) { - if (!object.is_null() && object->IsGlobalObject()) { + if (object->IsGlobalObject()) { const int argc = arguments().immediate(); const int receiver_offset = argc * kPointerSize; __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); @@ -2431,17 +2468,39 @@ Register CallStubCompiler::HandlerFrontendHeader(Handle object, } -void CallStubCompiler::GenerateJumpFunction(Handle object, - Register function, - Label* miss) { - ASSERT(function.is(a1)); - // Check that the function really is a function. - GenerateFunctionCheck(function, a3, miss); - if (!function.is(a1)) __ mov(a1, function); +void CallStubCompiler::CompileHandlerBackend(Handle 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 CallStubCompiler::CompileCallConstant( + Handle object, + Handle holder, + Handle name, + CheckType check, + Handle function) { + if (HasCustomCallGenerator(function)) { + Handle code = CompileCustomCall(object, holder, + Handle::null(), + function, Handle::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); - // Invoke the function. - __ InvokeFunction(a1, arguments(), JUMP_FUNCTION, - NullCallWrapper(), call_kind()); + CompileHandlerBackend(function); + HandlerFrontendFooter(&miss); + + // Return the generated code. + return GetCode(function); } @@ -2469,9 +2528,11 @@ Handle CallStubCompiler::CompileCallInterceptor(Handle object, // Restore receiver. __ lw(a0, MemOperand(sp, argc * kPointerSize)); - GenerateJumpFunction(object, a1, &miss); + GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); - HandlerFrontendFooter(&miss); + // Handle call cache miss. + __ bind(&miss); + GenerateMissBranch(); // Return the generated code. return GetCode(Code::FAST, name); @@ -2494,12 +2555,26 @@ Handle 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). + __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); + + // Jump to the cached code (tail call). Counters* counters = isolate()->counters(); __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); - GenerateJumpFunction(object, a1, 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. + __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); + __ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION, + NullCallWrapper(), call_kind); + HandlerFrontendFooter(&miss); // Return the generated code.