Ignore:
Timestamp:
Feb 4, 2019, 10:32:08 PM (6 years ago)
Author:
[email protected]
Message:

[JSC] Shrink size of VM by lazily allocating IsoSubspaces for non-common types
https://bugs.webkit.org/show_bug.cgi?id=193993

Reviewed by Keith Miller.

Source/JavaScriptCore:

JSC::VM has a lot of IsoSubspaces, and each takes 504B. This unnecessarily makes VM so large.
And some of them are rarely used. We should allocate it lazily.

In this patch, we make some IsoSubspaces std::unique_ptr<IsoSubspace>. And we add ensureXXXSpace
functions which allocate IsoSubspaces lazily. This function is used by subspaceFor<> in each class.
And we also add subspaceForConcurrently<> function, which is called from concurrent JIT tiers. This
returns nullptr if the subspace is not allocated yet. JSCell::subspaceFor now takes second template
parameter which tells the function whether subspaceFor is concurrently done. If the IsoSubspace is
lazily created, we may return nullptr for the concurrent access. We ensure the space's initialization
by using WTF::storeStoreFence when lazily allocating it.

In GC's constraint solving, we may touch these lazily allocated spaces. At that time, we check the
existence of the space before touching this. This is not racy because the main thread is stopped when
the constraint solving is working.

This changes sizeof(VM) from 64736 to 56472.

Another interesting thing is that we removed PreventCollectionScope preventCollectionScope(heap); in
Subspace::initialize. This is really dangerous API since it easily causes dead-lock between the
collector and the mutator if IsoSubspace is dynamically created. We do want to make IsoSubspaces
dynamically-created ones since the requirement of the pre-allocation poses a scalability problem
of IsoSubspace adoption because IsoSubspace is large. Registered Subspace is only touched in the
EndPhase, and the peripheries should be stopped when running EndPhase. Thus, as long as the main thread
can run this IsoSubspace code, the collector is never EndPhase. So this is safe.

  • API/JSCallbackFunction.h:
  • API/ObjCCallbackFunction.h:

(JSC::ObjCCallbackFunction::subspaceFor):

  • API/glib/JSCCallbackFunction.h:
  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::visitChildren):
(JSC::CodeBlock::finalizeUnconditionally):

  • bytecode/CodeBlock.h:
  • bytecode/EvalCodeBlock.h:
  • bytecode/ExecutableToCodeBlockEdge.h:
  • bytecode/FunctionCodeBlock.h:
  • bytecode/ModuleProgramCodeBlock.h:
  • bytecode/ProgramCodeBlock.h:
  • bytecode/UnlinkedFunctionExecutable.cpp:

(JSC::UnlinkedFunctionExecutable::unlinkedCodeBlockFor):

  • bytecode/UnlinkedFunctionExecutable.h:
  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::emitAllocateRawObject):
(JSC::DFG::SpeculativeJIT::compileMakeRope):
(JSC::DFG::SpeculativeJIT::compileNewObject):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileMakeRope):
(JSC::FTL::DFG::LowerDFGToB3::compileMaterializeNewObject):
(JSC::FTL::DFG::LowerDFGToB3::allocateObject):
(JSC::FTL::DFG::LowerDFGToB3::allocateVariableSizedObject):
(JSC::FTL::DFG::LowerDFGToB3::allocateVariableSizedCell):

  • heap/Heap.cpp:

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

  • heap/Subspace.cpp:

(JSC::Subspace::initialize):

  • jit/AssemblyHelpers.h:

(JSC::AssemblyHelpers::emitAllocateJSObjectWithKnownSize):
(JSC::AssemblyHelpers::emitAllocateVariableSizedCell):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_new_object):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_new_object):

  • runtime/DirectArguments.h:
  • runtime/DirectEvalExecutable.h:
  • runtime/ErrorInstance.h:

(JSC::ErrorInstance::subspaceFor):

  • runtime/ExecutableBase.h:
  • runtime/FunctionExecutable.h:
  • runtime/IndirectEvalExecutable.h:
  • runtime/InferredValue.cpp:

(JSC::InferredValue::visitChildren):

  • runtime/InferredValue.h:
  • runtime/InferredValueInlines.h:

(JSC::InferredValue::finalizeUnconditionally):

  • runtime/InternalFunction.h:
  • runtime/JSAsyncFunction.h:
  • runtime/JSAsyncGeneratorFunction.h:
  • runtime/JSBoundFunction.h:
  • runtime/JSCell.h:

(JSC::subspaceFor):
(JSC::subspaceForConcurrently):

  • runtime/JSCellInlines.h:

(JSC::allocatorForNonVirtualConcurrently):

  • runtime/JSCustomGetterSetterFunction.h:
  • runtime/JSDestructibleObject.h:
  • runtime/JSFunction.h:
  • runtime/JSGeneratorFunction.h:
  • runtime/JSImmutableButterfly.h:
  • runtime/JSLexicalEnvironment.h:

(JSC::JSLexicalEnvironment::subspaceFor):

  • runtime/JSNativeStdFunction.h:
  • runtime/JSSegmentedVariableObject.h:
  • runtime/JSString.h:
  • runtime/ModuleProgramExecutable.h:
  • runtime/NativeExecutable.h:
  • runtime/ProgramExecutable.h:
  • runtime/PropertyMapHashTable.h:
  • runtime/ProxyRevoke.h:
  • runtime/ScopedArguments.h:
  • runtime/ScriptExecutable.cpp:

(JSC::ScriptExecutable::clearCode):
(JSC::ScriptExecutable::installCode):

  • runtime/Structure.h:
  • runtime/StructureRareData.h:
  • runtime/SubspaceAccess.h: Copied from Source/JavaScriptCore/runtime/InferredValueInlines.h.
  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:

(JSC::VM::SpaceAndSet::SpaceAndSet):
(JSC::VM::SpaceAndSet::setFor):
(JSC::VM::forEachScriptExecutableSpace):
(JSC::VM::SpaceAndFinalizerSet::SpaceAndFinalizerSet): Deleted.
(JSC::VM::SpaceAndFinalizerSet::finalizerSetFor): Deleted.
(JSC::VM::ScriptExecutableSpaceAndSet::ScriptExecutableSpaceAndSet): Deleted.
(JSC::VM::ScriptExecutableSpaceAndSet::clearableCodeSetFor): Deleted.
(JSC::VM::UnlinkedFunctionExecutableSpaceAndSet::UnlinkedFunctionExecutableSpaceAndSet): Deleted.
(JSC::VM::UnlinkedFunctionExecutableSpaceAndSet::clearableCodeSetFor): Deleted.

  • runtime/WeakMapImpl.h:

(JSC::WeakMapImpl::subspaceFor):

  • wasm/js/JSWebAssemblyCodeBlock.h:
  • wasm/js/JSWebAssemblyMemory.h:
  • wasm/js/WebAssemblyFunction.h:
  • wasm/js/WebAssemblyWrapperFunction.h:

Source/WebCore:

  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateHeader):

  • bridge/runtime_method.h:

Source/WebKit:

  • WebProcess/Plugins/Netscape/JSNPMethod.h:
  • WebProcess/Plugins/Netscape/JSNPObject.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r240888 r240965  
    288288    , eagerlySweptDestructibleObjectSpace("Eagerly Swept JSDestructibleObject", heap, destructibleObjectHeapCellType.get(), fastMallocAllocator.get())
    289289    , segmentedVariableObjectSpace("JSSegmentedVariableObjectSpace", heap, segmentedVariableObjectHeapCellType.get(), fastMallocAllocator.get())
    290     , boundFunctionSpace ISO_SUBSPACE_INIT(heap, cellHeapCellType.get(), JSBoundFunction)
    291     , callbackFunctionSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), JSCallbackFunction)
    292     , customGetterSetterFunctionSpace ISO_SUBSPACE_INIT(heap, cellHeapCellType.get(), JSCustomGetterSetterFunction)
    293290    , executableToCodeBlockEdgeSpace ISO_SUBSPACE_INIT(heap, cellHeapCellType.get(), ExecutableToCodeBlockEdge)
    294291    , functionSpace ISO_SUBSPACE_INIT(heap, cellHeapCellType.get(), JSFunction)
    295     , inferredValueSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), InferredValue)
    296292    , internalFunctionSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), InternalFunction)
    297293    , nativeExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), NativeExecutable)
    298     , nativeStdFunctionSpace ISO_SUBSPACE_INIT(heap, cellHeapCellType.get(), JSNativeStdFunction)
    299 #if JSC_OBJC_API_ENABLED
    300     , objCCallbackFunctionSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), ObjCCallbackFunction)
    301 #endif
    302294    , propertyTableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), PropertyTable)
    303     , proxyRevokeSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), ProxyRevoke)
    304295    , structureRareDataSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), StructureRareData)
    305296    , structureSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), Structure)
    306     , weakSetSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), JSWeakSet)
    307     , weakMapSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), JSWeakMap)
    308     , errorInstanceSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), ErrorInstance)
    309 #if ENABLE(WEBASSEMBLY)
    310     , webAssemblyCodeBlockSpace ISO_SUBSPACE_INIT(heap, webAssemblyCodeBlockHeapCellType.get(), JSWebAssemblyCodeBlock)
    311     , webAssemblyFunctionSpace ISO_SUBSPACE_INIT(heap, cellHeapCellType.get(), WebAssemblyFunction)
    312     , webAssemblyWrapperFunctionSpace ISO_SUBSPACE_INIT(heap, cellHeapCellType.get(), WebAssemblyWrapperFunction)
    313 #endif
    314297    , executableToCodeBlockEdgesWithConstraints(executableToCodeBlockEdgeSpace)
    315298    , executableToCodeBlockEdgesWithFinalizers(executableToCodeBlockEdgeSpace)
    316     , inferredValuesWithFinalizers(inferredValueSpace)
    317299    , codeBlockSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), CodeBlock)
    318     , directEvalExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), DirectEvalExecutable)
    319300    , functionExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), FunctionExecutable)
    320     , indirectEvalExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), IndirectEvalExecutable)
    321     , moduleProgramExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), ModuleProgramExecutable)
    322301    , programExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), ProgramExecutable)
    323302    , unlinkedFunctionExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), UnlinkedFunctionExecutable)
     
    12401219}
    12411220
     1221#define DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(name, heapCellType, type) \
     1222    IsoSubspace* VM::name##Slow() \
     1223    { \
     1224        ASSERT(!m_##name); \
     1225        auto space = std::make_unique<IsoSubspace> ISO_SUBSPACE_INIT(heap, heapCellType, type); \
     1226        WTF::storeStoreFence(); \
     1227        m_##name = WTFMove(space); \
     1228        return m_##name.get(); \
     1229    }
     1230
     1231
     1232DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(boundFunctionSpace, cellHeapCellType.get(), JSBoundFunction)
     1233DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(callbackFunctionSpace, destructibleObjectHeapCellType.get(), JSCallbackFunction)
     1234DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(customGetterSetterFunctionSpace, cellHeapCellType.get(), JSCustomGetterSetterFunction)
     1235DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(errorInstanceSpace, destructibleObjectHeapCellType.get(), ErrorInstance)
     1236DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(nativeStdFunctionSpace, cellHeapCellType.get(), JSNativeStdFunction)
     1237DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(proxyRevokeSpace, destructibleObjectHeapCellType.get(), ProxyRevoke)
     1238DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(weakMapSpace, destructibleObjectHeapCellType.get(), JSWeakMap)
     1239DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(weakSetSpace, destructibleObjectHeapCellType.get(), JSWeakSet)
     1240#if JSC_OBJC_API_ENABLED
     1241DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(objCCallbackFunctionSpace, destructibleObjectHeapCellType.get(), ObjCCallbackFunction)
     1242#endif
     1243#if ENABLE(WEBASSEMBLY)
     1244DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyCodeBlockSpace, webAssemblyCodeBlockHeapCellType.get(), JSWebAssemblyCodeBlock)
     1245DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyFunctionSpace, cellHeapCellType.get(), WebAssemblyFunction)
     1246DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyWrapperFunctionSpace, cellHeapCellType.get(), WebAssemblyWrapperFunction)
     1247#endif
     1248
     1249#undef DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW
     1250
     1251#define DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(name, heapCellType, type) \
     1252    IsoSubspace* VM::name##Slow() \
     1253    { \
     1254        ASSERT(!m_##name); \
     1255        auto space = std::make_unique<SpaceAndSet> ISO_SUBSPACE_INIT(heap, heapCellType, type); \
     1256        WTF::storeStoreFence(); \
     1257        m_##name = WTFMove(space); \
     1258        return &m_##name->space; \
     1259    }
     1260
     1261DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(inferredValueSpace, destructibleCellHeapCellType.get(), InferredValue)
     1262DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(directEvalExecutableSpace, destructibleCellHeapCellType.get(), DirectEvalExecutable)
     1263DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(indirectEvalExecutableSpace, destructibleCellHeapCellType.get(), IndirectEvalExecutable)
     1264DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(moduleProgramExecutableSpace, destructibleCellHeapCellType.get(), ModuleProgramExecutable)
     1265
     1266#undef DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW
     1267
    12421268JSGlobalObject* VM::vmEntryGlobalObject(const CallFrame* callFrame) const
    12431269{
Note: See TracChangeset for help on using the changeset viewer.