⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 292191 in webkit


Ignore:
Timestamp:
Mar 31, 2022, 5:33:33 PM (5 years ago)
Author:
ysuzuki@apple.com
Message:

[JSC] Remove ExecutableToCodeBlockEdge
​https://bugs.webkit.org/show_bug.cgi?id=238485

Reviewed by Keith Miller.

It turned out that getting CodeBlock from JSFunction is critical. As we start using unlinked Baseline, we are loading
CodeBlock from JSFunction instead of embedding it, and it roughly contributes to 0.5% regression in Speedometer2.
It is also crucial to some other places: bound function thunk, remote function thunk, and virtual function calls.
While the subsequent patch will embed CodeBlock into CallLinkInfo to make it fast, we also would like to keep loading
CodeBlock from JSFunction faster since this is still used in bound function thunk etc.

In this patch, we remove ExecutableToCodeBlockEdge to remove one-level indirection between Executable to CodeBlock.
We can delegate ExecutableToCodeBlockEdge's job to existing Executables so that we can keep the current weak-edge
feature without introducing ExecutableToCodeBlockEdge. It also removes ExecutableToCodeBlockEdge allocations and
shrinks sizeof(CodeBlock) by 8 byte.

We move key functions from ExecutableToCodeBlockEdge to ScriptExecutable, and we maintain Executable-to-CodeBlock edge
in Executable side.

Local testing showed that 0.3% progression in Speedometer2.

  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::visitChildrenImpl):
(JSC::CodeBlock::visitChildren):
(JSC::CodeBlock::finalizeUnconditionally):
(JSC::CodeBlock::stronglyVisitStrongReferences):
(JSC::CodeBlock::finishCreationCommon): Deleted.

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::ownerEdge const): Deleted.

  • bytecode/ExecutableToCodeBlockEdge.cpp: Removed.
  • bytecode/ExecutableToCodeBlockEdge.h: Removed.
  • heap/Heap.cpp:

(JSC::Heap::Heap):
(JSC::Heap::finalizeUnconditionalFinalizers):
(JSC::Heap::deleteAllCodeBlocks):
(JSC::Heap::addCoreConstraints):

  • heap/Heap.h:

(JSC::Heap::ScriptExecutableSpaceAndSet::ScriptExecutableSpaceAndSet):
(JSC::Heap::ScriptExecutableSpaceAndSet::setAndSpaceFor):
(JSC::Heap::ScriptExecutableSpaceAndSet::clearableCodeSetFor):
(JSC::Heap::ScriptExecutableSpaceAndSet::outputConstraintsSetFor):
(JSC::Heap::ScriptExecutableSpaceAndSet::finalizerSetFor):

  • heap/IsoCellSet.h:
  • jit/JIT.cpp:

(JSC::JIT::emitPutCodeBlockToFrameInPrologue):

  • llint/LowLevelInterpreter.asm:
  • runtime/DirectEvalExecutable.cpp:

(JSC::DirectEvalExecutable::create):

  • runtime/EvalExecutable.cpp:

(JSC::EvalExecutable::visitChildrenImpl):

  • runtime/EvalExecutable.h:

(JSC::EvalExecutable::codeBlock const):
(JSC::EvalExecutable::unlinkedCodeBlock const):
(JSC::EvalExecutable::numVariables):
(JSC::EvalExecutable::numFunctionHoistingCandidates):
(JSC::EvalExecutable::numTopLevelFunctionDecls):
(JSC::EvalExecutable::allowDirectEvalCache const):
(JSC::EvalExecutable::codeBlock): Deleted.

  • runtime/FunctionExecutable.cpp:

(JSC::FunctionExecutable::baselineCodeBlockFor):
(JSC::shouldKeepInConstraintSet):
(JSC::FunctionExecutable::visitChildrenImpl):
(JSC::FunctionExecutable::visitOutputConstraintsImpl):

  • runtime/FunctionExecutable.h:
  • runtime/FunctionExecutableInlines.h:

(JSC::FunctionExecutable::finalizeUnconditionally):
(JSC::FunctionExecutable::replaceCodeBlockWith):
(JSC::FunctionExecutable::toString):

  • runtime/GlobalExecutable.cpp:

(JSC::GlobalExecutable::visitChildrenImpl):
(JSC::GlobalExecutable::visitOutputConstraintsImpl):
(JSC::GlobalExecutable::replaceCodeBlockWith):
(JSC::GlobalExecutable::finalizeUnconditionally):

  • runtime/GlobalExecutable.h:

(JSC::GlobalExecutable::codeBlock const):
(JSC::GlobalExecutable::unlinkedCodeBlock const):

  • runtime/IndirectEvalExecutable.cpp:

(JSC::IndirectEvalExecutable::createImpl):

  • runtime/JSFunction.cpp:
  • runtime/JSModuleRecord.cpp:

(JSC::JSModuleRecord::link):
(JSC::JSModuleRecord::instantiateDeclarations):

  • runtime/ModuleProgramExecutable.cpp:

(JSC::ModuleProgramExecutable::create):
(JSC::ModuleProgramExecutable::visitChildrenImpl):

  • runtime/ModuleProgramExecutable.h:
  • runtime/ProgramExecutable.cpp:

(JSC::ProgramExecutable::initializeGlobalProperties):
(JSC::ProgramExecutable::visitChildrenImpl):

  • runtime/ProgramExecutable.h:
  • runtime/ScriptExecutable.cpp:

(JSC::ScriptExecutable::clearCode):
(JSC::ScriptExecutable::installCode):
(JSC::ScriptExecutable::hasClearableCode const):
(JSC::ScriptExecutable::newCodeBlockFor):
(JSC::ScriptExecutable::runConstraint):
(JSC::ScriptExecutable::visitCodeBlockEdge):

  • runtime/ScriptExecutable.h:
  • runtime/ScriptExecutableInlines.h: Copied from Source/JavaScriptCore/runtime/FunctionExecutableInlines.h.

(JSC::ScriptExecutable::finalizeCodeBlockEdge):

  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:

(JSC::VM::executableToCodeBlockEdgesWithConstraints): Deleted.
(JSC::VM::executableToCodeBlockEdgesWithFinalizers): Deleted.

Location:
trunk/Source/JavaScriptCore
Files:
2 deleted
30 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r292083 r292191  
    628628    bytecode/DirectEvalCodeCache.h
    629629    bytecode/ExecutableInfo.h
    630     bytecode/ExecutableToCodeBlockEdge.h
    631630    bytecode/ExecutionCounter.h
    632631    bytecode/ExitKind.h
    … …  
    11541153    runtime/Scribble.h
    11551154    runtime/ScriptExecutable.h
     1155    runtime/ScriptExecutableInlines.h
    11561156    runtime/ScriptFetchParameters.h
    11571157    runtime/ScriptFetcher.h
  • trunk/Source/JavaScriptCore/ChangeLog

    r292181 r292191  
     12022-03-31  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Remove ExecutableToCodeBlockEdge
     4        https://bugs.webkit.org/show_bug.cgi?id=238485
     5
     6        Reviewed by Keith Miller.
     7
     8        It turned out that getting CodeBlock from JSFunction is critical. As we start using unlinked Baseline, we are loading
     9        CodeBlock from JSFunction instead of embedding it, and it roughly contributes to 0.5% regression in Speedometer2.
     10        It is also crucial to some other places: bound function thunk, remote function thunk, and virtual function calls.
     11        While the subsequent patch will embed CodeBlock into CallLinkInfo to make it fast, we also would like to keep loading
     12        CodeBlock from JSFunction faster since this is still used in bound function thunk etc.
     13
     14        In this patch, we remove ExecutableToCodeBlockEdge to remove one-level indirection between Executable to CodeBlock.
     15        We can delegate ExecutableToCodeBlockEdge's job to existing Executables so that we can keep the current weak-edge
     16        feature without introducing ExecutableToCodeBlockEdge. It also removes ExecutableToCodeBlockEdge allocations and
     17        shrinks sizeof(CodeBlock) by 8 byte.
     18
     19        We move key functions from ExecutableToCodeBlockEdge to ScriptExecutable, and we maintain Executable-to-CodeBlock edge
     20        in Executable side.
     21
     22        Local testing showed that 0.3% progression in Speedometer2.
     23
     24        * CMakeLists.txt:
     25        * JavaScriptCore.xcodeproj/project.pbxproj:
     26        * Sources.txt:
     27        * bytecode/CodeBlock.cpp:
     28        (JSC::CodeBlock::finishCreation):
     29        (JSC::CodeBlock::visitChildrenImpl):
     30        (JSC::CodeBlock::visitChildren):
     31        (JSC::CodeBlock::finalizeUnconditionally):
     32        (JSC::CodeBlock::stronglyVisitStrongReferences):
     33        (JSC::CodeBlock::finishCreationCommon): Deleted.
     34        * bytecode/CodeBlock.h:
     35        (JSC::CodeBlock::ownerEdge const): Deleted.
     36        * bytecode/ExecutableToCodeBlockEdge.cpp: Removed.
     37        * bytecode/ExecutableToCodeBlockEdge.h: Removed.
     38        * heap/Heap.cpp:
     39        (JSC::Heap::Heap):
     40        (JSC::Heap::finalizeUnconditionalFinalizers):
     41        (JSC::Heap::deleteAllCodeBlocks):
     42        (JSC::Heap::addCoreConstraints):
     43        * heap/Heap.h:
     44        (JSC::Heap::ScriptExecutableSpaceAndSet::ScriptExecutableSpaceAndSet):
     45        (JSC::Heap::ScriptExecutableSpaceAndSet::setAndSpaceFor):
     46        (JSC::Heap::ScriptExecutableSpaceAndSet::clearableCodeSetFor):
     47        (JSC::Heap::ScriptExecutableSpaceAndSet::outputConstraintsSetFor):
     48        (JSC::Heap::ScriptExecutableSpaceAndSet::finalizerSetFor):
     49        * heap/IsoCellSet.h:
     50        * jit/JIT.cpp:
     51        (JSC::JIT::emitPutCodeBlockToFrameInPrologue):
     52        * llint/LowLevelInterpreter.asm:
     53        * runtime/DirectEvalExecutable.cpp:
     54        (JSC::DirectEvalExecutable::create):
     55        * runtime/EvalExecutable.cpp:
     56        (JSC::EvalExecutable::visitChildrenImpl):
     57        * runtime/EvalExecutable.h:
     58        (JSC::EvalExecutable::codeBlock const):
     59        (JSC::EvalExecutable::unlinkedCodeBlock const):
     60        (JSC::EvalExecutable::numVariables):
     61        (JSC::EvalExecutable::numFunctionHoistingCandidates):
     62        (JSC::EvalExecutable::numTopLevelFunctionDecls):
     63        (JSC::EvalExecutable::allowDirectEvalCache const):
     64        (JSC::EvalExecutable::codeBlock): Deleted.
     65        * runtime/FunctionExecutable.cpp:
     66        (JSC::FunctionExecutable::baselineCodeBlockFor):
     67        (JSC::shouldKeepInConstraintSet):
     68        (JSC::FunctionExecutable::visitChildrenImpl):
     69        (JSC::FunctionExecutable::visitOutputConstraintsImpl):
     70        * runtime/FunctionExecutable.h:
     71        * runtime/FunctionExecutableInlines.h:
     72        (JSC::FunctionExecutable::finalizeUnconditionally):
     73        (JSC::FunctionExecutable::replaceCodeBlockWith):
     74        (JSC::FunctionExecutable::toString):
     75        * runtime/GlobalExecutable.cpp:
     76        (JSC::GlobalExecutable::visitChildrenImpl):
     77        (JSC::GlobalExecutable::visitOutputConstraintsImpl):
     78        (JSC::GlobalExecutable::replaceCodeBlockWith):
     79        (JSC::GlobalExecutable::finalizeUnconditionally):
     80        * runtime/GlobalExecutable.h:
     81        (JSC::GlobalExecutable::codeBlock const):
     82        (JSC::GlobalExecutable::unlinkedCodeBlock const):
     83        * runtime/IndirectEvalExecutable.cpp:
     84        (JSC::IndirectEvalExecutable::createImpl):
     85        * runtime/JSFunction.cpp:
     86        * runtime/JSModuleRecord.cpp:
     87        (JSC::JSModuleRecord::link):
     88        (JSC::JSModuleRecord::instantiateDeclarations):
     89        * runtime/ModuleProgramExecutable.cpp:
     90        (JSC::ModuleProgramExecutable::create):
     91        (JSC::ModuleProgramExecutable::visitChildrenImpl):
     92        * runtime/ModuleProgramExecutable.h:
     93        * runtime/ProgramExecutable.cpp:
     94        (JSC::ProgramExecutable::initializeGlobalProperties):
     95        (JSC::ProgramExecutable::visitChildrenImpl):
     96        * runtime/ProgramExecutable.h:
     97        * runtime/ScriptExecutable.cpp:
     98        (JSC::ScriptExecutable::clearCode):
     99        (JSC::ScriptExecutable::installCode):
     100        (JSC::ScriptExecutable::hasClearableCode const):
     101        (JSC::ScriptExecutable::newCodeBlockFor):
     102        (JSC::ScriptExecutable::runConstraint):
     103        (JSC::ScriptExecutable::visitCodeBlockEdge):
     104        * runtime/ScriptExecutable.h:
     105        * runtime/ScriptExecutableInlines.h: Copied from Source/JavaScriptCore/runtime/FunctionExecutableInlines.h.
     106        (JSC::ScriptExecutable::finalizeCodeBlockEdge):
     107        * runtime/VM.cpp:
     108        (JSC::VM::VM):
     109        * runtime/VM.h:
     110        (JSC::VM::executableToCodeBlockEdgesWithConstraints): Deleted.
     111        (JSC::VM::executableToCodeBlockEdgesWithFinalizers): Deleted.
     112
    11132022-03-31  Patrick Angle  <pangle@apple.com>
    2114
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r292083 r292191  
    371371                0F5E0FE72086AD480097F0DE /* IsoSubspacePerVM.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5E0FE52086AD460097F0DE /* IsoSubspacePerVM.h */; settings = {ATTRIBUTES = (Private, ); }; };
    372372                0F5EF91F16878F7D003E5C25 /* JITThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5EF91C16878F78003E5C25 /* JITThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
    373                 0F60FE901FFC37020003320A /* ExecutableToCodeBlockEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F60FE8E1FFC36FD0003320A /* ExecutableToCodeBlockEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
    374373                0F61832A1C45BF070072450B /* AirCCallingConvention.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183211C45BF070072450B /* AirCCallingConvention.h */; };
    375374                0F61832D1C45BF070072450B /* AirEmitShuffle.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183241C45BF070072450B /* AirEmitShuffle.h */; };
    … …  
    19901989                E386FD7F26E867B800E4C28B /* TemporalPlainTimePrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = E386FD7926E867B800E4C28B /* TemporalPlainTimePrototype.h */; };
    19911990                E3893A1D2203A7C600E79A74 /* AsyncFromSyncIteratorPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E3893A1C2203A7C600E79A74 /* AsyncFromSyncIteratorPrototype.lut.h */; };
     1991                E38DB2E727F588F80027BD3F /* ScriptExecutableInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E38DB2E627F588F70027BD3F /* ScriptExecutableInlines.h */; };
    19921992                E38E8790254B978400F6F9E4 /* JSDateMath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9788FC221471AD0C0068CE2D /* JSDateMath.cpp */; };
    19931993                E39006212208BFC4001019CF /* SubspaceAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = E39006202208BFC3001019CF /* SubspaceAccess.h */; settings = {ATTRIBUTES = (Private, ); }; };
    … …  
    28982898                0F5EF91B16878F78003E5C25 /* JITThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITThunks.cpp; sourceTree = "<group>"; };
    28992899                0F5EF91C16878F78003E5C25 /* JITThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITThunks.h; sourceTree = "<group>"; };
    2900                 0F60FE8D1FFC36FC0003320A /* ExecutableToCodeBlockEdge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableToCodeBlockEdge.cpp; sourceTree = "<group>"; };
    2901                 0F60FE8E1FFC36FD0003320A /* ExecutableToCodeBlockEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutableToCodeBlockEdge.h; sourceTree = "<group>"; };
    29022900                0F6183201C45BF070072450B /* AirCCallingConvention.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirCCallingConvention.cpp; path = b3/air/AirCCallingConvention.cpp; sourceTree = "<group>"; };
    29032901                0F6183211C45BF070072450B /* AirCCallingConvention.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirCCallingConvention.h; path = b3/air/AirCCallingConvention.h; sourceTree = "<group>"; };
    … …  
    54805478                E38D060C1F8E814100649CF2 /* ScriptFetchParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptFetchParameters.h; sourceTree = "<group>"; };
    54815479                E38D060D1F8E814100649CF2 /* JSScriptFetchParameters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSScriptFetchParameters.cpp; sourceTree = "<group>"; };
     5480                E38DB2E627F588F70027BD3F /* ScriptExecutableInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptExecutableInlines.h; sourceTree = "<group>"; };
    54825481                E39006202208BFC3001019CF /* SubspaceAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubspaceAccess.h; sourceTree = "<group>"; };
    54835482                E3915C062309682900CB2561 /* WasmContext.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WasmContext.cpp; sourceTree = "<group>"; };
    … …  
    82258224                                147341E01DC2CE9600AA29BA /* ScriptExecutable.cpp */,
    82268225                                147341CD1DC02D7900AA29BA /* ScriptExecutable.h */,
     8226                                E38DB2E627F588F70027BD3F /* ScriptExecutableInlines.h */,
    82278227                                8852151A9C3842389B3215B7 /* ScriptFetcher.h */,
    82288228                                E38D060C1F8E814100649CF2 /* ScriptFetchParameters.h */,
    … …  
    89788978                                14AD91061DCA92940014F9FE /* EvalCodeBlock.h */,
    89798979                                14142E521B796EDD00F4BF4B /* ExecutableInfo.h */,
    8980                                 0F60FE8D1FFC36FC0003320A /* ExecutableToCodeBlockEdge.cpp */,
    8981                                 0F60FE8E1FFC36FD0003320A /* ExecutableToCodeBlockEdge.h */,
    89828980                                0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */,
    89838981                                0F56A1D115000F31002992B1 /* ExecutionCounter.h */,
    … …  
    1027410272                                14142E531B796EDD00F4BF4B /* ExecutableInfo.h in Headers */,
    1027510273                                0F5193F7266C432D00483A2C /* ExecutableMemoryHandle.h in Headers */,
    10276                                 0F60FE901FFC37020003320A /* ExecutableToCodeBlockEdge.h in Headers */,
    1027710274                                0F56A1D315000F35002992B1 /* ExecutionCounter.h in Headers */,
    1027810275                                0F44A7B020BF68620022B171 /* ExitFlag.h in Headers */,
    … …  
    1104511042                                A5FD007E189B0B4C00633231 /* ScriptCallStackFactory.h in Headers */,
    1104611043                                147341CE1DC02D7900AA29BA /* ScriptExecutable.h in Headers */,
     11044                                E38DB2E727F588F80027BD3F /* ScriptExecutableInlines.h in Headers */,
    1104711045                                CEAE7D7B889B477BA93ABA6C /* ScriptFetcher.h in Headers */,
    1104811046                                E3201C1E1F8E824C0076A032 /* ScriptFetchParameters.h in Headers */,
  • trunk/Source/JavaScriptCore/Sources.txt

    r290209 r292191  
    230230bytecode/DirectEvalCodeCache.cpp
    231231bytecode/EvalCodeBlock.cpp
    232 bytecode/ExecutableToCodeBlockEdge.cpp
    233232bytecode/ExecutionCounter.cpp
    234233bytecode/ExitFlag.cpp
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r291779 r292191  
    312312{
    313313    Base::finishCreation(vm);
    314     finishCreationCommon(vm);
    315314
    316315    optimizeAfterWarmUp();
    … …  
    368367{
    369368    Base::finishCreation(vm);
    370     finishCreationCommon(vm);
    371369
    372370    ASSERT(vm.heap.isDeferred());
    … …  
    765763
    766764    return true;
    767 }
    768 
    769 void CodeBlock::finishCreationCommon(VM& vm)
    770 {
    771     m_ownerEdge.set(vm, this, ExecutableToCodeBlockEdge::create(vm, this));
    772765}
    773766
    … …  
    10521045    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    10531046    Base::visitChildren(cell, visitor);
    1054     visitor.append(thisObject->m_ownerEdge);
    10551047    thisObject->visitChildren(visitor);
    10561048}
    … …  
    10801072    stronglyVisitWeakReferences(locker, visitor);
    10811073   
    1082     Heap::SpaceAndSet::setFor(*subspace()).add(this);
     1074    Heap::CodeBlockSpaceAndSet::setFor(*subspace()).add(this);
    10831075}
    10841076
    … …  
    16681660    updateActivity();
    16691661
    1670     Heap::SpaceAndSet::setFor(*subspace()).remove(this);
     1662    Heap::CodeBlockSpaceAndSet::setFor(*subspace()).remove(this);
    16711663
    16721664    // In CodeBlock::shouldVisitStrongly() we may have decided to skip visiting this
    … …  
    18351827   
    18361828    visitor.append(m_globalObject);
    1837     visitor.append(m_ownerExecutable); // This is extra important since it causes the ExecutableToCodeBlockEdge to be marked.
     1829    visitor.append(m_ownerExecutable); // This is extra important since it causes the Executable -> CodeBlock edge activated.
    18381830    visitor.append(m_unlinkedCode);
    18391831    if (m_rareData)
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r290788 r292191  
    8888class BytecodeLivenessAnalysis;
    8989class CodeBlockSet;
    90 class ExecutableToCodeBlockEdge;
    9190class JSModuleEnvironment;
    9291class LLIntOffsetsExtractor;
    … …  
    9493class MetadataTable;
    9594class RegisterAtOffsetList;
     95class ScriptExecutable;
    9696class StructureStubInfo;
    9797class BaselineJITCode;
    … …  
    135135    void finishCreation(VM&, CopyParsedBlockTag, CodeBlock& other);
    136136    bool finishCreation(VM&, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*);
    137    
    138     void finishCreationCommon(VM&);
    139137
    140138    WriteBarrier<JSGlobalObject> m_globalObject;
    … …  
    370368    ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); }
    371369   
    372     ExecutableToCodeBlockEdge* ownerEdge() const { return m_ownerEdge.get(); }
    373 
    374370    VM& vm() const { return *m_vm; }
    375371
    … …  
    850846private:
    851847    friend class CodeBlockSet;
    852     friend class ExecutableToCodeBlockEdge;
     848    friend class FunctionExecutable;
     849    friend class ScriptExecutable;
    853850
    854851    template<typename Visitor> ALWAYS_INLINE void visitChildren(Visitor&);
    … …  
    924921    WriteBarrier<UnlinkedCodeBlock> m_unlinkedCode;
    925922    WriteBarrier<ScriptExecutable> m_ownerExecutable;
    926     WriteBarrier<ExecutableToCodeBlockEdge> m_ownerEdge;
    927923    // m_vm must be a pointer (instead of a reference) because the JSCLLIntOffsetsExtractor
    928924    // cannot handle it being a reference.
    … …  
    976972};
    977973#if !ASSERT_ENABLED && COMPILER(GCC_COMPATIBLE)
    978 static_assert(sizeof(CodeBlock) <= 256, "Keep it small for memory saving");
     974static_assert(sizeof(CodeBlock) <= 240, "Keep it small for memory saving");
    979975#endif
    980976
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r290129 r292191  
    369369    FOR_EACH_JSC_COMMON_ISO_SUBSPACE(INIT_SERVER_ISO_SUBSPACE)
    370370    FOR_EACH_JSC_STRUCTURE_ISO_SUBSPACE(INIT_SERVER_STRUCTURE_ISO_SUBSPACE)
    371     , executableToCodeBlockEdgesWithConstraints(executableToCodeBlockEdgeSpace)
    372     , executableToCodeBlockEdgesWithFinalizers(executableToCodeBlockEdgeSpace)
    373371    , codeBlockSpaceAndSet ISO_SUBSPACE_INIT(*this, destructibleCellHeapCellType, CodeBlock) // Hash:0x77e66ec9
    374372    , functionExecutableSpaceAndSet ISO_SUBSPACE_INIT(*this, destructibleCellHeapCellType, FunctionExecutable) // Hash:0x5d158f3
    … …  
    675673    VM& vm = this->vm();
    676674    vm.builtinExecutables()->finalizeUnconditionally();
    677     finalizeMarkedUnconditionalFinalizers<FunctionExecutable>(functionExecutableSpaceAndSet.space);
     675
     676    {
     677        // We run this before CodeBlock's unconditional finalizer since CodeBlock looks at the owner executable's installed CodeBlock in its finalizeUnconditionally.
     678
     679        // FunctionExecutable requires all live instances to run finalizers. Thus, we do not use finalizer set.
     680        finalizeMarkedUnconditionalFinalizers<FunctionExecutable>(functionExecutableSpaceAndSet.space);
     681
     682        finalizeMarkedUnconditionalFinalizers<ProgramExecutable>(programExecutableSpaceAndSet.finalizerSet);
     683        if (m_evalExecutableSpace)
     684            finalizeMarkedUnconditionalFinalizers<EvalExecutable>(m_evalExecutableSpace->finalizerSet);
     685        if (m_moduleProgramExecutableSpace)
     686            finalizeMarkedUnconditionalFinalizers<ModuleProgramExecutable>(m_moduleProgramExecutableSpace->finalizerSet);
     687    }
     688
    678689    finalizeMarkedUnconditionalFinalizers<SymbolTable>(symbolTableSpace);
    679     finalizeMarkedUnconditionalFinalizers<ExecutableToCodeBlockEdge>(executableToCodeBlockEdgesWithFinalizers); // We run this before CodeBlock's unconditional finalizer since CodeBlock looks at the owner executable's installed CodeBlock in its finalizeUnconditionally.
     690
    680691    forEachCodeBlockSpace(
    681692        [&] (auto& space) {
    … …  
    10041015        [&] (auto& spaceAndSet) {
    10051016            HeapIterationScope heapIterationScope(*this);
    1006             auto& set = spaceAndSet.set;
     1017            auto& set = spaceAndSet.clearableCodeSet;
    10071018            set.forEachLiveCell(
    10081019                [&] (HeapCell* cell, HeapCell::Kind) {
    … …  
    29182929            {
    29192930                SetRootMarkReasonScope rootScope(visitor, RootMarkReason::ExecutableToCodeBlockEdges);
    2920                 add(heap->executableToCodeBlockEdgesWithConstraints);
     2931                add(heap->functionExecutableSpaceAndSet.outputConstraintsSet);
     2932                add(heap->programExecutableSpaceAndSet.outputConstraintsSet);
     2933                if (heap->m_evalExecutableSpace)
     2934                    add(heap->m_evalExecutableSpace->outputConstraintsSet);
     2935                if (heap->m_moduleProgramExecutableSpace)
     2936                    add(heap->m_moduleProgramExecutableSpace->outputConstraintsSet);
    29212937            }
    29222938            if (heap->m_weakMapSpace) {
    … …  
    31703186#undef DEFINE_DYNAMIC_ISO_SUBSPACE_MEMBER_SLOW
    31713187
    3172 #define DEFINE_DYNAMIC_SPACE_AND_SET_MEMBER_SLOW(name, heapCellType, type) \
     3188#define DEFINE_DYNAMIC_SPACE_AND_SET_MEMBER_SLOW(name, heapCellType, type, spaceType) \
    31733189    IsoSubspace* Heap::name##Slow() \
    31743190    { \
    31753191        ASSERT(!m_##name); \
    3176         auto space = makeUnique<SpaceAndSet> ISO_SUBSPACE_INIT(*this, heapCellType, type); \
     3192        auto space = makeUnique<spaceType> ISO_SUBSPACE_INIT(*this, heapCellType, type); \
    31773193        WTF::storeStoreFence(); \
    31783194        m_##name = WTFMove(space); \
    … …  
    31803196    }
    31813197
    3182 DEFINE_DYNAMIC_SPACE_AND_SET_MEMBER_SLOW(evalExecutableSpace, destructibleCellHeapCellType, EvalExecutable) // Hash:0x958e3e9d
    3183 DEFINE_DYNAMIC_SPACE_AND_SET_MEMBER_SLOW(moduleProgramExecutableSpace, destructibleCellHeapCellType, ModuleProgramExecutable) // Hash:0x6506fa3c
     3198DEFINE_DYNAMIC_SPACE_AND_SET_MEMBER_SLOW(evalExecutableSpace, destructibleCellHeapCellType, EvalExecutable, Heap::ScriptExecutableSpaceAndSets) // Hash:0x958e3e9d
     3199DEFINE_DYNAMIC_SPACE_AND_SET_MEMBER_SLOW(moduleProgramExecutableSpace, destructibleCellHeapCellType, ModuleProgramExecutable, Heap::ScriptExecutableSpaceAndSets) // Hash:0x6506fa3c
    31843200
    31853201#undef DEFINE_DYNAMIC_SPACE_AND_SET_MEMBER_SLOW
  • trunk/Source/JavaScriptCore/heap/Heap.h

    r290209 r292191  
    121121    v(domAttributeGetterSetterSpace, cellHeapCellType, DOMAttributeGetterSetter) \
    122122    v(exceptionSpace, destructibleCellHeapCellType, Exception) \
    123     v(executableToCodeBlockEdgeSpace, cellHeapCellType, ExecutableToCodeBlockEdge) \
    124123    v(functionSpace, cellHeapCellType, JSFunction) \
    125124    v(getterSetterSpace, cellHeapCellType, GetterSetter) \
    … …  
    10301029#undef DEFINE_DYNAMIC_ISO_SUBSPACE_MEMBER
    10311030   
    1032     IsoCellSet executableToCodeBlockEdgesWithConstraints;
    1033     IsoCellSet executableToCodeBlockEdgesWithFinalizers;
    1034 
    1035 #define DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(name) \
     1031#define DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(name, type) \
    10361032    template<SubspaceAccess mode> \
    10371033    IsoSubspace* name() \
    … …  
    10441040    } \
    10451041    IsoSubspace* name##Slow(); \
    1046     std::unique_ptr<SpaceAndSet> m_##name;
     1042    std::unique_ptr<type> m_##name;
    10471043   
    10481044    struct SpaceAndSet {
    … …  
    10681064    };
    10691065
    1070     SpaceAndSet codeBlockSpaceAndSet;
     1066    using CodeBlockSpaceAndSet = SpaceAndSet;
     1067    CodeBlockSpaceAndSet codeBlockSpaceAndSet;
    10711068
    10721069    template<typename Func>
    … …  
    10761073    }
    10771074
    1078     DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(evalExecutableSpace)
    1079     DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(moduleProgramExecutableSpace)
    1080     SpaceAndSet functionExecutableSpaceAndSet;
    1081     SpaceAndSet programExecutableSpaceAndSet;
     1075    struct ScriptExecutableSpaceAndSets {
     1076        WTF_MAKE_STRUCT_FAST_ALLOCATED;
     1077
     1078        IsoSubspace space;
     1079        IsoCellSet clearableCodeSet;
     1080        IsoCellSet outputConstraintsSet;
     1081        IsoCellSet finalizerSet;
     1082
     1083        template<typename... Arguments>
     1084        ScriptExecutableSpaceAndSets(Arguments&&... arguments)
     1085            : space(std::forward<Arguments>(arguments)...)
     1086            , clearableCodeSet(space)
     1087            , outputConstraintsSet(space)
     1088            , finalizerSet(space)
     1089        {
     1090        }
     1091
     1092        static ScriptExecutableSpaceAndSets& setAndSpaceFor(Subspace& space)
     1093        {
     1094            return *bitwise_cast<ScriptExecutableSpaceAndSets*>(
     1095                bitwise_cast<char*>(&space) -
     1096                OBJECT_OFFSETOF(ScriptExecutableSpaceAndSets, space));
     1097        }
     1098
     1099        static IsoCellSet& clearableCodeSetFor(Subspace& space) { return setAndSpaceFor(space).clearableCodeSet; }
     1100        static IsoCellSet& outputConstraintsSetFor(Subspace& space) { return setAndSpaceFor(space).outputConstraintsSet; }
     1101        static IsoCellSet& finalizerSetFor(Subspace& space) { return setAndSpaceFor(space).finalizerSet; }
     1102    };
     1103
     1104    DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(evalExecutableSpace, ScriptExecutableSpaceAndSets)
     1105    DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(moduleProgramExecutableSpace, ScriptExecutableSpaceAndSets)
     1106    ScriptExecutableSpaceAndSets functionExecutableSpaceAndSet;
     1107    ScriptExecutableSpaceAndSets programExecutableSpaceAndSet;
    10821108
    10831109    template<typename Func>
    … …  
    10921118    }
    10931119
    1094     SpaceAndSet unlinkedFunctionExecutableSpaceAndSet;
     1120    using UnlinkedFunctionExecutableSpaceAndSet = SpaceAndSet;
     1121    UnlinkedFunctionExecutableSpaceAndSet unlinkedFunctionExecutableSpaceAndSet;
    10951122
    10961123    Vector<IsoSubspacePerVM*> perVMIsoSubspaces;
  • trunk/Source/JavaScriptCore/heap/IsoCellSet.h

    r273138 r292191  
    3030#include <wtf/ConcurrentVector.h>
    3131#include <wtf/FastBitVector.h>
     32#include <wtf/Noncopyable.h>
     33#include <wtf/Nonmovable.h>
    3234#include <wtf/SentinelLinkedList.h>
    3335#include <wtf/SharedTask.h>
    … …  
    4143// removal. Each such set should be thought of as a 0.8% increase in object size for objects in that
    4244// IsoSubspace (it's like adding 1 bit every 16 bytes, or 1 bit every 128 bits).
    43 class IsoCellSet : public PackedRawSentinelNode<IsoCellSet> {
     45class IsoCellSet final : public PackedRawSentinelNode<IsoCellSet> {
     46    WTF_MAKE_NONCOPYABLE(IsoCellSet);
     47    WTF_MAKE_NONMOVABLE(IsoCellSet);
    4448public:
    4549    IsoCellSet(IsoSubspace& subspace);
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r292083 r292191  
    216216    else
    217217        loadPtr(Address(result, FunctionExecutable::offsetOfCodeBlockForCall()), result);
    218 
    219     loadPtr(Address(result, ExecutableToCodeBlockEdge::offsetOfCodeBlock()), result);
    220218    emitPutToCallFrameHeader(result, CallFrameSlot::codeBlock);
    221219
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r292080 r292191  
    14941494.isExecutable:
    14951495    loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister
    1496     loadp ExecutableToCodeBlockEdge::m_codeBlock[targetRegister], targetRegister
    14971496end
    14981497
    … …  
    15081507.isExecutable:
    15091508    loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister
    1510     loadp ExecutableToCodeBlockEdge::m_codeBlock[targetRegister], targetRegister
    15111509end
    15121510
  • trunk/Source/JavaScriptCore/runtime/DirectEvalExecutable.cpp

    r287303 r292191  
    6464    }
    6565
    66     executable->m_unlinkedEvalCodeBlock.set(vm, executable, unlinkedEvalCode);
     66    executable->m_unlinkedCodeBlock.set(vm, executable, unlinkedEvalCode);
    6767
    6868    return executable;
  • trunk/Source/JavaScriptCore/runtime/EvalExecutable.cpp

    r291779 r292191  
    5757    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    5858    Base::visitChildren(thisObject, visitor);
    59     visitor.append(thisObject->m_unlinkedEvalCodeBlock);
    60     visitor.append(thisObject->m_evalCodeBlock);
    6159    if (TemplateObjectMap* map = thisObject->m_templateObjectMap.get()) {
    6260        Locker locker { thisObject->cellLock() };
  • trunk/Source/JavaScriptCore/runtime/EvalExecutable.h

    r290129 r292191  
    2626#pragma once
    2727
    28 #include "ExecutableToCodeBlockEdge.h"
    2928#include "GlobalExecutable.h"
    3029#include "UnlinkedEvalCodeBlock.h"
    … …  
    4039    static void destroy(JSCell*);
    4140   
    42     EvalCodeBlock* codeBlock()
     41    EvalCodeBlock* codeBlock() const
    4342    {
    44         return bitwise_cast<EvalCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_evalCodeBlock.get()));
     43        return bitwise_cast<EvalCodeBlock*>(Base::codeBlock());
     44    }
     45
     46    UnlinkedEvalCodeBlock* unlinkedCodeBlock() const
     47    {
     48        return bitwise_cast<UnlinkedEvalCodeBlock*>(Base::unlinkedCodeBlock());
    4549    }
    4650
    … …  
    6367    DECLARE_INFO;
    6468
    65     unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
    66     unsigned numFunctionHoistingCandidates() { return m_unlinkedEvalCodeBlock->numFunctionHoistingCandidates(); }
    67     unsigned numTopLevelFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
    68     bool allowDirectEvalCache() const { return m_unlinkedEvalCodeBlock->allowDirectEvalCache(); }
     69    unsigned numVariables() { return unlinkedCodeBlock()->numVariables(); }
     70    unsigned numFunctionHoistingCandidates() { return unlinkedCodeBlock()->numFunctionHoistingCandidates(); }
     71    unsigned numTopLevelFunctionDecls() { return unlinkedCodeBlock()->numberOfFunctionDecls(); }
     72    bool allowDirectEvalCache() const { return unlinkedCodeBlock()->allowDirectEvalCache(); }
    6973    NeedsClassFieldInitializer needsClassFieldInitializer() const { return static_cast<NeedsClassFieldInitializer>(m_needsClassFieldInitializer); }
    7074    PrivateBrandRequirement privateBrandRequirement() const { return static_cast<PrivateBrandRequirement>(m_privateBrandRequirement); }
    … …  
    8387    unsigned m_privateBrandRequirement : 1;
    8488
    85     WriteBarrier<ExecutableToCodeBlockEdge> m_evalCodeBlock;
    86     WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
    8789    std::unique_ptr<TemplateObjectMap> m_templateObjectMap;
    8890};
  • trunk/Source/JavaScriptCore/runtime/FunctionExecutable.cpp

    r291779 r292191  
    2525
    2626#include "config.h"
     27#include "FunctionExecutable.h"
    2728
    2829#include "CodeBlock.h"
    2930#include "FunctionCodeBlock.h"
     31#include "FunctionExecutableInlines.h"
    3032#include "FunctionOverrides.h"
     33#include "IsoCellSetInlines.h"
    3134#include "JSCJSValueInlines.h"
    3235
    … …  
    5659FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
    5760{
    58     ExecutableToCodeBlockEdge* edge;
     61    CodeBlock* codeBlock = nullptr;
    5962    if (kind == CodeForCall)
    60         edge = m_codeBlockForCall.get();
     63        codeBlock = codeBlockForCall();
    6164    else {
    6265        RELEASE_ASSERT(kind == CodeForConstruct);
    63         edge = m_codeBlockForConstruct.get();
    64     }
    65     if (!edge)
     66        codeBlock = codeBlockForConstruct();
     67    }
     68    if (!codeBlock)
    6669        return nullptr;
    67     return static_cast<FunctionCodeBlock*>(edge->codeBlock()->baselineAlternative());
     70    return static_cast<FunctionCodeBlock*>(codeBlock->baselineAlternative());
     71}
     72
     73template<typename Visitor>
     74static inline bool shouldKeepInConstraintSet(Visitor& visitor, CodeBlock* codeBlockForCall, CodeBlock* codeBlockForConstruct)
     75{
     76    // If either CodeBlock is not marked yet, we will run output-constraints.
     77    return (codeBlockForCall && !visitor.isMarked(codeBlockForCall)) || (codeBlockForConstruct && !visitor.isMarked(codeBlockForConstruct));
    6878}
    6979
    … …  
    7181void FunctionExecutable::visitChildrenImpl(JSCell* cell, Visitor& visitor)
    7282{
     83    VM& vm = visitor.vm();
    7384    FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
    7485    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    7586    Base::visitChildren(thisObject, visitor);
    7687    visitor.append(thisObject->m_topLevelExecutable);
    77     visitor.append(thisObject->m_codeBlockForCall);
    78     visitor.append(thisObject->m_codeBlockForConstruct);
    7988    visitor.append(thisObject->m_unlinkedExecutable);
    8089    if (RareData* rareData = thisObject->m_rareData.get()) {
    … …  
    8796        }
    8897    }
     98
     99    // Since FunctionExecutable's finalizer always needs to be run, we do not track FunctionExecutable via finalizerSet.
     100    auto* codeBlockForCall = thisObject->m_codeBlockForCall.get();
     101    if (codeBlockForCall)
     102        visitCodeBlockEdge(visitor, codeBlockForCall);
     103    auto* codeBlockForConstruct = thisObject->m_codeBlockForConstruct.get();
     104    if (codeBlockForConstruct)
     105        visitCodeBlockEdge(visitor, codeBlockForConstruct);
     106
     107    if (shouldKeepInConstraintSet(visitor, codeBlockForCall, codeBlockForConstruct))
     108        vm.heap.functionExecutableSpaceAndSet.outputConstraintsSet.add(thisObject);
    89109}
    90110
    91111DEFINE_VISIT_CHILDREN(FunctionExecutable);
     112
     113template<typename Visitor>
     114void FunctionExecutable::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor)
     115{
     116    VM& vm = visitor.vm();
     117    auto* executable = jsCast<FunctionExecutable*>(cell);
     118    auto* codeBlockForCall = executable->m_codeBlockForCall.get();
     119    if (codeBlockForCall) {
     120        if (!visitor.isMarked(codeBlockForCall))
     121            runConstraint(NoLockingNecessary, visitor, codeBlockForCall);
     122    }
     123    auto* codeBlockForConstruct = executable->codeBlockForConstruct();
     124    if (codeBlockForConstruct) {
     125        if (!visitor.isMarked(codeBlockForConstruct))
     126            runConstraint(NoLockingNecessary, visitor, codeBlockForConstruct);
     127    }
     128
     129    if (!shouldKeepInConstraintSet(visitor, codeBlockForCall, codeBlockForConstruct))
     130        vm.heap.functionExecutableSpaceAndSet.outputConstraintsSet.remove(executable);
     131}
     132
     133DEFINE_VISIT_OUTPUT_CONSTRAINTS(FunctionExecutable);
    92134
    93135FunctionExecutable* FunctionExecutable::fromGlobalCode(
  • trunk/Source/JavaScriptCore/runtime/FunctionExecutable.h

    r290129 r292191  
    2626#pragma once
    2727
    28 #include "ExecutableToCodeBlockEdge.h"
    2928#include "JSFunction.h"
    3029#include "ScriptExecutable.h"
    … …  
    7069    // for answering questions that that don't vary between call and construct --
    7170    // for example, argumentsRegister().
    72     FunctionCodeBlock* eitherCodeBlock()
    73     {
    74         ExecutableToCodeBlockEdge* edge;
    75         if (m_codeBlockForCall)
    76             edge = m_codeBlockForCall.get();
    77         else
    78             edge = m_codeBlockForConstruct.get();
    79         return bitwise_cast<FunctionCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(edge));
     71    FunctionCodeBlock* eitherCodeBlock() const
     72    {
     73        if (auto* result = codeBlockForCall())
     74            return result;
     75        return codeBlockForConstruct();
    8076    }
    8177       
    8278    bool isGeneratedForCall() const
    8379    {
    84         return !!m_codeBlockForCall;
    85     }
    86 
    87     FunctionCodeBlock* codeBlockForCall()
    88     {
    89         return bitwise_cast<FunctionCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_codeBlockForCall.get()));
     80        return !!codeBlockForCall();
     81    }
     82
     83    FunctionCodeBlock* codeBlockForCall() const
     84    {
     85        return bitwise_cast<FunctionCodeBlock*>(m_codeBlockForCall.get());
    9086    }
    9187
    9288    bool isGeneratedForConstruct() const
    9389    {
    94         return !!m_codeBlockForConstruct;
    95     }
    96 
    97     FunctionCodeBlock* codeBlockForConstruct()
    98     {
    99         return bitwise_cast<FunctionCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_codeBlockForConstruct.get()));
     90        return !!codeBlockForConstruct();
     91    }
     92
     93    FunctionCodeBlock* codeBlockForConstruct() const
     94    {
     95        return bitwise_cast<FunctionCodeBlock*>(m_codeBlockForConstruct.get());
    10096    }
    10197       
    … …  
    122118        return baselineCodeBlockFor(kind);
    123119    }
     120
     121    FunctionCodeBlock* replaceCodeBlockWith(VM&, CodeSpecializationKind, CodeBlock*);
    124122
    125123    RefPtr<TypeSet> returnStatementTypeSet()
    … …  
    163161
    164162    DECLARE_VISIT_CHILDREN;
     163    DECLARE_VISIT_OUTPUT_CONSTRAINTS;
    165164    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
    166165    {
    … …  
    332331    WriteBarrier<ScriptExecutable> m_topLevelExecutable;
    333332    WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
    334     WriteBarrier<ExecutableToCodeBlockEdge> m_codeBlockForCall;
    335     WriteBarrier<ExecutableToCodeBlockEdge> m_codeBlockForConstruct;
     333    WriteBarrier<CodeBlock> m_codeBlockForCall;
     334    WriteBarrier<CodeBlock> m_codeBlockForConstruct;
    336335    InferredValue<JSFunction> m_singleton;
    337336    Box<InlineWatchpointSet> m_polyProtoWatchpoint;
  • trunk/Source/JavaScriptCore/runtime/FunctionExecutableInlines.h

    r278462 r292191  
    2828#include "FunctionExecutable.h"
    2929#include "InferredValueInlines.h"
     30#include "ScriptExecutableInlines.h"
    3031
    3132namespace JSC {
    … …  
    3435{
    3536    m_singleton.finalizeUnconditionally(vm);
     37    finalizeCodeBlockEdge(vm, m_codeBlockForCall);
     38    finalizeCodeBlockEdge(vm, m_codeBlockForConstruct);
     39    vm.heap.functionExecutableSpaceAndSet.outputConstraintsSet.remove(this);
    3640}
    3741
    38 JSString* FunctionExecutable::toString(JSGlobalObject* globalObject)
     42inline FunctionCodeBlock* FunctionExecutable::replaceCodeBlockWith(VM& vm, CodeSpecializationKind kind, CodeBlock* newCodeBlock)
     43{
     44    if (kind == CodeForCall) {
     45        FunctionCodeBlock* oldCodeBlock = codeBlockForCall();
     46        m_codeBlockForCall.setMayBeNull(vm, this, newCodeBlock);
     47        return oldCodeBlock;
     48    }
     49    ASSERT(kind == CodeForConstruct);
     50    FunctionCodeBlock* oldCodeBlock = codeBlockForConstruct();
     51    m_codeBlockForConstruct.setMayBeNull(vm, this, newCodeBlock);
     52    return oldCodeBlock;
     53}
     54
     55inline JSString* FunctionExecutable::toString(JSGlobalObject* globalObject)
    3956{
    4057    RareData& rareData = ensureRareData();
  • trunk/Source/JavaScriptCore/runtime/GlobalExecutable.cpp

    r291779 r292191  
    2727#include "GlobalExecutable.h"
    2828
     29#include "IsoCellSetInlines.h"
    2930#include "JSCellInlines.h"
     31#include "ScriptExecutableInlines.h"
    3032
    3133namespace JSC {
    … …  
    3335const ClassInfo GlobalExecutable::s_info = { "GlobalExecutable"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(GlobalExecutable) };
    3436
     37template<typename Visitor>
     38void GlobalExecutable::visitChildrenImpl(JSCell* cell, Visitor& visitor)
     39{
     40    auto* executable = jsCast<GlobalExecutable*>(cell);
     41    ASSERT_GC_OBJECT_INHERITS(executable, info());
     42    Base::visitChildren(executable, visitor);
     43    visitor.append(executable->m_unlinkedCodeBlock);
     44
     45    if (auto* codeBlock = executable->codeBlock()) {
     46        // If CodeBlocks is not marked yet, we will run output-constraints.
     47        // We maintain the invariant that, whenever we see unmarked CodeBlock, then we must run finalizer.
     48        // And whenever we set a bit on outputConstraintsSet, we must already set a bit in finalizerSet.
     49        visitCodeBlockEdge(visitor, codeBlock);
     50        if (!visitor.isMarked(codeBlock)) {
     51            Heap::ScriptExecutableSpaceAndSets::finalizerSetFor(*executable->subspace()).add(executable);
     52            Heap::ScriptExecutableSpaceAndSets::outputConstraintsSetFor(*executable->subspace()).add(executable);
     53        }
     54    }
     55}
     56
     57DEFINE_VISIT_CHILDREN(GlobalExecutable);
     58
     59template<typename Visitor>
     60void GlobalExecutable::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor)
     61{
     62    auto* executable = jsCast<GlobalExecutable*>(cell);
     63    if (CodeBlock* codeBlock = executable->codeBlock()) {
     64        if (!visitor.isMarked(codeBlock))
     65            runConstraint(NoLockingNecessary, visitor, codeBlock);
     66        if (visitor.isMarked(codeBlock))
     67            Heap::ScriptExecutableSpaceAndSets::outputConstraintsSetFor(*executable->subspace()).remove(executable);
     68    }
     69}
     70
     71DEFINE_VISIT_OUTPUT_CONSTRAINTS(GlobalExecutable);
     72
     73CodeBlock* GlobalExecutable::replaceCodeBlockWith(VM& vm, CodeBlock* newCodeBlock)
     74{
     75    CodeBlock* oldCodeBlock = codeBlock();
     76    m_codeBlock.setMayBeNull(vm, this, newCodeBlock);
     77    return oldCodeBlock;
     78}
     79
     80void GlobalExecutable::finalizeUnconditionally(VM& vm)
     81{
     82    finalizeCodeBlockEdge(vm, m_codeBlock);
     83    Heap::ScriptExecutableSpaceAndSets::outputConstraintsSetFor(*subspace()).remove(this);
     84    Heap::ScriptExecutableSpaceAndSets::finalizerSetFor(*subspace()).remove(this);
     85}
     86
    3587} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/GlobalExecutable.h

    r278588 r292191  
    2626#pragma once
    2727
    28 #include "ExecutableToCodeBlockEdge.h"
    2928#include "ScriptExecutable.h"
    3029
    … …  
    4948    }
    5049
     50    DECLARE_VISIT_CHILDREN;
     51    DECLARE_VISIT_OUTPUT_CONSTRAINTS;
     52
     53    void finalizeUnconditionally(VM&);
     54
    5155protected:
     56    friend class ScriptExecutable;
    5257    GlobalExecutable(Structure* structure, VM& vm, const SourceCode& sourceCode, bool isInStrictContext, DerivedContextType derivedContextType, bool isInArrowFunctionContext, bool isInsideOrdinaryFunction, EvalContextType evalContextType, Intrinsic intrinsic)
    5358        : Base(structure, vm, sourceCode, isInStrictContext ? StrictModeLexicalFeature : NoLexicalFeatures, derivedContextType, isInArrowFunctionContext, isInsideOrdinaryFunction, evalContextType, intrinsic)
    … …  
    5560    }
    5661
     62    CodeBlock* codeBlock() const
     63    {
     64        return m_codeBlock.get();
     65    }
     66
     67    UnlinkedCodeBlock* unlinkedCodeBlock() const
     68    {
     69        return m_unlinkedCodeBlock.get();
     70    }
     71
     72    CodeBlock* replaceCodeBlockWith(VM&, CodeBlock*);
     73
     74    WriteBarrier<CodeBlock> m_codeBlock;
     75    WriteBarrier<UnlinkedCodeBlock> m_unlinkedCodeBlock;
    5776    int m_lastLine { -1 };
    5877    unsigned m_endColumn { UINT_MAX };
  • trunk/Source/JavaScriptCore/runtime/IndirectEvalExecutable.cpp

    r287303 r292191  
    6666    }
    6767
    68     executable->m_unlinkedEvalCodeBlock.set(vm, executable, unlinkedEvalCode);
     68    executable->m_unlinkedCodeBlock.set(vm, executable, unlinkedEvalCode);
    6969
    7070    return executable;
  • trunk/Source/JavaScriptCore/runtime/JSFunction.cpp

    r291779 r292191  
    3232#include "CommonIdentifiers.h"
    3333#include "CallFrame.h"
     34#include "FunctionExecutableInlines.h"
    3435#include "GeneratorPrototype.h"
    3536#include "JSBoundFunction.h"
  • trunk/Source/JavaScriptCore/runtime/JSModuleRecord.cpp

    r291779 r292191  
    9797    m_moduleProgramExecutable.set(vm, this, executable);
    9898
    99     return executable->unlinkedModuleProgramCodeBlock()->isAsync() ? Synchronousness::Async : Synchronousness::Sync;
     99    return executable->unlinkedCodeBlock()->isAsync() ? Synchronousness::Async : Synchronousness::Sync;
    100100}
    101101
    … …  
    210210    // Initialize heap allocated function declarations.
    211211    // They can be called before the body of the module is executed under circular dependencies.
    212     UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock = moduleProgramExecutable->unlinkedModuleProgramCodeBlock();
     212    UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock = moduleProgramExecutable->unlinkedCodeBlock();
    213213    for (size_t i = 0, numberOfFunctions = unlinkedCodeBlock->numberOfFunctionDecls(); i < numberOfFunctions; ++i) {
    214214        UnlinkedFunctionExecutable* unlinkedFunctionExecutable = unlinkedCodeBlock->functionDecl(i);
  • trunk/Source/JavaScriptCore/runtime/ModuleProgramExecutable.cpp

    r291779 r292191  
    6363    }
    6464
    65     executable->m_unlinkedModuleProgramCodeBlock.set(globalObject->vm(), executable, unlinkedModuleProgramCode);
     65    executable->m_unlinkedCodeBlock.set(globalObject->vm(), executable, unlinkedModuleProgramCode);
    6666
    6767    executable->m_moduleEnvironmentSymbolTable.set(globalObject->vm(), executable, jsCast<SymbolTable*>(unlinkedModuleProgramCode->constantRegister(VirtualRegister(unlinkedModuleProgramCode->moduleEnvironmentSymbolTableConstantRegisterOffset())).get())->cloneScopePart(globalObject->vm()));
    … …  
    8686    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    8787    Base::visitChildren(thisObject, visitor);
    88     visitor.append(thisObject->m_unlinkedModuleProgramCodeBlock);
    8988    visitor.append(thisObject->m_moduleEnvironmentSymbolTable);
    90     visitor.append(thisObject->m_moduleProgramCodeBlock);
    9189    if (TemplateObjectMap* map = thisObject->m_templateObjectMap.get()) {
    9290        Locker locker { thisObject->cellLock() };
  • trunk/Source/JavaScriptCore/runtime/ModuleProgramExecutable.h

    r290129 r292191  
    2626#pragma once
    2727
    28 #include "ExecutableToCodeBlockEdge.h"
    2928#include "GlobalExecutable.h"
    3029
    … …  
    4746    static void destroy(JSCell*);
    4847
    49     ModuleProgramCodeBlock* codeBlock()
     48    ModuleProgramCodeBlock* codeBlock() const
    5049    {
    51         return bitwise_cast<ModuleProgramCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_moduleProgramCodeBlock.get()));
     50        return bitwise_cast<ModuleProgramCodeBlock*>(Base::codeBlock());
     51    }
     52
     53    UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock() const
     54    {
     55        return bitwise_cast<UnlinkedModuleProgramCodeBlock*>(Base::unlinkedCodeBlock());
    5256    }
    5357
    … …  
    6468    DECLARE_INFO;
    6569
    66     UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); }
    6770    bool isAsync() const { return features() & AwaitFeature; }
    6871
    … …  
    7982    DECLARE_VISIT_CHILDREN;
    8083
    81     WriteBarrier<UnlinkedModuleProgramCodeBlock> m_unlinkedModuleProgramCodeBlock;
    8284    WriteBarrier<SymbolTable> m_moduleEnvironmentSymbolTable;
    83     WriteBarrier<ExecutableToCodeBlockEdge> m_moduleProgramCodeBlock;
    8485    std::unique_ptr<TemplateObjectMap> m_templateObjectMap;
    8586};
  • trunk/Source/JavaScriptCore/runtime/ProgramExecutable.cpp

    r291779 r292191  
    151151    }
    152152
    153 
    154     m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCodeBlock);
     153    m_unlinkedCodeBlock.set(vm, this, unlinkedCodeBlock);
    155154
    156155    BatchedTransitionOptimizer optimizer(vm, globalObject);
    … …  
    217216    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    218217    Base::visitChildren(thisObject, visitor);
    219     visitor.append(thisObject->m_unlinkedProgramCodeBlock);
    220     visitor.append(thisObject->m_programCodeBlock);
    221218    if (TemplateObjectMap* map = thisObject->m_templateObjectMap.get()) {
    222219        Locker locker { thisObject->cellLock() };
  • trunk/Source/JavaScriptCore/runtime/ProgramExecutable.h

    r290129 r292191  
    2626#pragma once
    2727
    28 #include "ExecutableToCodeBlockEdge.h"
    2928#include "GlobalExecutable.h"
    3029
    … …  
    5756    static void destroy(JSCell*);
    5857
    59     ProgramCodeBlock* codeBlock()
     58    ProgramCodeBlock* codeBlock() const
    6059    {
    61         return bitwise_cast<ProgramCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_programCodeBlock.get()));
     60        return bitwise_cast<ProgramCodeBlock*>(Base::codeBlock());
     61    }
     62
     63    UnlinkedProgramCodeBlock* unlinkedCodeBlock() const
     64    {
     65        return bitwise_cast<UnlinkedProgramCodeBlock*>(Base::unlinkedCodeBlock());
    6266    }
    6367
    … …  
    8488    DECLARE_VISIT_CHILDREN;
    8589
    86     WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
    87     WriteBarrier<ExecutableToCodeBlockEdge> m_programCodeBlock;
    8890    std::unique_ptr<TemplateObjectMap> m_templateObjectMap;
    8991};
  • trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp

    r291779 r292191  
    3030#include "EvalCodeBlock.h"
    3131#include "FunctionCodeBlock.h"
     32#include "FunctionExecutableInlines.h"
    3233#include "GlobalExecutable.h"
    3334#include "IsoCellSetInlines.h"
    … …  
    8788    case EvalExecutableType: {
    8889        EvalExecutable* executable = static_cast<EvalExecutable*>(this);
    89         executable->m_evalCodeBlock.clear();
    90         executable->m_unlinkedEvalCodeBlock.clear();
     90        executable->m_codeBlock.clear();
     91        executable->m_unlinkedCodeBlock.clear();
    9192        break;
    9293    }
    9394    case ProgramExecutableType: {
    9495        ProgramExecutable* executable = static_cast<ProgramExecutable*>(this);
    95         executable->m_programCodeBlock.clear();
    96         executable->m_unlinkedProgramCodeBlock.clear();
     96        executable->m_codeBlock.clear();
     97        executable->m_unlinkedCodeBlock.clear();
    9798        break;
    9899    }
    99100    case ModuleProgramExecutableType: {
    100101        ModuleProgramExecutable* executable = static_cast<ModuleProgramExecutable*>(this);
    101         executable->m_moduleProgramCodeBlock.clear();
    102         executable->m_unlinkedModuleProgramCodeBlock.clear();
     102        executable->m_codeBlock.clear();
     103        executable->m_unlinkedCodeBlock.clear();
    103104        executable->m_moduleEnvironmentSymbolTable.clear();
    104105        break;
    … …  
    109110    }
    110111
    111     ASSERT(&Heap::SpaceAndSet::setFor(*subspace()) == &clearableCodeSet);
     112    ASSERT(&Heap::ScriptExecutableSpaceAndSets::clearableCodeSetFor(*subspace()) == &clearableCodeSet);
    112113    clearableCodeSet.remove(this);
    113114}
    … …  
    132133        ASSERT(kind == CodeForCall);
    133134       
    134         oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_programCodeBlock.get());
    135         executable->m_programCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
     135        oldCodeBlock = executable->replaceCodeBlockWith(vm, codeBlock);
    136136        break;
    137137    }
    … …  
    143143        ASSERT(kind == CodeForCall);
    144144
    145         oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_moduleProgramCodeBlock.get());
    146         executable->m_moduleProgramCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
     145        oldCodeBlock = executable->replaceCodeBlockWith(vm, codeBlock);
    147146        break;
    148147    }
    … …  
    154153        ASSERT(kind == CodeForCall);
    155154       
    156         oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_evalCodeBlock.get());
    157         executable->m_evalCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
     155        oldCodeBlock = executable->replaceCodeBlockWith(vm, codeBlock);
    158156        break;
    159157    }
    … …  
    163161        FunctionCodeBlock* codeBlock = static_cast<FunctionCodeBlock*>(genericCodeBlock);
    164162       
    165         switch (kind) {
    166         case CodeForCall:
    167             oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_codeBlockForCall.get());
    168             executable->m_codeBlockForCall.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
    169             break;
    170         case CodeForConstruct:
    171             oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_codeBlockForConstruct.get());
    172             executable->m_codeBlockForConstruct.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
    173             break;
    174         }
     163        oldCodeBlock = executable->replaceCodeBlockWith(vm, kind, codeBlock);
    175164        break;
    176165    }
    … …  
    188177    }
    189178
    190     auto& clearableCodeSet = Heap::SpaceAndSet::setFor(*subspace());
     179    auto& clearableCodeSet = Heap::ScriptExecutableSpaceAndSets::clearableCodeSetFor(*subspace());
    191180    if (hasClearableCode(vm))
    192181        clearableCodeSet.add(this);
    … …  
    226215    if (structure(vm)->classInfo() == FunctionExecutable::info()) {
    227216        auto* executable = static_cast<const FunctionExecutable*>(this);
    228         if (executable->m_codeBlockForCall || executable->m_codeBlockForConstruct)
     217        if (executable->eitherCodeBlock())
    229218            return true;
    230219
    231220    } else if (structure(vm)->classInfo() == EvalExecutable::info()) {
    232221        auto* executable = static_cast<const EvalExecutable*>(this);
    233         if (executable->m_evalCodeBlock || executable->m_unlinkedEvalCodeBlock)
     222        if (executable->m_codeBlock || executable->m_unlinkedCodeBlock)
    234223            return true;
    235224
    236225    } else if (structure(vm)->classInfo() == ProgramExecutable::info()) {
    237226        auto* executable = static_cast<const ProgramExecutable*>(this);
    238         if (executable->m_programCodeBlock || executable->m_unlinkedProgramCodeBlock)
     227        if (executable->m_codeBlock || executable->m_unlinkedCodeBlock)
    239228            return true;
    240229
    241230    } else if (structure(vm)->classInfo() == ModuleProgramExecutable::info()) {
    242231        auto* executable = static_cast<const ModuleProgramExecutable*>(this);
    243         if (executable->m_moduleProgramCodeBlock
    244             || executable->m_unlinkedModuleProgramCodeBlock
     232        if (executable->m_codeBlock
     233            || executable->m_unlinkedCodeBlock
    245234            || executable->m_moduleEnvironmentSymbolTable)
    246235            return true;
    … …  
    262251        EvalExecutable* executable = jsCast<EvalExecutable*>(this);
    263252        RELEASE_ASSERT(kind == CodeForCall);
    264         RELEASE_ASSERT(!executable->m_evalCodeBlock);
     253        RELEASE_ASSERT(!executable->m_codeBlock);
    265254        RELEASE_ASSERT(!function);
    266         RELEASE_AND_RETURN(throwScope, EvalCodeBlock::create(vm, executable, executable->m_unlinkedEvalCodeBlock.get(), scope));
     255        RELEASE_AND_RETURN(throwScope, EvalCodeBlock::create(vm, executable, executable->unlinkedCodeBlock(), scope));
    267256    }
    268257
    … …  
    270259        ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
    271260        RELEASE_ASSERT(kind == CodeForCall);
    272         RELEASE_ASSERT(!executable->m_programCodeBlock);
     261        RELEASE_ASSERT(!executable->m_codeBlock);
    273262        RELEASE_ASSERT(!function);
    274         RELEASE_AND_RETURN(throwScope, ProgramCodeBlock::create(vm, executable, executable->m_unlinkedProgramCodeBlock.get(), scope));
     263        RELEASE_AND_RETURN(throwScope, ProgramCodeBlock::create(vm, executable, executable->unlinkedCodeBlock(), scope));
    275264    }
    276265
    … …  
    278267        ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);
    279268        RELEASE_ASSERT(kind == CodeForCall);
    280         RELEASE_ASSERT(!executable->m_moduleProgramCodeBlock);
     269        RELEASE_ASSERT(!executable->m_codeBlock);
    281270        RELEASE_ASSERT(!function);
    282         RELEASE_AND_RETURN(throwScope, ModuleProgramCodeBlock::create(vm, executable, executable->m_unlinkedModuleProgramCodeBlock.get(), scope));
     271        RELEASE_AND_RETURN(throwScope, ModuleProgramCodeBlock::create(vm, executable, executable->unlinkedCodeBlock(), scope));
    283272    }
    284273
    … …  
    536525}
    537526
     527template<typename Visitor>
     528void ScriptExecutable::runConstraint(const ConcurrentJSLocker& locker, Visitor& visitor, CodeBlock* codeBlock)
     529{
     530    ASSERT(codeBlock);
     531    codeBlock->propagateTransitions(locker, visitor);
     532    codeBlock->determineLiveness(locker, visitor);
     533}
     534
     535template void ScriptExecutable::runConstraint(const ConcurrentJSLocker&, AbstractSlotVisitor&, CodeBlock*);
     536template void ScriptExecutable::runConstraint(const ConcurrentJSLocker&, SlotVisitor&, CodeBlock*);
     537
     538template<typename Visitor>
     539void ScriptExecutable::visitCodeBlockEdge(Visitor& visitor, CodeBlock* codeBlock)
     540{
     541    ASSERT(codeBlock);
     542
     543    ConcurrentJSLocker locker(codeBlock->m_lock);
     544
     545    if (codeBlock->shouldVisitStrongly(locker, visitor))
     546        visitor.appendUnbarriered(codeBlock);
     547
     548    if (JITCode::isOptimizingJIT(codeBlock->jitType())) {
     549        // If we jettison ourselves we'll install our alternative, so make sure that it
     550        // survives GC even if we don't.
     551        visitor.append(codeBlock->m_alternative);
     552    }
     553
     554    // NOTE: There are two sides to this constraint, with different requirements for correctness.
     555    // Because everything is ultimately protected with weak references and jettisoning, it's
     556    // always "OK" to claim that something is dead prematurely and it's "OK" to keep things alive.
     557    // But both choices could lead to bad perf - either recomp cycles or leaks.
     558    //
     559    // Determining CodeBlock liveness: This part is the most consequential. We want to keep the
     560    // output constraint active so long as we think that we may yet prove that the CodeBlock is
     561    // live but we haven't done it yet.
     562    //
     563    // Marking Structures if profitable: It's important that we do a pass of this. Logically, this
     564    // seems like it is a constraint of CodeBlock. But we have always first run this as a result
     565    // of the edge being marked even before we determine the liveness of the CodeBlock. This
     566    // allows a CodeBlock to mark itself by first proving that all of the Structures it weakly
     567    // depends on could be strongly marked. (This part is also called propagateTransitions.)
     568    //
     569    // As a weird caveat, we only fixpoint the constraints so long as the CodeBlock is not live.
     570    // This means that we may overlook structure marking opportunities created by other marking
     571    // that happens after the CodeBlock is marked. This was an accidental policy decision from a
     572    // long time ago, but it is probably OK, since it's only worthwhile to keep fixpointing the
     573    // structure marking if we still have unmarked structures after the first round. We almost
     574    // never will because we will mark-if-profitable based on the owning global object being
     575    // already marked. We mark it just in case that hadn't happened yet. And if the CodeBlock is
     576    // not yet marked because it weakly depends on a structure that we did not yet mark, then we
     577    // will keep fixpointing until the end.
     578    visitor.appendUnbarriered(codeBlock->globalObject());
     579    runConstraint(locker, visitor, codeBlock);
     580}
     581
     582template void ScriptExecutable::visitCodeBlockEdge(AbstractSlotVisitor&, CodeBlock*);
     583template void ScriptExecutable::visitCodeBlockEdge(SlotVisitor&, CodeBlock*);
     584
    538585} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/ScriptExecutable.h

    r283903 r292191  
    140140    static TemplateObjectMap& ensureTemplateObjectMapImpl(std::unique_ptr<TemplateObjectMap>& dest);
    141141
     142    template<typename Visitor>
     143    static void runConstraint(const ConcurrentJSLocker&, Visitor&, CodeBlock*);
     144    template<typename Visitor>
     145    static void visitCodeBlockEdge(Visitor&, CodeBlock*);
     146    void finalizeCodeBlockEdge(VM&, WriteBarrier<CodeBlock>&);
     147
    142148    SourceCode m_source;
    143149    Intrinsic m_intrinsic { NoIntrinsic };
  • trunk/Source/JavaScriptCore/runtime/ScriptExecutableInlines.h

    r292190 r292191  
    11/*
    2  * Copyright (C) 2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
    … …  
    2626#pragma once
    2727
    28 #include "FunctionExecutable.h"
    29 #include "InferredValueInlines.h"
     28#include "ScriptExecutable.h"
    3029
    3130namespace JSC {
    3231
    33 inline void FunctionExecutable::finalizeUnconditionally(VM& vm)
     32inline void ScriptExecutable::finalizeCodeBlockEdge(VM& vm, WriteBarrier<CodeBlock>& codeBlockEdge)
    3433{
    35     m_singleton.finalizeUnconditionally(vm);
    36 }
     34    auto* codeBlock = codeBlockEdge.get();
     35    if (!codeBlock)
     36        return;
    3737
    38 JSString* FunctionExecutable::toString(JSGlobalObject* globalObject)
    39 {
    40     RareData& rareData = ensureRareData();
    41     if (!rareData.m_asString)
    42         return toStringSlow(globalObject);
    43     return rareData.m_asString.get();
     38    if (!vm.heap.isMarked(codeBlock)) {
     39        if (codeBlock->shouldJettisonDueToWeakReference(vm))
     40            codeBlock->jettison(Profiler::JettisonDueToWeakReference);
     41        else
     42            codeBlock->jettison(Profiler::JettisonDueToOldAge);
     43        if (codeBlock == codeBlockEdge.get())
     44            codeBlockEdge.clear();
     45    }
    4446}
    4547
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r290768 r292191  
    4848#include "EvalCodeBlock.h"
    4949#include "Exception.h"
    50 #include "ExecutableToCodeBlockEdge.h"
    5150#include "FTLThunks.h"
    5251#include "FileBasedFuzzerAgent.h"
    … …  
    299298    hashMapBucketMapStructure.set(*this, HashMapBucket<HashMapBucketDataKeyValue>::createStructure(*this, nullptr, jsNull()));
    300299    bigIntStructure.set(*this, JSBigInt::createStructure(*this, nullptr, jsNull()));
    301     executableToCodeBlockEdgeStructure.set(*this, ExecutableToCodeBlockEdge::createStructure(*this, nullptr, jsNull()));
    302300
    303301    // Eagerly initialize constant cells since the concurrent compiler can access them.
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r290869 r292191  
    374374    FOR_EACH_JSC_DYNAMIC_ISO_SUBSPACE(DEFINE_DYNAMIC_ISO_SUBSPACE_ACCESSOR_IMPL)
    375375
    376     ALWAYS_INLINE IsoCellSet& executableToCodeBlockEdgesWithConstraints() { return heap.executableToCodeBlockEdgesWithConstraints; }
    377     ALWAYS_INLINE IsoCellSet& executableToCodeBlockEdgesWithFinalizers() { return heap.executableToCodeBlockEdgesWithFinalizers; }
    378 
    379376    ALWAYS_INLINE GCClient::IsoSubspace& codeBlockSpace() { return clientHeap.codeBlockSpace; }
    380377
    … …  
    442439    Strong<Structure> hashMapBucketMapStructure;
    443440    Strong<Structure> bigIntStructure;
    444     Strong<Structure> executableToCodeBlockEdgeStructure;
    445441
    446442    Strong<JSPropertyNameEnumerator> m_emptyPropertyNameEnumerator;
Note: See TracChangeset for help on using the changeset viewer.