Changeset 138609 in webkit


Ignore:
Timestamp:
Jan 2, 2013 12:48:18 AM (11 years ago)
Author:
fpizlo@apple.com
Message:

Baseline JIT should have closure call caching
https://bugs.webkit.org/show_bug.cgi?id=105900

Reviewed by Gavin Barraclough.

This is not a speed-up by itself, but is meant to allow the DFG inliner to
accurately discern between closure calls and non-closure calls, so that it can
do closure call inlining in the future.

  • bytecode/CallLinkStatus.cpp:

(JSC::CallLinkStatus::computeFromLLInt):
(JSC::CallLinkStatus::computeFor):

  • bytecode/CallLinkStatus.h:

(JSC::CallLinkStatus::CallLinkStatus):
(JSC::CallLinkStatus::isClosureCall):
(CallLinkStatus):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleCall):

  • jit/JIT.cpp:

(JSC::JIT::linkFor):
(JSC::JIT::linkSlowCall):

  • jit/JIT.h:

(JSC::JIT::compileClosureCall):

  • jit/JITCall.cpp:

(JSC::JIT::privateCompileClosureCall):

  • jit/JITCall32_64.cpp:

(JSC::JIT::privateCompileClosureCall):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • jit/JITStubs.h:
  • jit/ThunkGenerators.cpp:

(JSC::linkClosureCallGenerator):

  • jit/ThunkGenerators.h:
Location:
trunk/Source/JavaScriptCore
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r138606 r138609  
     12013-01-01  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Baseline JIT should have closure call caching
     4        https://bugs.webkit.org/show_bug.cgi?id=105900
     5
     6        Reviewed by Gavin Barraclough.
     7       
     8        This is not a speed-up by itself, but is meant to allow the DFG inliner to
     9        accurately discern between closure calls and non-closure calls, so that it can
     10        do closure call inlining in the future.
     11
     12        * bytecode/CallLinkStatus.cpp:
     13        (JSC::CallLinkStatus::computeFromLLInt):
     14        (JSC::CallLinkStatus::computeFor):
     15        * bytecode/CallLinkStatus.h:
     16        (JSC::CallLinkStatus::CallLinkStatus):
     17        (JSC::CallLinkStatus::isClosureCall):
     18        (CallLinkStatus):
     19        * dfg/DFGByteCodeParser.cpp:
     20        (JSC::DFG::ByteCodeParser::handleCall):
     21        * jit/JIT.cpp:
     22        (JSC::JIT::linkFor):
     23        (JSC::JIT::linkSlowCall):
     24        * jit/JIT.h:
     25        (JSC::JIT::compileClosureCall):
     26        * jit/JITCall.cpp:
     27        (JSC::JIT::privateCompileClosureCall):
     28        * jit/JITCall32_64.cpp:
     29        (JSC::JIT::privateCompileClosureCall):
     30        * jit/JITStubs.cpp:
     31        (JSC::DEFINE_STUB_FUNCTION):
     32        * jit/JITStubs.h:
     33        * jit/ThunkGenerators.cpp:
     34        (JSC::linkClosureCallGenerator):
     35        * jit/ThunkGenerators.h:
     36
    1372013-01-01  Dan Bernstein  <mitz@apple.com>
    238
  • trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp

    r108444 r138609  
    4040    LLIntCallLinkInfo* callLinkInfo = instruction[4].u.callLinkInfo;
    4141   
    42     return CallLinkStatus(callLinkInfo->lastSeenCallee.get(), false);
     42    return CallLinkStatus(callLinkInfo->lastSeenCallee.get(), false, false);
    4343#else
    44     return CallLinkStatus(0, false);
     44    return CallLinkStatus(0, false, false);
    4545#endif
    4646}
     
    5757        return CallLinkStatus(0, true);
    5858   
    59     JSFunction* target = profiledBlock->getCallLinkInfo(bytecodeIndex).lastSeenCallee.get();
     59    CallLinkInfo& callLinkInfo = profiledBlock->getCallLinkInfo(bytecodeIndex);
     60    JSFunction* target = callLinkInfo.lastSeenCallee.get();
    6061    if (!target)
    6162        return computeFromLLInt(profiledBlock, bytecodeIndex);
    6263   
    63     return CallLinkStatus(target, false);
     64    return CallLinkStatus(target, false, !!callLinkInfo.stub);
    6465#else
    65     return CallLinkStatus(0, false);
     66    return CallLinkStatus(0, false, false);
    6667#endif
    6768}
  • trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h

    r108444 r138609  
    3737        : m_callTarget(0)
    3838        , m_couldTakeSlowPath(false)
     39        , m_isClosureCall(false)
    3940    {
    4041    }
    4142   
    42     CallLinkStatus(JSFunction* callTarget, bool couldTakeSlowPath)
     43    CallLinkStatus(JSFunction* callTarget, bool couldTakeSlowPath, bool isClosureCall = false)
    4344        : m_callTarget(callTarget)
    4445        , m_couldTakeSlowPath(couldTakeSlowPath)
     46        , m_isClosureCall(isClosureCall)
    4547    {
    4648    }
     
    5355   
    5456    bool couldTakeSlowPath() const { return m_couldTakeSlowPath; }
     57    bool isClosureCall() const { return m_isClosureCall; }
    5558   
    5659    JSFunction* callTarget() const { return m_callTarget; }
     
    6164    JSFunction* m_callTarget;
    6265    bool m_couldTakeSlowPath;
     66    bool m_isClosureCall;
    6367};
    6468
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r138300 r138609  
    11/*
    2  * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    13171317#endif
    13181318    } else if (callLinkStatus.isSet() && !callLinkStatus.couldTakeSlowPath()
     1319               && !callLinkStatus.isClosureCall() // We will eventually optimize this, I promise.
    13191320               && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
    13201321        callType = LinkedFunction;
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r138516 r138609  
    11/*
    2  * Copyright (C) 2008, 2009, 2012 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2009, 2012, 2013 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    871871    // Patch the slow patch so we do not continue to try to link.
    872872    if (kind == CodeForCall) {
     873        ASSERT(callLinkInfo->callType == CallLinkInfo::Call
     874               || callLinkInfo->callType == CallLinkInfo::CallVarargs);
     875        if (callLinkInfo->callType == CallLinkInfo::Call) {
     876            repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->getCTIStub(linkClosureCallGenerator).code());
     877            return;
     878        }
     879
    873880        repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->getCTIStub(virtualCallGenerator).code());
    874881        return;
     
    879886}
    880887
     888void JIT::linkSlowCall(CodeBlock* callerCodeBlock, CallLinkInfo* callLinkInfo)
     889{
     890    RepatchBuffer repatchBuffer(callerCodeBlock);
     891
     892    repatchBuffer.relink(callLinkInfo->callReturnLocation, callerCodeBlock->globalData()->getCTIStub(virtualCallGenerator).code());
     893}
     894
    881895} // namespace JSC
    882896
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r138516 r138609  
    11/*
    2  * Copyright (C) 2008, 2012 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2012, 2013 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    305305            return JIT(globalData, codeBlock).privateCompile(functionEntryArityCheck, effort);
    306306        }
     307       
     308        static void compileClosureCall(JSGlobalData* globalData, CallLinkInfo* callLinkInfo, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, Structure* expectedStructure, ExecutableBase* expectedExecutable, MacroAssemblerCodePtr codePtr)
     309        {
     310            JIT jit(globalData, callerCodeBlock);
     311            jit.m_bytecodeOffset = callLinkInfo->codeOrigin.bytecodeIndex;
     312            jit.privateCompileClosureCall(callLinkInfo, calleeCodeBlock, expectedStructure, expectedExecutable, codePtr);
     313        }
    307314
    308315        static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, PropertyOffset cachedOffset, ReturnAddressPtr returnAddress)
     
    389396
    390397        static void linkFor(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, CodePtr, CallLinkInfo*, JSGlobalData*, CodeSpecializationKind);
     398        static void linkSlowCall(CodeBlock* callerCodeBlock, CallLinkInfo*);
    391399
    392400    private:
     
    397405        void privateCompileSlowCases();
    398406        JITCode privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffort);
     407       
     408        void privateCompileClosureCall(CallLinkInfo*, CodeBlock* calleeCodeBlock, Structure*, ExecutableBase*, MacroAssemblerCodePtr);
    399409       
    400410        void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, const Identifier&, const PropertySlot&, PropertyOffset cachedOffset, ReturnAddressPtr, CallFrame*);
  • trunk/Source/JavaScriptCore/jit/JITCall.cpp

    r138516 r138609  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3737#include "JSFunction.h"
    3838#include "Interpreter.h"
     39#include "RepatchBuffer.h"
    3940#include "ResultType.h"
    4041#include "SamplingTool.h"
     42#include "ThunkGenerators.h"
    4143
    4244#ifndef NDEBUG
     
    222224}
    223225
     226void JIT::privateCompileClosureCall(CallLinkInfo* callLinkInfo, CodeBlock* calleeCodeBlock, Structure* expectedStructure, ExecutableBase* expectedExecutable, MacroAssemblerCodePtr codePtr)
     227{
     228    JumpList slowCases;
     229   
     230    slowCases.append(branchTestPtr(NonZero, regT0, tagMaskRegister));
     231    slowCases.append(branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(expectedStructure)));
     232    slowCases.append(branchPtr(NotEqual, Address(regT0, JSFunction::offsetOfExecutable()), TrustedImmPtr(expectedExecutable)));
     233   
     234    loadPtr(Address(regT0, JSFunction::offsetOfScopeChain()), regT1);
     235    emitPutToCallFrameHeader(regT1, JSStack::ScopeChain);
     236   
     237    Call call = nearCall();
     238    Jump done = jump();
     239   
     240    slowCases.link(this);
     241    move(TrustedImmPtr(callLinkInfo->callReturnLocation.executableAddress()), regT2);
     242    restoreReturnAddressBeforeReturn(regT2);
     243    Jump slow = jump();
     244   
     245    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
     246   
     247    patchBuffer.link(call, FunctionPtr(codePtr.executableAddress()));
     248    patchBuffer.link(done, callLinkInfo->hotPathOther.labelAtOffset(0));
     249    patchBuffer.link(slow, CodeLocationLabel(m_globalData->getCTIStub(virtualCallGenerator).code()));
     250   
     251    RefPtr<ClosureCallStubRoutine> stubRoutine = adoptRef(new ClosureCallStubRoutine(
     252        FINALIZE_CODE(
     253            patchBuffer,
     254            ("Baseline closure call stub for %s, return point %p, target %p (%s)",
     255                toCString(*m_codeBlock).data(),
     256                callLinkInfo->hotPathOther.labelAtOffset(0).executableAddress(),
     257                codePtr.executableAddress(),
     258                toCString(*calleeCodeBlock).data())),
     259        *m_globalData, m_codeBlock->ownerExecutable(), expectedStructure, expectedExecutable,
     260        callLinkInfo->codeOrigin));
     261   
     262    RepatchBuffer repatchBuffer(m_codeBlock);
     263   
     264    repatchBuffer.replaceWithJump(
     265        RepatchBuffer::startOfBranchPtrWithPatchOnRegister(callLinkInfo->hotPathBegin),
     266        CodeLocationLabel(stubRoutine->code().code()));
     267    repatchBuffer.relink(callLinkInfo->callReturnLocation, m_globalData->getCTIStub(virtualCallGenerator).code());
     268   
     269    callLinkInfo->stub = stubRoutine.release();
     270}
     271
    224272} // namespace JSC
    225273
  • trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp

    r138516 r138609  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3737#include "JSArray.h"
    3838#include "JSFunction.h"
     39#include "RepatchBuffer.h"
    3940#include "ResultType.h"
    4041#include "SamplingTool.h"
     
    303304}
    304305
     306void JIT::privateCompileClosureCall(CallLinkInfo* callLinkInfo, CodeBlock* calleeCodeBlock, Structure* expectedStructure, ExecutableBase* expectedExecutable, MacroAssemblerCodePtr codePtr)
     307{
     308    JumpList slowCases;
     309
     310    slowCases.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
     311    slowCases.append(branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(expectedStructure)));
     312    slowCases.append(branchPtr(NotEqual, Address(regT0, JSFunction::offsetOfExecutable()), TrustedImmPtr(expectedExecutable)));
     313   
     314    loadPtr(Address(regT0, JSFunction::offsetOfScopeChain()), regT1);
     315    emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain);
     316   
     317    Call call = nearCall();
     318    Jump done = jump();
     319   
     320    slowCases.link(this);
     321    move(TrustedImmPtr(callLinkInfo->callReturnLocation.executableAddress()), regT2);
     322    restoreReturnAddressBeforeReturn(regT2);
     323    Jump slow = jump();
     324   
     325    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
     326   
     327    patchBuffer.link(call, FunctionPtr(codePtr.executableAddress()));
     328    patchBuffer.link(done, callLinkInfo->hotPathOther.labelAtOffset(0));
     329    patchBuffer.link(slow, CodeLocationLabel(m_globalData->getCTIStub(virtualCallGenerator).code()));
     330   
     331    RefPtr<ClosureCallStubRoutine> stubRoutine = adoptRef(new ClosureCallStubRoutine(
     332        FINALIZE_CODE(
     333            patchBuffer,
     334            ("Baseline closure call stub for %s, return point %p, target %p (%s)",
     335                toCString(*m_codeBlock).data(),
     336                callLinkInfo->hotPathOther.labelAtOffset(0).executableAddress(),
     337                codePtr.executableAddress(),
     338                toCString(*calleeCodeBlock).data())),
     339        *m_globalData, m_codeBlock->ownerExecutable(), expectedStructure, expectedExecutable,
     340        callLinkInfo->codeOrigin));
     341   
     342    RepatchBuffer repatchBuffer(m_codeBlock);
     343   
     344    repatchBuffer.replaceWithJump(
     345        RepatchBuffer::startOfBranchPtrWithPatchOnRegister(callLinkInfo->hotPathBegin),
     346        CodeLocationLabel(stubRoutine->code().code()));
     347    repatchBuffer.relink(callLinkInfo->callReturnLocation, m_globalData->getCTIStub(virtualCallGenerator).code());
     348   
     349    callLinkInfo->stub = stubRoutine.release();
     350}
     351
    305352} // namespace JSC
    306353
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r138516 r138609  
    11/*
    2  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.
    33 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
    44 * Copyright (C) Research In Motion Limited 2010, 2011. All rights reserved.
     
    21102110}
    21112111
     2112DEFINE_STUB_FUNCTION(void*, vm_lazyLinkClosureCall)
     2113{
     2114    STUB_INIT_STACK_FRAME(stackFrame);
     2115
     2116    CallFrame* callFrame = stackFrame.callFrame;
     2117   
     2118    CodeBlock* callerCodeBlock = callFrame->callerFrame()->codeBlock();
     2119    JSGlobalData* globalData = callerCodeBlock->globalData();
     2120    CallLinkInfo* callLinkInfo = &callerCodeBlock->getCallLinkInfo(callFrame->returnPC());
     2121    JSFunction* callee = jsCast<JSFunction*>(callFrame->callee());
     2122    ExecutableBase* executable = callee->executable();
     2123    Structure* structure = callee->structure();
     2124   
     2125    ASSERT(callLinkInfo->callType == CallLinkInfo::Call);
     2126    ASSERT(callLinkInfo->isLinked());
     2127    ASSERT(callLinkInfo->callee);
     2128    ASSERT(callee != callLinkInfo->callee.get());
     2129   
     2130    bool shouldLink = false;
     2131    CodeBlock* calleeCodeBlock = 0;
     2132    MacroAssemblerCodePtr codePtr;
     2133   
     2134    if (executable == callLinkInfo->callee.get()->executable()
     2135        && structure == callLinkInfo->callee.get()->structure()) {
     2136       
     2137        shouldLink = true;
     2138       
     2139        ASSERT(executable->hasJITCodeForCall());
     2140        codePtr = executable->generatedJITCodeForCall().addressForCall();
     2141        if (!callee->executable()->isHostFunction()) {
     2142            calleeCodeBlock = &jsCast<FunctionExecutable*>(executable)->generatedBytecodeForCall();
     2143            if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(calleeCodeBlock->numParameters())) {
     2144                shouldLink = false;
     2145                codePtr = executable->generatedJITCodeWithArityCheckFor(CodeForCall);
     2146            }
     2147        }
     2148    } else if (callee->isHostFunction())
     2149        codePtr = executable->generatedJITCodeForCall().addressForCall();
     2150    else {
     2151        // Need to clear the code block before compilation, because compilation can GC.
     2152        callFrame->setCodeBlock(0);
     2153       
     2154        FunctionExecutable* functionExecutable = jsCast<FunctionExecutable*>(executable);
     2155        JSScope* scopeChain = callee->scope();
     2156        JSObject* error = functionExecutable->compileFor(callFrame, scopeChain, CodeForCall);
     2157        if (error) {
     2158            callFrame->globalData().exception = error;
     2159            return 0;
     2160        }
     2161       
     2162        codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(CodeForCall);
     2163    }
     2164   
     2165    if (shouldLink) {
     2166        ASSERT(codePtr);
     2167        JIT::compileClosureCall(globalData, callLinkInfo, callerCodeBlock, calleeCodeBlock, structure, executable, codePtr);
     2168    } else
     2169        JIT::linkSlowCall(callerCodeBlock, callLinkInfo);
     2170
     2171    return codePtr.executableAddress();
     2172}
     2173
    21122174DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct)
    21132175{
  • trunk/Source/JavaScriptCore/jit/JITStubs.h

    r138465 r138609  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
    33 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
    44 *
     
    412412void* JIT_STUB cti_stack_check(STUB_ARGS_DECLARATION) WTF_INTERNAL;
    413413void* JIT_STUB cti_vm_lazyLinkCall(STUB_ARGS_DECLARATION) WTF_INTERNAL;
     414void* JIT_STUB cti_vm_lazyLinkClosureCall(STUB_ARGS_DECLARATION) WTF_INTERNAL;
    414415void* JIT_STUB cti_vm_lazyLinkConstruct(STUB_ARGS_DECLARATION) WTF_INTERNAL;
    415416void* JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION) REFERENCED_FROM_ASM WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp

    r138523 r138609  
    11/*
    2  * Copyright (C) 2010, 2012 Apple Inc. All rights reserved.
     2 * Copyright (C) 2010, 2012, 2013 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    105105{
    106106    return linkForGenerator(globalData, FunctionPtr(cti_vm_lazyLinkConstruct), FunctionPtr(cti_op_construct_NotJSConstruct), "construct");
     107}
     108
     109MacroAssemblerCodeRef linkClosureCallGenerator(JSGlobalData* globalData)
     110{
     111    return linkForGenerator(globalData, FunctionPtr(cti_vm_lazyLinkClosureCall), FunctionPtr(cti_op_call_NotJSFunction), "closure call");
    107112}
    108113
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.h

    r138516 r138609  
    11/*
    2  * Copyright (C) 2010, 2012 Apple Inc. All rights reserved.
     2 * Copyright (C) 2010, 2012, 2013 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3434MacroAssemblerCodeRef linkCallGenerator(JSGlobalData*);
    3535MacroAssemblerCodeRef linkConstructGenerator(JSGlobalData*);
     36MacroAssemblerCodeRef linkClosureCallGenerator(JSGlobalData*);
    3637MacroAssemblerCodeRef virtualCallGenerator(JSGlobalData*);
    3738MacroAssemblerCodeRef virtualConstructGenerator(JSGlobalData*);
Note: See TracChangeset for help on using the changeset viewer.