Changeset 195836 in webkit


Ignore:
Timestamp:
Jan 29, 2016 12:37:52 PM (8 years ago)
Author:
akling@apple.com
Message:

Shrink CodeBlock!
<https://webkit.org/b/153640>

Reviewed by Saam Barati.

Shrink CodeBlock by 112 bytes (from 640 to 528) by employing
these sophisticated tricks:

  • Remove members that are not used by anyone.
  • Don't cache both VM* and Heap* in members.
  • Reorder members to minimize struct padding.
  • Use RefCountedArray instead of Vector for arrays that never resize.
  • Put a not-always-present HashMap in a std::unique_ptr.

This increases CodeBlock space efficiency by 20%, as we can now
fit 30 of them in a MarkedBlock, up from 25.)

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::setNumParameters):
(JSC::CodeBlock::jettison):
(JSC::CodeBlock::noticeIncomingCall):
(JSC::CodeBlock::resultProfileForBytecodeOffset):

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::setJITCode):
(JSC::CodeBlock::capabilityLevelState):
(JSC::CodeBlock::codeType):
(JSC::CodeBlock::ensureResultProfile):
(JSC::CodeBlock::heap):

Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r195831 r195836  
     12016-01-29  Andreas Kling  <akling@apple.com>
     2
     3        Shrink CodeBlock!
     4        <https://webkit.org/b/153640>
     5
     6        Reviewed by Saam Barati.
     7
     8        Shrink CodeBlock by 112 bytes (from 640 to 528) by employing
     9        these sophisticated tricks:
     10
     11            - Remove members that are not used by anyone.
     12            - Don't cache both VM* and Heap* in members.
     13            - Reorder members to minimize struct padding.
     14            - Use RefCountedArray instead of Vector for arrays that never resize.
     15            - Put a not-always-present HashMap in a std::unique_ptr.
     16
     17        This increases CodeBlock space efficiency by 20%, as we can now
     18        fit 30 of them in a MarkedBlock, up from 25.)
     19
     20        * bytecode/CodeBlock.cpp:
     21        (JSC::CodeBlock::CodeBlock):
     22        (JSC::CodeBlock::finishCreation):
     23        (JSC::CodeBlock::setNumParameters):
     24        (JSC::CodeBlock::jettison):
     25        (JSC::CodeBlock::noticeIncomingCall):
     26        (JSC::CodeBlock::resultProfileForBytecodeOffset):
     27        * bytecode/CodeBlock.h:
     28        (JSC::CodeBlock::setJITCode):
     29        (JSC::CodeBlock::capabilityLevelState):
     30        (JSC::CodeBlock::codeType):
     31        (JSC::CodeBlock::ensureResultProfile):
     32        (JSC::CodeBlock::heap):
     33
    1342016-01-29  Saam barati  <sbarati@apple.com>
    235
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r195576 r195836  
    17411741    : JSCell(*vm, structure)
    17421742    , m_globalObject(other.m_globalObject)
    1743     , m_heap(other.m_heap)
    17441743    , m_numCalleeLocals(other.m_numCalleeLocals)
    17451744    , m_numVars(other.m_numVars)
    1746     , m_isConstructor(other.m_isConstructor)
    17471745    , m_shouldAlwaysBeInlined(true)
     1746#if ENABLE(JIT)
     1747    , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
     1748#endif
    17481749    , m_didFailFTLCompilation(false)
    17491750    , m_hasBeenCompiledWithFTL(false)
     1751    , m_isConstructor(other.m_isConstructor)
     1752    , m_isStrictMode(other.m_isStrictMode)
     1753    , m_needsActivation(other.m_needsActivation)
     1754    , m_codeType(other.m_codeType)
    17501755    , m_unlinkedCode(*other.m_vm, this, other.m_unlinkedCode.get())
    17511756    , m_hasDebuggerStatement(false)
     
    17581763    , m_scopeRegister(other.m_scopeRegister)
    17591764    , m_lexicalEnvironmentRegister(other.m_lexicalEnvironmentRegister)
    1760     , m_isStrictMode(other.m_isStrictMode)
    1761     , m_needsActivation(other.m_needsActivation)
     1765    , m_hash(other.m_hash)
    17621766    , m_source(other.m_source)
    17631767    , m_sourceOffset(other.m_sourceOffset)
    17641768    , m_firstLineColumnOffset(other.m_firstLineColumnOffset)
    1765     , m_codeType(other.m_codeType)
    17661769    , m_constantRegisters(other.m_constantRegisters)
    17671770    , m_constantsSourceCodeRepresentation(other.m_constantsSourceCodeRepresentation)
     
    17721775    , m_reoptimizationRetryCounter(0)
    17731776    , m_creationTime(std::chrono::steady_clock::now())
    1774     , m_hash(other.m_hash)
    1775 #if ENABLE(JIT)
    1776     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
    1777 #endif
    17781777{
    17791778    m_visitWeaklyHasBeenCalled.store(false, std::memory_order_relaxed);
    17801779
    1781     ASSERT(m_heap->isDeferred());
     1780    ASSERT(heap()->isDeferred());
    17821781    ASSERT(m_scopeRegister.isLocal());
    17831782
     
    18021801    }
    18031802   
    1804     m_heap->m_codeBlocks.add(this);
     1803    heap()->m_codeBlocks.add(this);
    18051804}
    18061805
     
    18091808    : JSCell(*vm, structure)
    18101809    , m_globalObject(scope->globalObject()->vm(), this, scope->globalObject())
    1811     , m_heap(&m_globalObject->vm().heap)
    18121810    , m_numCalleeLocals(unlinkedCodeBlock->m_numCalleeLocals)
    18131811    , m_numVars(unlinkedCodeBlock->m_numVars)
    1814     , m_isConstructor(unlinkedCodeBlock->isConstructor())
    18151812    , m_shouldAlwaysBeInlined(true)
     1813#if ENABLE(JIT)
     1814    , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
     1815#endif
    18161816    , m_didFailFTLCompilation(false)
    18171817    , m_hasBeenCompiledWithFTL(false)
     1818    , m_isConstructor(unlinkedCodeBlock->isConstructor())
     1819    , m_isStrictMode(unlinkedCodeBlock->isStrictMode())
     1820    , m_needsActivation(unlinkedCodeBlock->hasActivationRegister() && unlinkedCodeBlock->codeType() == FunctionCode)
     1821    , m_codeType(unlinkedCodeBlock->codeType())
    18181822    , m_unlinkedCode(m_globalObject->vm(), this, unlinkedCodeBlock)
    18191823    , m_hasDebuggerStatement(false)
     
    18251829    , m_scopeRegister(unlinkedCodeBlock->scopeRegister())
    18261830    , m_lexicalEnvironmentRegister(unlinkedCodeBlock->activationRegister())
    1827     , m_isStrictMode(unlinkedCodeBlock->isStrictMode())
    1828     , m_needsActivation(unlinkedCodeBlock->hasActivationRegister() && unlinkedCodeBlock->codeType() == FunctionCode)
    18291831    , m_source(sourceProvider)
    18301832    , m_sourceOffset(sourceOffset)
    18311833    , m_firstLineColumnOffset(firstLineColumnOffset)
    1832     , m_codeType(unlinkedCodeBlock->codeType())
    18331834    , m_osrExitCounter(0)
    18341835    , m_optimizationDelayCounter(0)
    18351836    , m_reoptimizationRetryCounter(0)
    18361837    , m_creationTime(std::chrono::steady_clock::now())
    1837 #if ENABLE(JIT)
    1838     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
    1839 #endif
    18401838{
    18411839    m_visitWeaklyHasBeenCalled.store(false, std::memory_order_relaxed);
    18421840
    1843     ASSERT(m_heap->isDeferred());
     1841    ASSERT(heap()->isDeferred());
    18441842    ASSERT(m_scopeRegister.isLocal());
    18451843
     
    18951893    }
    18961894
    1897     m_functionDecls.resizeToFit(unlinkedCodeBlock->numberOfFunctionDecls());
     1895    m_functionDecls = RefCountedArray<WriteBarrier<FunctionExecutable>>(unlinkedCodeBlock->numberOfFunctionDecls());
    18981896    for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) {
    18991897        UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
     
    19031901    }
    19041902
    1905     m_functionExprs.resizeToFit(unlinkedCodeBlock->numberOfFunctionExprs());
     1903    m_functionExprs = RefCountedArray<WriteBarrier<FunctionExecutable>>(unlinkedCodeBlock->numberOfFunctionExprs());
    19061904    for (size_t count = unlinkedCodeBlock->numberOfFunctionExprs(), i = 0; i < count; ++i) {
    19071905        UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionExpr(i);
     
    19591957    // Allocate metadata buffers for the bytecode
    19601958    if (size_t size = unlinkedCodeBlock->numberOfLLintCallLinkInfos())
    1961         m_llintCallLinkInfos.resizeToFit(size);
     1959        m_llintCallLinkInfos = RefCountedArray<LLIntCallLinkInfo>(size);
    19621960    if (size_t size = unlinkedCodeBlock->numberOfArrayProfiles())
    19631961        m_arrayProfiles.grow(size);
    19641962    if (size_t size = unlinkedCodeBlock->numberOfArrayAllocationProfiles())
    1965         m_arrayAllocationProfiles.resizeToFit(size);
     1963        m_arrayAllocationProfiles = RefCountedArray<ArrayAllocationProfile>(size);
    19661964    if (size_t size = unlinkedCodeBlock->numberOfValueProfiles())
    1967         m_valueProfiles.resizeToFit(size);
     1965        m_valueProfiles = RefCountedArray<ValueProfile>(size);
    19681966    if (size_t size = unlinkedCodeBlock->numberOfObjectAllocationProfiles())
    1969         m_objectAllocationProfiles.resizeToFit(size);
     1967        m_objectAllocationProfiles = RefCountedArray<ObjectAllocationProfile>(size);
    19701968
    19711969#if ENABLE(JIT)
     
    23192317        dumpBytecode();
    23202318   
    2321     m_heap->m_codeBlocks.add(this);
    2322     m_heap->reportExtraMemoryAllocated(m_instructions.size() * sizeof(Instruction));
     2319    heap()->m_codeBlocks.add(this);
     2320    heap()->reportExtraMemoryAllocated(m_instructions.size() * sizeof(Instruction));
    23232321}
    23242322
     
    23272325    : JSCell(*vm, structure)
    23282326    , m_globalObject(globalObject->vm(), this, globalObject)
    2329     , m_heap(&m_globalObject->vm().heap)
    23302327    , m_numCalleeLocals(0)
    23312328    , m_numVars(0)
    2332     , m_isConstructor(false)
    23332329    , m_shouldAlwaysBeInlined(false)
     2330#if ENABLE(JIT)
     2331    , m_capabilityLevelState(DFG::CannotCompile)
     2332#endif
    23342333    , m_didFailFTLCompilation(false)
    23352334    , m_hasBeenCompiledWithFTL(false)
     2335    , m_isConstructor(false)
     2336    , m_isStrictMode(false)
     2337    , m_needsActivation(false)
     2338    , m_codeType(FunctionCode)
    23362339    , m_hasDebuggerStatement(false)
    23372340    , m_steppingMode(SteppingModeDisabled)
     
    23392342    , m_ownerExecutable(m_globalObject->vm(), this, ownerExecutable)
    23402343    , m_vm(vm)
    2341     , m_isStrictMode(false)
    2342     , m_needsActivation(false)
    2343     , m_codeType(FunctionCode)
    23442344    , m_osrExitCounter(0)
    23452345    , m_optimizationDelayCounter(0)
    23462346    , m_reoptimizationRetryCounter(0)
    23472347    , m_creationTime(std::chrono::steady_clock::now())
    2348 #if ENABLE(JIT)
    2349     , m_capabilityLevelState(DFG::CannotCompile)
    2350 #endif
    2351 {
    2352     ASSERT(m_heap->isDeferred());
     2348{
     2349    ASSERT(heap()->isDeferred());
    23532350}
    23542351
     
    23572354    Base::finishCreation(vm);
    23582355
    2359     m_heap->m_codeBlocks.add(this);
     2356    heap()->m_codeBlocks.add(this);
    23602357}
    23612358#endif
     
    24002397    m_numParameters = newValue;
    24012398
    2402     m_argumentValueProfiles.resizeToFit(newValue);
     2399    m_argumentValueProfiles = RefCountedArray<ValueProfile>(newValue);
    24032400}
    24042401
     
    32963293#endif // ENABLE(DFG_JIT)
    32973294
    3298     DeferGCForAWhile deferGC(*m_heap);
     3295    DeferGCForAWhile deferGC(*heap());
    32993296   
    33003297    // We want to accomplish two things here:
     
    34223419        return;
    34233420
    3424     if (!canInline(m_capabilityLevelState))
     3421    if (!canInline(capabilityLevelState()))
    34253422        return;
    34263423   
     
    34713468    }
    34723469   
    3473     if (callerCodeBlock->m_capabilityLevelState == DFG::CapabilityLevelNotSet) {
     3470    if (callerCodeBlock->capabilityLevelState() == DFG::CapabilityLevelNotSet) {
    34743471        dataLog("In call from ", *callerCodeBlock, " ", callerFrame->codeOrigin(), " to ", *this, ": caller's DFG capability level is not set.\n");
    34753472        CRASH();
    34763473    }
    34773474   
    3478     if (canCompile(callerCodeBlock->m_capabilityLevelState))
     3475    if (canCompile(callerCodeBlock->capabilityLevelState()))
    34793476        return;
    34803477   
     
    41944191ResultProfile* CodeBlock::resultProfileForBytecodeOffset(int bytecodeOffset)
    41954192{
    4196     auto iterator = m_bytecodeOffsetToResultProfileIndexMap.find(bytecodeOffset);
    4197     if (iterator == m_bytecodeOffsetToResultProfileIndexMap.end())
     4193    if (!m_bytecodeOffsetToResultProfileIndexMap)
     4194        return nullptr;
     4195    auto iterator = m_bytecodeOffsetToResultProfileIndexMap->find(bytecodeOffset);
     4196    if (iterator == m_bytecodeOffsetToResultProfileIndexMap->end())
    41984197        return nullptr;
    41994198    return &m_resultProfiles[iterator->value];
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r194840 r195836  
    123123
    124124    WriteBarrier<JSGlobalObject> m_globalObject;
    125     Heap* m_heap;
    126125
    127126public:
     
    297296    void setJITCode(PassRefPtr<JITCode> code)
    298297    {
    299         ASSERT(m_heap->isDeferred());
    300         m_heap->reportExtraMemoryAllocated(code->size());
     298        ASSERT(heap()->isDeferred());
     299        heap()->reportExtraMemoryAllocated(code->size());
    301300        ConcurrentJITLocker locker(m_lock);
    302301        WTF::storeStoreFence(); // This is probably not needed because the lock will also do something similar, but it's good to be paranoid.
     
    324323    DFG::CapabilityLevel computeCapabilityLevel();
    325324    DFG::CapabilityLevel capabilityLevel();
    326     DFG::CapabilityLevel capabilityLevelState() { return m_capabilityLevelState; }
     325    DFG::CapabilityLevel capabilityLevelState() { return static_cast<DFG::CapabilityLevel>(m_capabilityLevelState); }
    327326
    328327    bool hasOptimizedReplacement(JITCode::JITType typeToReplace);
     
    378377    CodeType codeType() const
    379378    {
    380         return m_codeType;
     379        return static_cast<CodeType>(m_codeType);
    381380    }
    382381
     
    461460            profile = &m_resultProfiles.last();
    462461            ASSERT(&m_resultProfiles.last() == &m_resultProfiles[m_resultProfiles.size() - 1]);
    463             m_bytecodeOffsetToResultProfileIndexMap.add(bytecodeOffset, m_resultProfiles.size() - 1);
     462            if (!m_bytecodeOffsetToResultProfileIndexMap)
     463                m_bytecodeOffsetToResultProfileIndexMap = std::make_unique<BytecodeOffsetToResultProfileIndexMap>();
     464            m_bytecodeOffsetToResultProfileIndexMap->add(bytecodeOffset, m_resultProfiles.size() - 1);
    464465        }
    465466        return profile;
     
    611612    }
    612613
    613     Heap* heap() const { return m_heap; }
     614    Heap* heap() const { return &m_vm->heap; }
    614615    JSGlobalObject* globalObject() { return m_globalObject.get(); }
    615616
     
    863864    // FIXME: Make these remaining members private.
    864865
    865     int m_numLocalRegistersForCalleeSaves;
    866866    int m_numCalleeLocals;
    867867    int m_numVars;
    868     bool m_isConstructor : 1;
    869868   
    870869    // This is intentionally public; it's the responsibility of anyone doing any
     
    885884    // concurrent compilation threads finish what they're doing.
    886885    mutable ConcurrentJITLock m_lock;
    887    
     886
     887    Atomic<bool> m_visitWeaklyHasBeenCalled;
     888
    888889    bool m_shouldAlwaysBeInlined; // Not a bitfield because the JIT wants to store to it.
     890
     891#if ENABLE(JIT)
     892    unsigned m_capabilityLevelState : 2; // DFG::CapabilityLevel
     893#endif
     894
    889895    bool m_allTransitionsHaveBeenMarked : 1; // Initialized and used on every GC.
    890    
     896
    891897    bool m_didFailFTLCompilation : 1;
    892898    bool m_hasBeenCompiledWithFTL : 1;
     899    bool m_isConstructor : 1;
     900    bool m_isStrictMode : 1;
     901    bool m_needsActivation : 1;
     902    unsigned m_codeType : 2; // CodeType
    893903
    894904    // Internal methods for use by validation code. It would be private if it wasn't
     
    10311041    VirtualRegister m_scopeRegister;
    10321042    VirtualRegister m_lexicalEnvironmentRegister;
    1033 
    1034     bool m_isStrictMode;
    1035     bool m_needsActivation;
    1036 
    1037     Atomic<bool> m_visitWeaklyHasBeenCalled;
     1043    mutable CodeBlockHash m_hash;
    10381044
    10391045    RefPtr<SourceProvider> m_source;
    10401046    unsigned m_sourceOffset;
    10411047    unsigned m_firstLineColumnOffset;
    1042     CodeType m_codeType;
    1043 
    1044     Vector<LLIntCallLinkInfo> m_llintCallLinkInfos;
     1048
     1049    RefCountedArray<LLIntCallLinkInfo> m_llintCallLinkInfos;
    10451050    SentinelLinkedList<LLIntCallLinkInfo, BasicRawSentinelNode<LLIntCallLinkInfo>> m_incomingLLIntCalls;
    10461051    RefPtr<JITCode> m_jitCode;
     
    10601065    CompressedLazyOperandValueProfileHolder m_lazyOperandValueProfiles;
    10611066#endif
    1062     Vector<ValueProfile> m_argumentValueProfiles;
    1063     Vector<ValueProfile> m_valueProfiles;
     1067    RefCountedArray<ValueProfile> m_argumentValueProfiles;
     1068    RefCountedArray<ValueProfile> m_valueProfiles;
    10641069    SegmentedVector<RareCaseProfile, 8> m_rareCaseProfiles;
    10651070    SegmentedVector<ResultProfile, 8> m_resultProfiles;
    1066     HashMap<unsigned, unsigned, IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> m_bytecodeOffsetToResultProfileIndexMap;
    1067     Vector<ArrayAllocationProfile> m_arrayAllocationProfiles;
     1071    typedef HashMap<unsigned, unsigned, IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> BytecodeOffsetToResultProfileIndexMap;
     1072    std::unique_ptr<BytecodeOffsetToResultProfileIndexMap> m_bytecodeOffsetToResultProfileIndexMap;
     1073    RefCountedArray<ArrayAllocationProfile> m_arrayAllocationProfiles;
    10681074    ArrayProfileVector m_arrayProfiles;
    1069     Vector<ObjectAllocationProfile> m_objectAllocationProfiles;
     1075    RefCountedArray<ObjectAllocationProfile> m_objectAllocationProfiles;
    10701076
    10711077    // Constant Pool
     
    10751081    Vector<WriteBarrier<Unknown>> m_constantRegisters;
    10761082    Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation;
    1077     Vector<WriteBarrier<FunctionExecutable>> m_functionDecls;
    1078     Vector<WriteBarrier<FunctionExecutable>> m_functionExprs;
     1083    RefCountedArray<WriteBarrier<FunctionExecutable>> m_functionDecls;
     1084    RefCountedArray<WriteBarrier<FunctionExecutable>> m_functionExprs;
    10791085
    10801086    WriteBarrier<CodeBlock> m_alternative;
     
    10831089
    10841090    BaselineExecutionCounter m_jitExecuteCounter;
    1085     int32_t m_totalJITExecutions;
    10861091    uint32_t m_osrExitCounter;
    10871092    uint16_t m_optimizationDelayCounter;
     
    10901095    std::chrono::steady_clock::time_point m_creationTime;
    10911096
    1092     mutable CodeBlockHash m_hash;
    1093 
    10941097    std::unique_ptr<BytecodeLivenessAnalysis> m_livenessAnalysis;
    10951098
    10961099    std::unique_ptr<RareData> m_rareData;
    1097 #if ENABLE(JIT)
    1098     DFG::CapabilityLevel m_capabilityLevelState;
    1099 #endif
    11001100
    11011101    UnconditionalFinalizer m_unconditionalFinalizer;
Note: See TracChangeset for help on using the changeset viewer.