| Index: src/ia32/stub-cache-ia32.cc
|
| diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
|
| index c1f6eae0265e74e17766ca67fb6bc3182b664ca9..d799c3b4464770647c824352c88b51cc533127d9 100644
|
| --- a/src/ia32/stub-cache-ia32.cc
|
| +++ b/src/ia32/stub-cache-ia32.cc
|
| @@ -645,7 +645,7 @@ static void GenerateFastApiCallBody(MacroAssembler* masm,
|
|
|
| class CallInterceptorCompiler BASE_EMBEDDED {
|
| public:
|
| - CallInterceptorCompiler(CallStubCompiler* stub_compiler,
|
| + CallInterceptorCompiler(StubCompiler* stub_compiler,
|
| const ParameterCount& arguments,
|
| Register name,
|
| ExtraICState extra_state)
|
| @@ -756,8 +756,13 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
| if (can_do_fast_api_call) {
|
| GenerateFastApiCall(masm, optimization, arguments_.immediate());
|
| } else {
|
| - Handle<JSFunction> fun = optimization.constant_function();
|
| - stub_compiler_->GenerateJumpFunction(object, fun);
|
| + CallKind call_kind = CallICBase::Contextual::decode(extra_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);
|
| }
|
|
|
| // Deferred code for fast API call case---clean preallocated space.
|
| @@ -825,7 +830,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
| __ j(not_equal, interceptor_succeeded);
|
| }
|
|
|
| - CallStubCompiler* stub_compiler_;
|
| + StubCompiler* stub_compiler_;
|
| const ParameterCount& arguments_;
|
| Register name_;
|
| ExtraICState extra_state_;
|
| @@ -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(
|
| Handle<Cell> cell,
|
| Handle<JSFunction> function,
|
| @@ -1625,7 +1621,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(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.
|
| __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset),
|
| @@ -1658,7 +1656,20 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
|
| GenerateFastPropertyLoad(
|
| masm(), edi, reg, index.is_inobject(holder),
|
| 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);
|
|
|
| @@ -2070,7 +2081,8 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
|
| __ bind(&miss);
|
| // Restore function name in ecx.
|
| __ Set(ecx, Immediate(name));
|
| - HandlerFrontendFooter(&name_miss);
|
| + __ bind(&name_miss);
|
| + GenerateMissBranch();
|
|
|
| // Return the generated code.
|
| return GetCode(type, name);
|
| @@ -2138,7 +2150,8 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
|
| __ bind(&miss);
|
| // Restore function name in ecx.
|
| __ Set(ecx, Immediate(name));
|
| - HandlerFrontendFooter(&name_miss);
|
| + __ bind(&name_miss);
|
| + GenerateMissBranch();
|
|
|
| // Return the generated code.
|
| return GetCode(type, name);
|
| @@ -2187,10 +2200,15 @@ 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);
|
| - // We do not have to patch the receiver because the function makes no use of
|
| - // it.
|
| - GenerateJumpFunctionIgnoreReceiver(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);
|
|
|
| HandlerFrontendFooter(&miss);
|
|
|
| @@ -2297,10 +2315,12 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
|
| __ mov(eax, Operand(esp, 1 * 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);
|
| - // 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);
|
|
|
| @@ -2384,10 +2404,12 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
|
| __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
|
| __ 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);
|
| - // 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);
|
|
|
| @@ -2447,7 +2469,8 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
|
| __ bind(&miss);
|
| __ add(esp, Immediate(kFastApiCallArguments * kPointerSize));
|
|
|
| - HandlerFrontendFooter(&miss_before_stack_reserved);
|
| + __ bind(&miss_before_stack_reserved);
|
| + GenerateMissBranch();
|
|
|
| // Return the generated code.
|
| return GetCode(function);
|
| @@ -2466,7 +2489,7 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
|
|
|
|
|
| void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
|
| - if (!object.is_null() && object->IsGlobalObject()) {
|
| + if (object->IsGlobalObject()) {
|
| const int argc = arguments().immediate();
|
| const int receiver_offset = (argc + 1) * kPointerSize;
|
| __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
|
| @@ -2556,18 +2579,40 @@ Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
|
| }
|
|
|
|
|
| -void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
|
| - Register function,
|
| - Label* miss) {
|
| - // Check that the function really is a function.
|
| - GenerateFunctionCheck(function, ebx, miss);
|
| +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);
|
| +}
|
| +
|
|
|
| - 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);
|
| + CompileHandlerBackend(function);
|
| + HandlerFrontendFooter(&miss);
|
|
|
| - // Invoke the function.
|
| - __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
|
| - NullCallWrapper(), call_kind());
|
| + // Return the generated code.
|
| + return GetCode(function);
|
| }
|
|
|
|
|
| @@ -2594,9 +2639,29 @@ Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
|
| // Restore receiver.
|
| __ 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 GetCode(Code::FAST, name);
|
| @@ -2619,10 +2684,25 @@ 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);
|
| - 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);
|
|
|
|
|