Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (292190 => 292191)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2022-04-01 00:33:33 UTC (rev 292191)
@@ -627,7 +627,6 @@
bytecode/DataFormat.h
bytecode/DirectEvalCodeCache.h
bytecode/ExecutableInfo.h
- bytecode/ExecutableToCodeBlockEdge.h
bytecode/ExecutionCounter.h
bytecode/ExitKind.h
bytecode/ExitingInlineKind.h
@@ -1153,6 +1152,7 @@
runtime/ScopedArgumentsTable.h
runtime/Scribble.h
runtime/ScriptExecutable.h
+ runtime/ScriptExecutableInlines.h
runtime/ScriptFetchParameters.h
runtime/ScriptFetcher.h
runtime/ShadowRealmObject.h
Modified: trunk/Source/_javascript_Core/ChangeLog (292190 => 292191)
--- trunk/Source/_javascript_Core/ChangeLog 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/ChangeLog 2022-04-01 00:33:33 UTC (rev 292191)
@@ -1,3 +1,115 @@
+2022-03-31 Yusuke Suzuki <ysuz...@apple.com>
+
+ [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:
+ * _javascript_Core.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/_javascript_Core/runtime/FunctionExecutableInlines.h.
+ (JSC::ScriptExecutable::finalizeCodeBlockEdge):
+ * runtime/VM.cpp:
+ (JSC::VM::VM):
+ * runtime/VM.h:
+ (JSC::VM::executableToCodeBlockEdgesWithConstraints): Deleted.
+ (JSC::VM::executableToCodeBlockEdgesWithFinalizers): Deleted.
+
2022-03-31 Patrick Angle <pan...@apple.com>
Web Inspector: Support Container Queries in the Styles sidebar
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (292190 => 292191)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2022-04-01 00:33:33 UTC (rev 292191)
@@ -370,7 +370,6 @@
0F5E0FD8207C72730097F0DE /* DFGAbstractInterpreterClobberState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5E0FD6207C72710097F0DE /* DFGAbstractInterpreterClobberState.h */; };
0F5E0FE72086AD480097F0DE /* IsoSubspacePerVM.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5E0FE52086AD460097F0DE /* IsoSubspacePerVM.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F5EF91F16878F7D003E5C25 /* JITThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5EF91C16878F78003E5C25 /* JITThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F60FE901FFC37020003320A /* ExecutableToCodeBlockEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F60FE8E1FFC36FD0003320A /* ExecutableToCodeBlockEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F61832A1C45BF070072450B /* AirCCallingConvention.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183211C45BF070072450B /* AirCCallingConvention.h */; };
0F61832D1C45BF070072450B /* AirEmitShuffle.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183241C45BF070072450B /* AirEmitShuffle.h */; };
0F61832F1C45BF070072450B /* AirLowerAfterRegAlloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183261C45BF070072450B /* AirLowerAfterRegAlloc.h */; };
@@ -1989,6 +1988,7 @@
E386FD7E26E867B800E4C28B /* TemporalPlainTime.h in Headers */ = {isa = PBXBuildFile; fileRef = E386FD7826E867B800E4C28B /* TemporalPlainTime.h */; };
E386FD7F26E867B800E4C28B /* TemporalPlainTimePrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = E386FD7926E867B800E4C28B /* TemporalPlainTimePrototype.h */; };
E3893A1D2203A7C600E79A74 /* AsyncFromSyncIteratorPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E3893A1C2203A7C600E79A74 /* AsyncFromSyncIteratorPrototype.lut.h */; };
+ E38DB2E727F588F80027BD3F /* ScriptExecutableInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E38DB2E627F588F70027BD3F /* ScriptExecutableInlines.h */; };
E38E8790254B978400F6F9E4 /* JSDateMath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9788FC221471AD0C0068CE2D /* JSDateMath.cpp */; };
E39006212208BFC4001019CF /* SubspaceAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = E39006202208BFC3001019CF /* SubspaceAccess.h */; settings = {ATTRIBUTES = (Private, ); }; };
E392E6F824D25FA600B20767 /* B3BottomTupleValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E392E6F624D25FA600B20767 /* B3BottomTupleValue.cpp */; };
@@ -2897,8 +2897,6 @@
0F5E0FE62086AD470097F0DE /* IsoSubspacePerVM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IsoSubspacePerVM.cpp; sourceTree = "<group>"; };
0F5EF91B16878F78003E5C25 /* JITThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITThunks.cpp; sourceTree = "<group>"; };
0F5EF91C16878F78003E5C25 /* JITThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITThunks.h; sourceTree = "<group>"; };
- 0F60FE8D1FFC36FC0003320A /* ExecutableToCodeBlockEdge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableToCodeBlockEdge.cpp; sourceTree = "<group>"; };
- 0F60FE8E1FFC36FD0003320A /* ExecutableToCodeBlockEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutableToCodeBlockEdge.h; sourceTree = "<group>"; };
0F6183201C45BF070072450B /* AirCCallingConvention.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirCCallingConvention.cpp; path = b3/air/AirCCallingConvention.cpp; sourceTree = "<group>"; };
0F6183211C45BF070072450B /* AirCCallingConvention.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirCCallingConvention.h; path = b3/air/AirCCallingConvention.h; sourceTree = "<group>"; };
0F6183221C45BF070072450B /* AirCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirCustom.cpp; path = b3/air/AirCustom.cpp; sourceTree = "<group>"; };
@@ -5479,6 +5477,7 @@
E38D060B1F8E814100649CF2 /* JSScriptFetchParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSScriptFetchParameters.h; sourceTree = "<group>"; };
E38D060C1F8E814100649CF2 /* ScriptFetchParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptFetchParameters.h; sourceTree = "<group>"; };
E38D060D1F8E814100649CF2 /* JSScriptFetchParameters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSScriptFetchParameters.cpp; sourceTree = "<group>"; };
+ E38DB2E627F588F70027BD3F /* ScriptExecutableInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptExecutableInlines.h; sourceTree = "<group>"; };
E39006202208BFC3001019CF /* SubspaceAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubspaceAccess.h; sourceTree = "<group>"; };
E3915C062309682900CB2561 /* WasmContext.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WasmContext.cpp; sourceTree = "<group>"; };
E392E6F624D25FA600B20767 /* B3BottomTupleValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3BottomTupleValue.cpp; path = b3/B3BottomTupleValue.cpp; sourceTree = "<group>"; };
@@ -8224,6 +8223,7 @@
33111B8A2397256500AA34CE /* Scribble.h */,
147341E01DC2CE9600AA29BA /* ScriptExecutable.cpp */,
147341CD1DC02D7900AA29BA /* ScriptExecutable.h */,
+ E38DB2E627F588F70027BD3F /* ScriptExecutableInlines.h */,
8852151A9C3842389B3215B7 /* ScriptFetcher.h */,
E38D060C1F8E814100649CF2 /* ScriptFetchParameters.h */,
A7299DA317D12858005F5FF9 /* SetConstructor.cpp */,
@@ -8977,8 +8977,6 @@
14AD91121DCA97FD0014F9FE /* EvalCodeBlock.cpp */,
14AD91061DCA92940014F9FE /* EvalCodeBlock.h */,
14142E521B796EDD00F4BF4B /* ExecutableInfo.h */,
- 0F60FE8D1FFC36FC0003320A /* ExecutableToCodeBlockEdge.cpp */,
- 0F60FE8E1FFC36FD0003320A /* ExecutableToCodeBlockEdge.h */,
0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */,
0F56A1D115000F31002992B1 /* ExecutionCounter.h */,
0F44A7A920BF685E0022B171 /* ExitFlag.cpp */,
@@ -10273,7 +10271,6 @@
E35A0B9D220AD87A00AC4474 /* ExecutableBaseInlines.h in Headers */,
14142E531B796EDD00F4BF4B /* ExecutableInfo.h in Headers */,
0F5193F7266C432D00483A2C /* ExecutableMemoryHandle.h in Headers */,
- 0F60FE901FFC37020003320A /* ExecutableToCodeBlockEdge.h in Headers */,
0F56A1D315000F35002992B1 /* ExecutionCounter.h in Headers */,
0F44A7B020BF68620022B171 /* ExitFlag.h in Headers */,
0F44A7B120BF68C90022B171 /* ExitingInlineKind.h in Headers */,
@@ -11044,6 +11041,7 @@
A5FD0070189B00AA00633231 /* ScriptCallStack.h in Headers */,
A5FD007E189B0B4C00633231 /* ScriptCallStackFactory.h in Headers */,
147341CE1DC02D7900AA29BA /* ScriptExecutable.h in Headers */,
+ E38DB2E727F588F80027BD3F /* ScriptExecutableInlines.h in Headers */,
CEAE7D7B889B477BA93ABA6C /* ScriptFetcher.h in Headers */,
E3201C1E1F8E824C0076A032 /* ScriptFetchParameters.h in Headers */,
A55D93A6185012A800400DED /* ScriptFunctionCall.h in Headers */,
Modified: trunk/Source/_javascript_Core/Sources.txt (292190 => 292191)
--- trunk/Source/_javascript_Core/Sources.txt 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/Sources.txt 2022-04-01 00:33:33 UTC (rev 292191)
@@ -229,7 +229,6 @@
bytecode/DeleteByVariant.cpp
bytecode/DirectEvalCodeCache.cpp
bytecode/EvalCodeBlock.cpp
-bytecode/ExecutableToCodeBlockEdge.cpp
bytecode/ExecutionCounter.cpp
bytecode/ExitFlag.cpp
bytecode/ExitKind.cpp
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -311,7 +311,6 @@
void CodeBlock::finishCreation(VM& vm, CopyParsedBlockTag, CodeBlock& other)
{
Base::finishCreation(vm);
- finishCreationCommon(vm);
optimizeAfterWarmUp();
@@ -367,7 +366,6 @@
JSScope* scope)
{
Base::finishCreation(vm);
- finishCreationCommon(vm);
ASSERT(vm.heap.isDeferred());
@@ -766,11 +764,6 @@
return true;
}
-void CodeBlock::finishCreationCommon(VM& vm)
-{
- m_ownerEdge.set(vm, this, ExecutableToCodeBlockEdge::create(vm, this));
-}
-
#if ENABLE(JIT)
void CodeBlock::setupWithUnlinkedBaselineCode(Ref<BaselineJITCode> jitCode)
{
@@ -1051,7 +1044,6 @@
CodeBlock* thisObject = jsCast<CodeBlock*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(cell, visitor);
- visitor.append(thisObject->m_ownerEdge);
thisObject->visitChildren(visitor);
}
@@ -1079,7 +1071,7 @@
stronglyVisitStrongReferences(locker, visitor);
stronglyVisitWeakReferences(locker, visitor);
- Heap::SpaceAndSet::setFor(*subspace()).add(this);
+ Heap::CodeBlockSpaceAndSet::setFor(*subspace()).add(this);
}
template<typename Visitor>
@@ -1667,7 +1659,7 @@
};
updateActivity();
- Heap::SpaceAndSet::setFor(*subspace()).remove(this);
+ Heap::CodeBlockSpaceAndSet::setFor(*subspace()).remove(this);
// In CodeBlock::shouldVisitStrongly() we may have decided to skip visiting this
// codeBlock. By the time we get here, we're done with the verifier GC. So, let's
@@ -1834,7 +1826,7 @@
UNUSED_PARAM(locker);
visitor.append(m_globalObject);
- visitor.append(m_ownerExecutable); // This is extra important since it causes the ExecutableToCodeBlockEdge to be marked.
+ visitor.append(m_ownerExecutable); // This is extra important since it causes the Executable -> CodeBlock edge activated.
visitor.append(m_unlinkedCode);
if (m_rareData)
m_rareData->m_directEvalCodeCache.visitAggregate(visitor);
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (292190 => 292191)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2022-04-01 00:33:33 UTC (rev 292191)
@@ -87,12 +87,12 @@
class BinaryArithProfile;
class BytecodeLivenessAnalysis;
class CodeBlockSet;
-class ExecutableToCodeBlockEdge;
class JSModuleEnvironment;
class LLIntOffsetsExtractor;
class LLIntPrototypeLoadAdaptiveStructureWatchpoint;
class MetadataTable;
class RegisterAtOffsetList;
+class ScriptExecutable;
class StructureStubInfo;
class BaselineJITCode;
class BaselineJITData;
@@ -134,8 +134,6 @@
void finishCreation(VM&, CopyParsedBlockTag, CodeBlock& other);
bool finishCreation(VM&, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*);
-
- void finishCreationCommon(VM&);
WriteBarrier<JSGlobalObject> m_globalObject;
@@ -369,8 +367,6 @@
ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); }
- ExecutableToCodeBlockEdge* ownerEdge() const { return m_ownerEdge.get(); }
-
VM& vm() const { return *m_vm; }
VirtualRegister thisRegister() const { return m_unlinkedCode->thisRegister(); }
@@ -849,7 +845,8 @@
private:
friend class CodeBlockSet;
- friend class ExecutableToCodeBlockEdge;
+ friend class FunctionExecutable;
+ friend class ScriptExecutable;
template<typename Visitor> ALWAYS_INLINE void visitChildren(Visitor&);
@@ -923,7 +920,6 @@
WriteBarrier<UnlinkedCodeBlock> m_unlinkedCode;
WriteBarrier<ScriptExecutable> m_ownerExecutable;
- WriteBarrier<ExecutableToCodeBlockEdge> m_ownerEdge;
// m_vm must be a pointer (instead of a reference) because the JSCLLIntOffsetsExtractor
// cannot handle it being a reference.
VM* m_vm;
@@ -975,7 +971,7 @@
#endif
};
#if !ASSERT_ENABLED && COMPILER(GCC_COMPATIBLE)
-static_assert(sizeof(CodeBlock) <= 256, "Keep it small for memory saving");
+static_assert(sizeof(CodeBlock) <= 240, "Keep it small for memory saving");
#endif
template <typename ExecutableType>
Deleted: trunk/Source/_javascript_Core/bytecode/ExecutableToCodeBlockEdge.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/bytecode/ExecutableToCodeBlockEdge.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/bytecode/ExecutableToCodeBlockEdge.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2018-2021 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "ExecutableToCodeBlockEdge.h"
-
-#include "CodeBlock.h"
-#include "IsoCellSetInlines.h"
-#include "JSObjectInlines.h"
-#include "StructureInlines.h"
-
-namespace JSC {
-
-const ClassInfo ExecutableToCodeBlockEdge::s_info = { "ExecutableToCodeBlockEdge"_s, nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(ExecutableToCodeBlockEdge) };
-
-Structure* ExecutableToCodeBlockEdge::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
-{
- return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
-}
-
-ExecutableToCodeBlockEdge* ExecutableToCodeBlockEdge::create(VM& vm, CodeBlock* codeBlock)
-{
- ExecutableToCodeBlockEdge* result = new (NotNull, allocateCell<ExecutableToCodeBlockEdge>(vm)) ExecutableToCodeBlockEdge(vm, codeBlock);
- result->finishCreation(vm);
- return result;
-}
-
-void ExecutableToCodeBlockEdge::finishCreation(VM& vm)
-{
- Base::finishCreation(vm);
- ASSERT(!isActive());
-}
-
-template<typename Visitor>
-void ExecutableToCodeBlockEdge::visitChildrenImpl(JSCell* cell, Visitor& visitor)
-{
- VM& vm = visitor.vm();
- ExecutableToCodeBlockEdge* edge = jsCast<ExecutableToCodeBlockEdge*>(cell);
- ASSERT_GC_OBJECT_INHERITS(cell, info());
- Base::visitChildren(cell, visitor);
-
- CodeBlock* codeBlock = edge->m_codeBlock.get();
-
- // It's possible for someone to hold a pointer to the edge after the edge has cleared its weak
- // reference to the codeBlock. In a conservative GC like ours, that could happen at random for
- // no good reason and it's Totally OK (TM). See finalizeUnconditionally() for where we clear
- // m_codeBlock.
- if (!codeBlock)
- return;
-
- if (!edge->isActive()) {
- visitor.appendUnbarriered(codeBlock);
- return;
- }
-
- ConcurrentJSLocker locker(codeBlock->m_lock);
-
- if (codeBlock->shouldVisitStrongly(locker, visitor))
- visitor.appendUnbarriered(codeBlock);
-
- if (!visitor.isMarked(codeBlock))
- vm.executableToCodeBlockEdgesWithFinalizers().add(edge);
-
- if (JITCode::isOptimizingJIT(codeBlock->jitType())) {
- // If we jettison ourselves we'll install our alternative, so make sure that it
- // survives GC even if we don't.
- visitor.append(codeBlock->m_alternative);
- }
-
- // NOTE: There are two sides to this constraint, with different requirements for correctness.
- // Because everything is ultimately protected with weak references and jettisoning, it's
- // always "OK" to claim that something is dead prematurely and it's "OK" to keep things alive.
- // But both choices could lead to bad perf - either recomp cycles or leaks.
- //
- // Determining CodeBlock liveness: This part is the most consequential. We want to keep the
- // output constraint active so long as we think that we may yet prove that the CodeBlock is
- // live but we haven't done it yet.
- //
- // Marking Structures if profitable: It's important that we do a pass of this. Logically, this
- // seems like it is a constraint of CodeBlock. But we have always first run this as a result
- // of the edge being marked even before we determine the liveness of the CodeBlock. This
- // allows a CodeBlock to mark itself by first proving that all of the Structures it weakly
- // depends on could be strongly marked. (This part is also called propagateTransitions.)
- //
- // As a weird caveat, we only fixpoint the constraints so long as the CodeBlock is not live.
- // This means that we may overlook structure marking opportunities created by other marking
- // that happens after the CodeBlock is marked. This was an accidental policy decision from a
- // long time ago, but it is probably OK, since it's only worthwhile to keep fixpointing the
- // structure marking if we still have unmarked structures after the first round. We almost
- // never will because we will mark-if-profitable based on the owning global object being
- // already marked. We mark it just in case that hadn't happened yet. And if the CodeBlock is
- // not yet marked because it weakly depends on a structure that we did not yet mark, then we
- // will keep fixpointing until the end.
- visitor.appendUnbarriered(codeBlock->globalObject());
- vm.executableToCodeBlockEdgesWithConstraints().add(edge);
- edge->runConstraint(locker, vm, visitor);
-}
-
-DEFINE_VISIT_CHILDREN(ExecutableToCodeBlockEdge);
-
-template<typename Visitor>
-void ExecutableToCodeBlockEdge::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor)
-{
- VM& vm = visitor.vm();
- ExecutableToCodeBlockEdge* edge = jsCast<ExecutableToCodeBlockEdge*>(cell);
-
- edge->runConstraint(NoLockingNecessary, vm, visitor);
-}
-
-DEFINE_VISIT_OUTPUT_CONSTRAINTS(ExecutableToCodeBlockEdge);
-
-void ExecutableToCodeBlockEdge::finalizeUnconditionally(VM& vm)
-{
- CodeBlock* codeBlock = m_codeBlock.get();
-
- if (!vm.heap.isMarked(codeBlock)) {
- if (codeBlock->shouldJettisonDueToWeakReference(vm))
- codeBlock->jettison(Profiler::JettisonDueToWeakReference);
- else
- codeBlock->jettison(Profiler::JettisonDueToOldAge);
- m_codeBlock.clear();
- }
-
- vm.executableToCodeBlockEdgesWithFinalizers().remove(this);
- vm.executableToCodeBlockEdgesWithConstraints().remove(this);
-}
-
-inline void ExecutableToCodeBlockEdge::activate()
-{
- setPerCellBit(true);
-}
-
-inline void ExecutableToCodeBlockEdge::deactivate()
-{
- setPerCellBit(false);
-}
-
-inline bool ExecutableToCodeBlockEdge::isActive() const
-{
- return perCellBit();
-}
-
-CodeBlock* ExecutableToCodeBlockEdge::deactivateAndUnwrap(ExecutableToCodeBlockEdge* edge)
-{
- if (!edge)
- return nullptr;
- edge->deactivate();
- return edge->codeBlock();
-}
-
-ExecutableToCodeBlockEdge* ExecutableToCodeBlockEdge::wrap(CodeBlock* codeBlock)
-{
- if (!codeBlock)
- return nullptr;
- return codeBlock->ownerEdge();
-}
-
-ExecutableToCodeBlockEdge* ExecutableToCodeBlockEdge::wrapAndActivate(CodeBlock* codeBlock)
-{
- if (!codeBlock)
- return nullptr;
- ExecutableToCodeBlockEdge* result = codeBlock->ownerEdge();
- result->activate();
- return result;
-}
-
-ExecutableToCodeBlockEdge::ExecutableToCodeBlockEdge(VM& vm, CodeBlock* codeBlock)
- : Base(vm, vm.executableToCodeBlockEdgeStructure.get())
- , m_codeBlock(vm, this, codeBlock)
-{
-}
-
-template<typename Visitor>
-void ExecutableToCodeBlockEdge::runConstraint(const ConcurrentJSLocker& locker, VM& vm, Visitor& visitor)
-{
- CodeBlock* codeBlock = m_codeBlock.get();
-
- codeBlock->propagateTransitions(locker, visitor);
- codeBlock->determineLiveness(locker, visitor);
-
- if (visitor.isMarked(codeBlock))
- vm.executableToCodeBlockEdgesWithConstraints().remove(this);
-}
-
-template void ExecutableToCodeBlockEdge::runConstraint(const ConcurrentJSLocker&, VM&, AbstractSlotVisitor&);
-template void ExecutableToCodeBlockEdge::runConstraint(const ConcurrentJSLocker&, VM&, SlotVisitor&);
-
-
-} // namespace JSC
-
Deleted: trunk/Source/_javascript_Core/bytecode/ExecutableToCodeBlockEdge.h (292190 => 292191)
--- trunk/Source/_javascript_Core/bytecode/ExecutableToCodeBlockEdge.h 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/bytecode/ExecutableToCodeBlockEdge.h 2022-04-01 00:33:33 UTC (rev 292191)
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2018-2022 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include "ConcurrentJSLock.h"
-#include "IsoSubspace.h"
-#include "JSCast.h"
-#include "VM.h"
-
-namespace JSC {
-
-class CodeBlock;
-class LLIntOffsetsExtractor;
-
-class ExecutableToCodeBlockEdge final : public JSCell {
-public:
- typedef JSCell Base;
- static constexpr unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
-
- template<typename CellType, SubspaceAccess>
- static GCClient::IsoSubspace* subspaceFor(VM& vm)
- {
- return &vm.executableToCodeBlockEdgeSpace();
- }
-
- static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
-
- static ExecutableToCodeBlockEdge* create(VM&, CodeBlock*);
-
- DECLARE_INFO;
-
- CodeBlock* codeBlock() const { return m_codeBlock.get(); }
-
- DECLARE_VISIT_CHILDREN;
- DECLARE_VISIT_OUTPUT_CONSTRAINTS;
- void finalizeUnconditionally(VM&);
-
- static CodeBlock* unwrap(ExecutableToCodeBlockEdge* edge)
- {
- if (!edge)
- return nullptr;
- return edge->codeBlock();
- }
-
- static CodeBlock* deactivateAndUnwrap(ExecutableToCodeBlockEdge* edge);
-
- static ExecutableToCodeBlockEdge* wrap(CodeBlock* codeBlock);
-
- static ExecutableToCodeBlockEdge* wrapAndActivate(CodeBlock* codeBlock);
-
- static ptrdiff_t offsetOfCodeBlock() { return OBJECT_OFFSETOF(ExecutableToCodeBlockEdge, m_codeBlock); }
-
-private:
- friend class LLIntOffsetsExtractor;
-
- ExecutableToCodeBlockEdge(VM&, CodeBlock*);
-
- void finishCreation(VM&);
-
- void activate();
- void deactivate();
- bool isActive() const;
-
- template<typename Visitor> void runConstraint(const ConcurrentJSLocker&, VM&, Visitor&);
-
- WriteBarrier<CodeBlock> m_codeBlock;
-};
-
-} // namespace JSC
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -368,8 +368,6 @@
, destructibleObjectSpace("JSDestructibleObject", *this, destructibleObjectHeapCellType, fastMallocAllocator.get()) // Hash:0x4f5ed7a9
FOR_EACH_JSC_COMMON_ISO_SUBSPACE(INIT_SERVER_ISO_SUBSPACE)
FOR_EACH_JSC_STRUCTURE_ISO_SUBSPACE(INIT_SERVER_STRUCTURE_ISO_SUBSPACE)
- , executableToCodeBlockEdgesWithConstraints(executableToCodeBlockEdgeSpace)
- , executableToCodeBlockEdgesWithFinalizers(executableToCodeBlockEdgeSpace)
, codeBlockSpaceAndSet ISO_SUBSPACE_INIT(*this, destructibleCellHeapCellType, CodeBlock) // Hash:0x77e66ec9
, functionExecutableSpaceAndSet ISO_SUBSPACE_INIT(*this, destructibleCellHeapCellType, FunctionExecutable) // Hash:0x5d158f3
, programExecutableSpaceAndSet ISO_SUBSPACE_INIT(*this, destructibleCellHeapCellType, ProgramExecutable) // Hash:0x527c77e7
@@ -674,9 +672,22 @@
{
VM& vm = this->vm();
vm.builtinExecutables()->finalizeUnconditionally();
- finalizeMarkedUnconditionalFinalizers<FunctionExecutable>(functionExecutableSpaceAndSet.space);
+
+ {
+ // We run this before CodeBlock's unconditional finalizer since CodeBlock looks at the owner executable's installed CodeBlock in its finalizeUnconditionally.
+
+ // FunctionExecutable requires all live instances to run finalizers. Thus, we do not use finalizer set.
+ finalizeMarkedUnconditionalFinalizers<FunctionExecutable>(functionExecutableSpaceAndSet.space);
+
+ finalizeMarkedUnconditionalFinalizers<ProgramExecutable>(programExecutableSpaceAndSet.finalizerSet);
+ if (m_evalExecutableSpace)
+ finalizeMarkedUnconditionalFinalizers<EvalExecutable>(m_evalExecutableSpace->finalizerSet);
+ if (m_moduleProgramExecutableSpace)
+ finalizeMarkedUnconditionalFinalizers<ModuleProgramExecutable>(m_moduleProgramExecutableSpace->finalizerSet);
+ }
+
finalizeMarkedUnconditionalFinalizers<SymbolTable>(symbolTableSpace);
- finalizeMarkedUnconditionalFinalizers<ExecutableToCodeBlockEdge>(executableToCodeBlockEdgesWithFinalizers); // We run this before CodeBlock's unconditional finalizer since CodeBlock looks at the owner executable's installed CodeBlock in its finalizeUnconditionally.
+
forEachCodeBlockSpace(
[&] (auto& space) {
this->finalizeMarkedUnconditionalFinalizers<CodeBlock>(space.set);
@@ -1003,7 +1014,7 @@
forEachScriptExecutableSpace(
[&] (auto& spaceAndSet) {
HeapIterationScope heapIterationScope(*this);
- auto& set = spaceAndSet.set;
+ auto& set = spaceAndSet.clearableCodeSet;
set.forEachLiveCell(
[&] (HeapCell* cell, HeapCell::Kind) {
ScriptExecutable* executable = static_cast<ScriptExecutable*>(cell);
@@ -2917,7 +2928,12 @@
{
SetRootMarkReasonScope rootScope(visitor, RootMarkReason::ExecutableToCodeBlockEdges);
- add(heap->executableToCodeBlockEdgesWithConstraints);
+ add(heap->functionExecutableSpaceAndSet.outputConstraintsSet);
+ add(heap->programExecutableSpaceAndSet.outputConstraintsSet);
+ if (heap->m_evalExecutableSpace)
+ add(heap->m_evalExecutableSpace->outputConstraintsSet);
+ if (heap->m_moduleProgramExecutableSpace)
+ add(heap->m_moduleProgramExecutableSpace->outputConstraintsSet);
}
if (heap->m_weakMapSpace) {
SetRootMarkReasonScope rootScope(visitor, RootMarkReason::WeakMapSpace);
@@ -3169,18 +3185,18 @@
#undef DEFINE_DYNAMIC_ISO_SUBSPACE_MEMBER_SLOW
-#define DEFINE_DYNAMIC_SPACE_AND_SET_MEMBER_SLOW(name, heapCellType, type) \
+#define DEFINE_DYNAMIC_SPACE_AND_SET_MEMBER_SLOW(name, heapCellType, type, spaceType) \
IsoSubspace* Heap::name##Slow() \
{ \
ASSERT(!m_##name); \
- auto space = makeUnique<SpaceAndSet> ISO_SUBSPACE_INIT(*this, heapCellType, type); \
+ auto space = makeUnique<spaceType> ISO_SUBSPACE_INIT(*this, heapCellType, type); \
WTF::storeStoreFence(); \
m_##name = WTFMove(space); \
return &m_##name->space; \
}
-DEFINE_DYNAMIC_SPACE_AND_SET_MEMBER_SLOW(evalExecutableSpace, destructibleCellHeapCellType, EvalExecutable) // Hash:0x958e3e9d
-DEFINE_DYNAMIC_SPACE_AND_SET_MEMBER_SLOW(moduleProgramExecutableSpace, destructibleCellHeapCellType, ModuleProgramExecutable) // Hash:0x6506fa3c
+DEFINE_DYNAMIC_SPACE_AND_SET_MEMBER_SLOW(evalExecutableSpace, destructibleCellHeapCellType, EvalExecutable, Heap::ScriptExecutableSpaceAndSets) // Hash:0x958e3e9d
+DEFINE_DYNAMIC_SPACE_AND_SET_MEMBER_SLOW(moduleProgramExecutableSpace, destructibleCellHeapCellType, ModuleProgramExecutable, Heap::ScriptExecutableSpaceAndSets) // Hash:0x6506fa3c
#undef DEFINE_DYNAMIC_SPACE_AND_SET_MEMBER_SLOW
Modified: trunk/Source/_javascript_Core/heap/Heap.h (292190 => 292191)
--- trunk/Source/_javascript_Core/heap/Heap.h 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/heap/Heap.h 2022-04-01 00:33:33 UTC (rev 292191)
@@ -120,7 +120,6 @@
v(dateInstanceSpace, dateInstanceHeapCellType, DateInstance) \
v(domAttributeGetterSetterSpace, cellHeapCellType, DOMAttributeGetterSetter) \
v(exceptionSpace, destructibleCellHeapCellType, Exception) \
- v(executableToCodeBlockEdgeSpace, cellHeapCellType, ExecutableToCodeBlockEdge) \
v(functionSpace, cellHeapCellType, JSFunction) \
v(getterSetterSpace, cellHeapCellType, GetterSetter) \
v(globalLexicalEnvironmentSpace, globalLexicalEnvironmentHeapCellType, JSGlobalLexicalEnvironment) \
@@ -1029,10 +1028,7 @@
FOR_EACH_JSC_DYNAMIC_ISO_SUBSPACE(DEFINE_DYNAMIC_ISO_SUBSPACE_MEMBER)
#undef DEFINE_DYNAMIC_ISO_SUBSPACE_MEMBER
- IsoCellSet executableToCodeBlockEdgesWithConstraints;
- IsoCellSet executableToCodeBlockEdgesWithFinalizers;
-
-#define DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(name) \
+#define DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(name, type) \
template<SubspaceAccess mode> \
IsoSubspace* name() \
{ \
@@ -1043,7 +1039,7 @@
return name##Slow(); \
} \
IsoSubspace* name##Slow(); \
- std::unique_ptr<SpaceAndSet> m_##name;
+ std::unique_ptr<type> m_##name;
struct SpaceAndSet {
WTF_MAKE_STRUCT_FAST_ALLOCATED;
@@ -1067,7 +1063,8 @@
}
};
- SpaceAndSet codeBlockSpaceAndSet;
+ using CodeBlockSpaceAndSet = SpaceAndSet;
+ CodeBlockSpaceAndSet codeBlockSpaceAndSet;
template<typename Func>
void forEachCodeBlockSpace(const Func& func)
@@ -1075,11 +1072,40 @@
func(codeBlockSpaceAndSet);
}
- DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(evalExecutableSpace)
- DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(moduleProgramExecutableSpace)
- SpaceAndSet functionExecutableSpaceAndSet;
- SpaceAndSet programExecutableSpaceAndSet;
+ struct ScriptExecutableSpaceAndSets {
+ WTF_MAKE_STRUCT_FAST_ALLOCATED;
+ IsoSubspace space;
+ IsoCellSet clearableCodeSet;
+ IsoCellSet outputConstraintsSet;
+ IsoCellSet finalizerSet;
+
+ template<typename... Arguments>
+ ScriptExecutableSpaceAndSets(Arguments&&... arguments)
+ : space(std::forward<Arguments>(arguments)...)
+ , clearableCodeSet(space)
+ , outputConstraintsSet(space)
+ , finalizerSet(space)
+ {
+ }
+
+ static ScriptExecutableSpaceAndSets& setAndSpaceFor(Subspace& space)
+ {
+ return *bitwise_cast<ScriptExecutableSpaceAndSets*>(
+ bitwise_cast<char*>(&space) -
+ OBJECT_OFFSETOF(ScriptExecutableSpaceAndSets, space));
+ }
+
+ static IsoCellSet& clearableCodeSetFor(Subspace& space) { return setAndSpaceFor(space).clearableCodeSet; }
+ static IsoCellSet& outputConstraintsSetFor(Subspace& space) { return setAndSpaceFor(space).outputConstraintsSet; }
+ static IsoCellSet& finalizerSetFor(Subspace& space) { return setAndSpaceFor(space).finalizerSet; }
+ };
+
+ DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(evalExecutableSpace, ScriptExecutableSpaceAndSets)
+ DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(moduleProgramExecutableSpace, ScriptExecutableSpaceAndSets)
+ ScriptExecutableSpaceAndSets functionExecutableSpaceAndSet;
+ ScriptExecutableSpaceAndSets programExecutableSpaceAndSet;
+
template<typename Func>
void forEachScriptExecutableSpace(const Func& func)
{
@@ -1091,7 +1117,8 @@
func(programExecutableSpaceAndSet);
}
- SpaceAndSet unlinkedFunctionExecutableSpaceAndSet;
+ using UnlinkedFunctionExecutableSpaceAndSet = SpaceAndSet;
+ UnlinkedFunctionExecutableSpaceAndSet unlinkedFunctionExecutableSpaceAndSet;
Vector<IsoSubspacePerVM*> perVMIsoSubspaces;
#undef DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER
Modified: trunk/Source/_javascript_Core/heap/IsoCellSet.h (292190 => 292191)
--- trunk/Source/_javascript_Core/heap/IsoCellSet.h 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/heap/IsoCellSet.h 2022-04-01 00:33:33 UTC (rev 292191)
@@ -29,6 +29,8 @@
#include <wtf/Bitmap.h>
#include <wtf/ConcurrentVector.h>
#include <wtf/FastBitVector.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Nonmovable.h>
#include <wtf/SentinelLinkedList.h>
#include <wtf/SharedTask.h>
@@ -40,7 +42,9 @@
// Create a set of cells that are in an IsoSubspace. This allows concurrent O(1) set insertion and
// removal. Each such set should be thought of as a 0.8% increase in object size for objects in that
// IsoSubspace (it's like adding 1 bit every 16 bytes, or 1 bit every 128 bits).
-class IsoCellSet : public PackedRawSentinelNode<IsoCellSet> {
+class IsoCellSet final : public PackedRawSentinelNode<IsoCellSet> {
+ WTF_MAKE_NONCOPYABLE(IsoCellSet);
+ WTF_MAKE_NONMOVABLE(IsoCellSet);
public:
IsoCellSet(IsoSubspace& subspace);
~IsoCellSet();
Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/jit/JIT.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -215,8 +215,6 @@
loadPtr(Address(result, FunctionExecutable::offsetOfCodeBlockForConstruct()), result);
else
loadPtr(Address(result, FunctionExecutable::offsetOfCodeBlockForCall()), result);
-
- loadPtr(Address(result, ExecutableToCodeBlockEdge::offsetOfCodeBlock()), result);
emitPutToCallFrameHeader(result, CallFrameSlot::codeBlock);
#if ASSERT_ENABLED
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (292190 => 292191)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2022-04-01 00:33:33 UTC (rev 292191)
@@ -1493,7 +1493,6 @@
loadp (FunctionRareData::m_executable - (constexpr JSFunction::rareDataTag))[targetRegister], targetRegister
.isExecutable:
loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister
- loadp ExecutableToCodeBlockEdge::m_codeBlock[targetRegister], targetRegister
end
macro functionForConstructCodeBlockGetter(targetRegister)
@@ -1507,7 +1506,6 @@
loadp (FunctionRareData::m_executable - (constexpr JSFunction::rareDataTag))[targetRegister], targetRegister
.isExecutable:
loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister
- loadp ExecutableToCodeBlockEdge::m_codeBlock[targetRegister], targetRegister
end
macro notFunctionCodeBlockGetter(targetRegister)
Modified: trunk/Source/_javascript_Core/runtime/DirectEvalExecutable.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/DirectEvalExecutable.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/DirectEvalExecutable.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -63,7 +63,7 @@
return nullptr;
}
- executable->m_unlinkedEvalCodeBlock.set(vm, executable, unlinkedEvalCode);
+ executable->m_unlinkedCodeBlock.set(vm, executable, unlinkedEvalCode);
return executable;
}
Modified: trunk/Source/_javascript_Core/runtime/EvalExecutable.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/EvalExecutable.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/EvalExecutable.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -56,8 +56,6 @@
EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
- visitor.append(thisObject->m_unlinkedEvalCodeBlock);
- visitor.append(thisObject->m_evalCodeBlock);
if (TemplateObjectMap* map = thisObject->m_templateObjectMap.get()) {
Locker locker { thisObject->cellLock() };
for (auto& entry : *map)
Modified: trunk/Source/_javascript_Core/runtime/EvalExecutable.h (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/EvalExecutable.h 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/EvalExecutable.h 2022-04-01 00:33:33 UTC (rev 292191)
@@ -25,7 +25,6 @@
#pragma once
-#include "ExecutableToCodeBlockEdge.h"
#include "GlobalExecutable.h"
#include "UnlinkedEvalCodeBlock.h"
@@ -39,11 +38,16 @@
static void destroy(JSCell*);
- EvalCodeBlock* codeBlock()
+ EvalCodeBlock* codeBlock() const
{
- return bitwise_cast<EvalCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_evalCodeBlock.get()));
+ return bitwise_cast<EvalCodeBlock*>(Base::codeBlock());
}
+ UnlinkedEvalCodeBlock* unlinkedCodeBlock() const
+ {
+ return bitwise_cast<UnlinkedEvalCodeBlock*>(Base::unlinkedCodeBlock());
+ }
+
Ref<JITCode> generatedJITCode()
{
return generatedJITCodeForCall();
@@ -62,10 +66,10 @@
DECLARE_INFO;
- unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
- unsigned numFunctionHoistingCandidates() { return m_unlinkedEvalCodeBlock->numFunctionHoistingCandidates(); }
- unsigned numTopLevelFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
- bool allowDirectEvalCache() const { return m_unlinkedEvalCodeBlock->allowDirectEvalCache(); }
+ unsigned numVariables() { return unlinkedCodeBlock()->numVariables(); }
+ unsigned numFunctionHoistingCandidates() { return unlinkedCodeBlock()->numFunctionHoistingCandidates(); }
+ unsigned numTopLevelFunctionDecls() { return unlinkedCodeBlock()->numberOfFunctionDecls(); }
+ bool allowDirectEvalCache() const { return unlinkedCodeBlock()->allowDirectEvalCache(); }
NeedsClassFieldInitializer needsClassFieldInitializer() const { return static_cast<NeedsClassFieldInitializer>(m_needsClassFieldInitializer); }
PrivateBrandRequirement privateBrandRequirement() const { return static_cast<PrivateBrandRequirement>(m_privateBrandRequirement); }
TemplateObjectMap& ensureTemplateObjectMap(VM&);
@@ -82,8 +86,6 @@
unsigned m_needsClassFieldInitializer : 1;
unsigned m_privateBrandRequirement : 1;
- WriteBarrier<ExecutableToCodeBlockEdge> m_evalCodeBlock;
- WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
std::unique_ptr<TemplateObjectMap> m_templateObjectMap;
};
Modified: trunk/Source/_javascript_Core/runtime/FunctionExecutable.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/FunctionExecutable.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/FunctionExecutable.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -24,10 +24,13 @@
*/
#include "config.h"
+#include "FunctionExecutable.h"
#include "CodeBlock.h"
#include "FunctionCodeBlock.h"
+#include "FunctionExecutableInlines.h"
#include "FunctionOverrides.h"
+#include "IsoCellSetInlines.h"
#include "JSCJSValueInlines.h"
namespace JSC {
@@ -55,27 +58,33 @@
FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
{
- ExecutableToCodeBlockEdge* edge;
+ CodeBlock* codeBlock = nullptr;
if (kind == CodeForCall)
- edge = m_codeBlockForCall.get();
+ codeBlock = codeBlockForCall();
else {
RELEASE_ASSERT(kind == CodeForConstruct);
- edge = m_codeBlockForConstruct.get();
+ codeBlock = codeBlockForConstruct();
}
- if (!edge)
+ if (!codeBlock)
return nullptr;
- return static_cast<FunctionCodeBlock*>(edge->codeBlock()->baselineAlternative());
+ return static_cast<FunctionCodeBlock*>(codeBlock->baselineAlternative());
}
template<typename Visitor>
+static inline bool shouldKeepInConstraintSet(Visitor& visitor, CodeBlock* codeBlockForCall, CodeBlock* codeBlockForConstruct)
+{
+ // If either CodeBlock is not marked yet, we will run output-constraints.
+ return (codeBlockForCall && !visitor.isMarked(codeBlockForCall)) || (codeBlockForConstruct && !visitor.isMarked(codeBlockForConstruct));
+}
+
+template<typename Visitor>
void FunctionExecutable::visitChildrenImpl(JSCell* cell, Visitor& visitor)
{
+ VM& vm = visitor.vm();
FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
visitor.append(thisObject->m_topLevelExecutable);
- visitor.append(thisObject->m_codeBlockForCall);
- visitor.append(thisObject->m_codeBlockForConstruct);
visitor.append(thisObject->m_unlinkedExecutable);
if (RareData* rareData = thisObject->m_rareData.get()) {
visitor.append(rareData->m_cachedPolyProtoStructureID);
@@ -86,10 +95,43 @@
visitor.append(entry.value);
}
}
+
+ // Since FunctionExecutable's finalizer always needs to be run, we do not track FunctionExecutable via finalizerSet.
+ auto* codeBlockForCall = thisObject->m_codeBlockForCall.get();
+ if (codeBlockForCall)
+ visitCodeBlockEdge(visitor, codeBlockForCall);
+ auto* codeBlockForConstruct = thisObject->m_codeBlockForConstruct.get();
+ if (codeBlockForConstruct)
+ visitCodeBlockEdge(visitor, codeBlockForConstruct);
+
+ if (shouldKeepInConstraintSet(visitor, codeBlockForCall, codeBlockForConstruct))
+ vm.heap.functionExecutableSpaceAndSet.outputConstraintsSet.add(thisObject);
}
DEFINE_VISIT_CHILDREN(FunctionExecutable);
+template<typename Visitor>
+void FunctionExecutable::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor)
+{
+ VM& vm = visitor.vm();
+ auto* executable = jsCast<FunctionExecutable*>(cell);
+ auto* codeBlockForCall = executable->m_codeBlockForCall.get();
+ if (codeBlockForCall) {
+ if (!visitor.isMarked(codeBlockForCall))
+ runConstraint(NoLockingNecessary, visitor, codeBlockForCall);
+ }
+ auto* codeBlockForConstruct = executable->codeBlockForConstruct();
+ if (codeBlockForConstruct) {
+ if (!visitor.isMarked(codeBlockForConstruct))
+ runConstraint(NoLockingNecessary, visitor, codeBlockForConstruct);
+ }
+
+ if (!shouldKeepInConstraintSet(visitor, codeBlockForCall, codeBlockForConstruct))
+ vm.heap.functionExecutableSpaceAndSet.outputConstraintsSet.remove(executable);
+}
+
+DEFINE_VISIT_OUTPUT_CONSTRAINTS(FunctionExecutable);
+
FunctionExecutable* FunctionExecutable::fromGlobalCode(
const Identifier& name, JSGlobalObject* globalObject, const SourceCode& source,
JSObject*& exception, int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition)
Modified: trunk/Source/_javascript_Core/runtime/FunctionExecutable.h (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/FunctionExecutable.h 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/FunctionExecutable.h 2022-04-01 00:33:33 UTC (rev 292191)
@@ -25,7 +25,6 @@
#pragma once
-#include "ExecutableToCodeBlockEdge.h"
#include "JSFunction.h"
#include "ScriptExecutable.h"
#include "SourceCode.h"
@@ -69,34 +68,31 @@
// Returns either call or construct bytecode. This can be appropriate
// for answering questions that that don't vary between call and construct --
// for example, argumentsRegister().
- FunctionCodeBlock* eitherCodeBlock()
+ FunctionCodeBlock* eitherCodeBlock() const
{
- ExecutableToCodeBlockEdge* edge;
- if (m_codeBlockForCall)
- edge = m_codeBlockForCall.get();
- else
- edge = m_codeBlockForConstruct.get();
- return bitwise_cast<FunctionCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(edge));
+ if (auto* result = codeBlockForCall())
+ return result;
+ return codeBlockForConstruct();
}
bool isGeneratedForCall() const
{
- return !!m_codeBlockForCall;
+ return !!codeBlockForCall();
}
- FunctionCodeBlock* codeBlockForCall()
+ FunctionCodeBlock* codeBlockForCall() const
{
- return bitwise_cast<FunctionCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_codeBlockForCall.get()));
+ return bitwise_cast<FunctionCodeBlock*>(m_codeBlockForCall.get());
}
bool isGeneratedForConstruct() const
{
- return !!m_codeBlockForConstruct;
+ return !!codeBlockForConstruct();
}
- FunctionCodeBlock* codeBlockForConstruct()
+ FunctionCodeBlock* codeBlockForConstruct() const
{
- return bitwise_cast<FunctionCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_codeBlockForConstruct.get()));
+ return bitwise_cast<FunctionCodeBlock*>(m_codeBlockForConstruct.get());
}
bool isGeneratedFor(CodeSpecializationKind kind)
@@ -122,6 +118,8 @@
return baselineCodeBlockFor(kind);
}
+ FunctionCodeBlock* replaceCodeBlockWith(VM&, CodeSpecializationKind, CodeBlock*);
+
RefPtr<TypeSet> returnStatementTypeSet()
{
RareData& rareData = ensureRareData();
@@ -162,6 +160,7 @@
SourceCode classSource() const { return m_unlinkedExecutable->classSource(); }
DECLARE_VISIT_CHILDREN;
+ DECLARE_VISIT_OUTPUT_CONSTRAINTS;
static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
{
return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), info());
@@ -331,8 +330,8 @@
std::unique_ptr<RareData> m_rareData;
WriteBarrier<ScriptExecutable> m_topLevelExecutable;
WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
- WriteBarrier<ExecutableToCodeBlockEdge> m_codeBlockForCall;
- WriteBarrier<ExecutableToCodeBlockEdge> m_codeBlockForConstruct;
+ WriteBarrier<CodeBlock> m_codeBlockForCall;
+ WriteBarrier<CodeBlock> m_codeBlockForConstruct;
InferredValue<JSFunction> m_singleton;
Box<InlineWatchpointSet> m_polyProtoWatchpoint;
};
Modified: trunk/Source/_javascript_Core/runtime/FunctionExecutableInlines.h (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/FunctionExecutableInlines.h 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/FunctionExecutableInlines.h 2022-04-01 00:33:33 UTC (rev 292191)
@@ -27,6 +27,7 @@
#include "FunctionExecutable.h"
#include "InferredValueInlines.h"
+#include "ScriptExecutableInlines.h"
namespace JSC {
@@ -33,10 +34,26 @@
inline void FunctionExecutable::finalizeUnconditionally(VM& vm)
{
m_singleton.finalizeUnconditionally(vm);
+ finalizeCodeBlockEdge(vm, m_codeBlockForCall);
+ finalizeCodeBlockEdge(vm, m_codeBlockForConstruct);
+ vm.heap.functionExecutableSpaceAndSet.outputConstraintsSet.remove(this);
}
-JSString* FunctionExecutable::toString(JSGlobalObject* globalObject)
+inline FunctionCodeBlock* FunctionExecutable::replaceCodeBlockWith(VM& vm, CodeSpecializationKind kind, CodeBlock* newCodeBlock)
{
+ if (kind == CodeForCall) {
+ FunctionCodeBlock* oldCodeBlock = codeBlockForCall();
+ m_codeBlockForCall.setMayBeNull(vm, this, newCodeBlock);
+ return oldCodeBlock;
+ }
+ ASSERT(kind == CodeForConstruct);
+ FunctionCodeBlock* oldCodeBlock = codeBlockForConstruct();
+ m_codeBlockForConstruct.setMayBeNull(vm, this, newCodeBlock);
+ return oldCodeBlock;
+}
+
+inline JSString* FunctionExecutable::toString(JSGlobalObject* globalObject)
+{
RareData& rareData = ensureRareData();
if (!rareData.m_asString)
return toStringSlow(globalObject);
Modified: trunk/Source/_javascript_Core/runtime/GlobalExecutable.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/GlobalExecutable.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/GlobalExecutable.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -26,10 +26,62 @@
#include "config.h"
#include "GlobalExecutable.h"
+#include "IsoCellSetInlines.h"
#include "JSCellInlines.h"
+#include "ScriptExecutableInlines.h"
namespace JSC {
const ClassInfo GlobalExecutable::s_info = { "GlobalExecutable"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(GlobalExecutable) };
+template<typename Visitor>
+void GlobalExecutable::visitChildrenImpl(JSCell* cell, Visitor& visitor)
+{
+ auto* executable = jsCast<GlobalExecutable*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(executable, info());
+ Base::visitChildren(executable, visitor);
+ visitor.append(executable->m_unlinkedCodeBlock);
+
+ if (auto* codeBlock = executable->codeBlock()) {
+ // If CodeBlocks is not marked yet, we will run output-constraints.
+ // We maintain the invariant that, whenever we see unmarked CodeBlock, then we must run finalizer.
+ // And whenever we set a bit on outputConstraintsSet, we must already set a bit in finalizerSet.
+ visitCodeBlockEdge(visitor, codeBlock);
+ if (!visitor.isMarked(codeBlock)) {
+ Heap::ScriptExecutableSpaceAndSets::finalizerSetFor(*executable->subspace()).add(executable);
+ Heap::ScriptExecutableSpaceAndSets::outputConstraintsSetFor(*executable->subspace()).add(executable);
+ }
+ }
+}
+
+DEFINE_VISIT_CHILDREN(GlobalExecutable);
+
+template<typename Visitor>
+void GlobalExecutable::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor)
+{
+ auto* executable = jsCast<GlobalExecutable*>(cell);
+ if (CodeBlock* codeBlock = executable->codeBlock()) {
+ if (!visitor.isMarked(codeBlock))
+ runConstraint(NoLockingNecessary, visitor, codeBlock);
+ if (visitor.isMarked(codeBlock))
+ Heap::ScriptExecutableSpaceAndSets::outputConstraintsSetFor(*executable->subspace()).remove(executable);
+ }
+}
+
+DEFINE_VISIT_OUTPUT_CONSTRAINTS(GlobalExecutable);
+
+CodeBlock* GlobalExecutable::replaceCodeBlockWith(VM& vm, CodeBlock* newCodeBlock)
+{
+ CodeBlock* oldCodeBlock = codeBlock();
+ m_codeBlock.setMayBeNull(vm, this, newCodeBlock);
+ return oldCodeBlock;
+}
+
+void GlobalExecutable::finalizeUnconditionally(VM& vm)
+{
+ finalizeCodeBlockEdge(vm, m_codeBlock);
+ Heap::ScriptExecutableSpaceAndSets::outputConstraintsSetFor(*subspace()).remove(this);
+ Heap::ScriptExecutableSpaceAndSets::finalizerSetFor(*subspace()).remove(this);
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/GlobalExecutable.h (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/GlobalExecutable.h 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/GlobalExecutable.h 2022-04-01 00:33:33 UTC (rev 292191)
@@ -25,7 +25,6 @@
#pragma once
-#include "ExecutableToCodeBlockEdge.h"
#include "ScriptExecutable.h"
namespace JSC {
@@ -48,12 +47,32 @@
ASSERT(endColumn != UINT_MAX);
}
+ DECLARE_VISIT_CHILDREN;
+ DECLARE_VISIT_OUTPUT_CONSTRAINTS;
+
+ void finalizeUnconditionally(VM&);
+
protected:
+ friend class ScriptExecutable;
GlobalExecutable(Structure* structure, VM& vm, const SourceCode& sourceCode, bool isInStrictContext, DerivedContextType derivedContextType, bool isInArrowFunctionContext, bool isInsideOrdinaryFunction, EvalContextType evalContextType, Intrinsic intrinsic)
: Base(structure, vm, sourceCode, isInStrictContext ? StrictModeLexicalFeature : NoLexicalFeatures, derivedContextType, isInArrowFunctionContext, isInsideOrdinaryFunction, evalContextType, intrinsic)
{
}
+ CodeBlock* codeBlock() const
+ {
+ return m_codeBlock.get();
+ }
+
+ UnlinkedCodeBlock* unlinkedCodeBlock() const
+ {
+ return m_unlinkedCodeBlock.get();
+ }
+
+ CodeBlock* replaceCodeBlockWith(VM&, CodeBlock*);
+
+ WriteBarrier<CodeBlock> m_codeBlock;
+ WriteBarrier<UnlinkedCodeBlock> m_unlinkedCodeBlock;
int m_lastLine { -1 };
unsigned m_endColumn { UINT_MAX };
};
Modified: trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -65,7 +65,7 @@
return nullptr;
}
- executable->m_unlinkedEvalCodeBlock.set(vm, executable, unlinkedEvalCode);
+ executable->m_unlinkedCodeBlock.set(vm, executable, unlinkedEvalCode);
return executable;
}
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -31,6 +31,7 @@
#include "CatchScope.h"
#include "CommonIdentifiers.h"
#include "CallFrame.h"
+#include "FunctionExecutableInlines.h"
#include "GeneratorPrototype.h"
#include "JSBoundFunction.h"
#include "JSCInlines.h"
Modified: trunk/Source/_javascript_Core/runtime/JSModuleRecord.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/JSModuleRecord.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/JSModuleRecord.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -96,7 +96,7 @@
RETURN_IF_EXCEPTION(scope, Synchronousness::Sync);
m_moduleProgramExecutable.set(vm, this, executable);
- return executable->unlinkedModuleProgramCodeBlock()->isAsync() ? Synchronousness::Async : Synchronousness::Sync;
+ return executable->unlinkedCodeBlock()->isAsync() ? Synchronousness::Async : Synchronousness::Sync;
}
void JSModuleRecord::instantiateDeclarations(JSGlobalObject* globalObject, ModuleProgramExecutable* moduleProgramExecutable, JSValue scriptFetcher)
@@ -209,7 +209,7 @@
// section 15.2.1.16.4 step 16-a-iv.
// Initialize heap allocated function declarations.
// They can be called before the body of the module is executed under circular dependencies.
- UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock = moduleProgramExecutable->unlinkedModuleProgramCodeBlock();
+ UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock = moduleProgramExecutable->unlinkedCodeBlock();
for (size_t i = 0, numberOfFunctions = unlinkedCodeBlock->numberOfFunctionDecls(); i < numberOfFunctions; ++i) {
UnlinkedFunctionExecutable* unlinkedFunctionExecutable = unlinkedCodeBlock->functionDecl(i);
SymbolTableEntry entry = symbolTable->get(unlinkedFunctionExecutable->name().impl());
Modified: trunk/Source/_javascript_Core/runtime/ModuleProgramExecutable.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/ModuleProgramExecutable.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/ModuleProgramExecutable.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -62,7 +62,7 @@
return nullptr;
}
- executable->m_unlinkedModuleProgramCodeBlock.set(globalObject->vm(), executable, unlinkedModuleProgramCode);
+ executable->m_unlinkedCodeBlock.set(globalObject->vm(), executable, unlinkedModuleProgramCode);
executable->m_moduleEnvironmentSymbolTable.set(globalObject->vm(), executable, jsCast<SymbolTable*>(unlinkedModuleProgramCode->constantRegister(VirtualRegister(unlinkedModuleProgramCode->moduleEnvironmentSymbolTableConstantRegisterOffset())).get())->cloneScopePart(globalObject->vm()));
@@ -85,9 +85,7 @@
ModuleProgramExecutable* thisObject = jsCast<ModuleProgramExecutable*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
- visitor.append(thisObject->m_unlinkedModuleProgramCodeBlock);
visitor.append(thisObject->m_moduleEnvironmentSymbolTable);
- visitor.append(thisObject->m_moduleProgramCodeBlock);
if (TemplateObjectMap* map = thisObject->m_templateObjectMap.get()) {
Locker locker { thisObject->cellLock() };
for (auto& entry : *map)
Modified: trunk/Source/_javascript_Core/runtime/ModuleProgramExecutable.h (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/ModuleProgramExecutable.h 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/ModuleProgramExecutable.h 2022-04-01 00:33:33 UTC (rev 292191)
@@ -25,7 +25,6 @@
#pragma once
-#include "ExecutableToCodeBlockEdge.h"
#include "GlobalExecutable.h"
namespace JSC {
@@ -46,11 +45,16 @@
static void destroy(JSCell*);
- ModuleProgramCodeBlock* codeBlock()
+ ModuleProgramCodeBlock* codeBlock() const
{
- return bitwise_cast<ModuleProgramCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_moduleProgramCodeBlock.get()));
+ return bitwise_cast<ModuleProgramCodeBlock*>(Base::codeBlock());
}
+ UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock() const
+ {
+ return bitwise_cast<UnlinkedModuleProgramCodeBlock*>(Base::unlinkedCodeBlock());
+ }
+
Ref<JITCode> generatedJITCode()
{
return generatedJITCodeForCall();
@@ -63,7 +67,6 @@
DECLARE_INFO;
- UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); }
bool isAsync() const { return features() & AwaitFeature; }
SymbolTable* moduleEnvironmentSymbolTable() { return m_moduleEnvironmentSymbolTable.get(); }
@@ -78,9 +81,7 @@
DECLARE_VISIT_CHILDREN;
- WriteBarrier<UnlinkedModuleProgramCodeBlock> m_unlinkedModuleProgramCodeBlock;
WriteBarrier<SymbolTable> m_moduleEnvironmentSymbolTable;
- WriteBarrier<ExecutableToCodeBlockEdge> m_moduleProgramCodeBlock;
std::unique_ptr<TemplateObjectMap> m_templateObjectMap;
};
Modified: trunk/Source/_javascript_Core/runtime/ProgramExecutable.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/ProgramExecutable.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/ProgramExecutable.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -150,9 +150,8 @@
}
}
+ m_unlinkedCodeBlock.set(vm, this, unlinkedCodeBlock);
- m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCodeBlock);
-
BatchedTransitionOptimizer optimizer(vm, globalObject);
for (size_t i = 0, numberOfFunctions = unlinkedCodeBlock->numberOfFunctionDecls(); i < numberOfFunctions; ++i) {
@@ -216,8 +215,6 @@
ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
- visitor.append(thisObject->m_unlinkedProgramCodeBlock);
- visitor.append(thisObject->m_programCodeBlock);
if (TemplateObjectMap* map = thisObject->m_templateObjectMap.get()) {
Locker locker { thisObject->cellLock() };
for (auto& entry : *map)
Modified: trunk/Source/_javascript_Core/runtime/ProgramExecutable.h (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/ProgramExecutable.h 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/ProgramExecutable.h 2022-04-01 00:33:33 UTC (rev 292191)
@@ -25,7 +25,6 @@
#pragma once
-#include "ExecutableToCodeBlockEdge.h"
#include "GlobalExecutable.h"
namespace JSC {
@@ -56,11 +55,16 @@
static void destroy(JSCell*);
- ProgramCodeBlock* codeBlock()
+ ProgramCodeBlock* codeBlock() const
{
- return bitwise_cast<ProgramCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_programCodeBlock.get()));
+ return bitwise_cast<ProgramCodeBlock*>(Base::codeBlock());
}
+ UnlinkedProgramCodeBlock* unlinkedCodeBlock() const
+ {
+ return bitwise_cast<UnlinkedProgramCodeBlock*>(Base::unlinkedCodeBlock());
+ }
+
Ref<JITCode> generatedJITCode()
{
return generatedJITCodeForCall();
@@ -83,8 +87,6 @@
DECLARE_VISIT_CHILDREN;
- WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
- WriteBarrier<ExecutableToCodeBlockEdge> m_programCodeBlock;
std::unique_ptr<TemplateObjectMap> m_templateObjectMap;
};
Modified: trunk/Source/_javascript_Core/runtime/ScriptExecutable.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/ScriptExecutable.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/ScriptExecutable.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -29,6 +29,7 @@
#include "Debugger.h"
#include "EvalCodeBlock.h"
#include "FunctionCodeBlock.h"
+#include "FunctionExecutableInlines.h"
#include "GlobalExecutable.h"
#include "IsoCellSetInlines.h"
#include "JIT.h"
@@ -86,20 +87,20 @@
}
case EvalExecutableType: {
EvalExecutable* executable = static_cast<EvalExecutable*>(this);
- executable->m_evalCodeBlock.clear();
- executable->m_unlinkedEvalCodeBlock.clear();
+ executable->m_codeBlock.clear();
+ executable->m_unlinkedCodeBlock.clear();
break;
}
case ProgramExecutableType: {
ProgramExecutable* executable = static_cast<ProgramExecutable*>(this);
- executable->m_programCodeBlock.clear();
- executable->m_unlinkedProgramCodeBlock.clear();
+ executable->m_codeBlock.clear();
+ executable->m_unlinkedCodeBlock.clear();
break;
}
case ModuleProgramExecutableType: {
ModuleProgramExecutable* executable = static_cast<ModuleProgramExecutable*>(this);
- executable->m_moduleProgramCodeBlock.clear();
- executable->m_unlinkedModuleProgramCodeBlock.clear();
+ executable->m_codeBlock.clear();
+ executable->m_unlinkedCodeBlock.clear();
executable->m_moduleEnvironmentSymbolTable.clear();
break;
}
@@ -108,7 +109,7 @@
break;
}
- ASSERT(&Heap::SpaceAndSet::setFor(*subspace()) == &clearableCodeSet);
+ ASSERT(&Heap::ScriptExecutableSpaceAndSets::clearableCodeSetFor(*subspace()) == &clearableCodeSet);
clearableCodeSet.remove(this);
}
@@ -131,8 +132,7 @@
ASSERT(kind == CodeForCall);
- oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_programCodeBlock.get());
- executable->m_programCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
+ oldCodeBlock = executable->replaceCodeBlockWith(vm, codeBlock);
break;
}
@@ -142,8 +142,7 @@
ASSERT(kind == CodeForCall);
- oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_moduleProgramCodeBlock.get());
- executable->m_moduleProgramCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
+ oldCodeBlock = executable->replaceCodeBlockWith(vm, codeBlock);
break;
}
@@ -153,8 +152,7 @@
ASSERT(kind == CodeForCall);
- oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_evalCodeBlock.get());
- executable->m_evalCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
+ oldCodeBlock = executable->replaceCodeBlockWith(vm, codeBlock);
break;
}
@@ -162,16 +160,7 @@
FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
FunctionCodeBlock* codeBlock = static_cast<FunctionCodeBlock*>(genericCodeBlock);
- switch (kind) {
- case CodeForCall:
- oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_codeBlockForCall.get());
- executable->m_codeBlockForCall.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
- break;
- case CodeForConstruct:
- oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_codeBlockForConstruct.get());
- executable->m_codeBlockForConstruct.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
- break;
- }
+ oldCodeBlock = executable->replaceCodeBlockWith(vm, kind, codeBlock);
break;
}
}
@@ -187,7 +176,7 @@
break;
}
- auto& clearableCodeSet = Heap::SpaceAndSet::setFor(*subspace());
+ auto& clearableCodeSet = Heap::ScriptExecutableSpaceAndSets::clearableCodeSetFor(*subspace());
if (hasClearableCode(vm))
clearableCodeSet.add(this);
else
@@ -225,23 +214,23 @@
if (structure(vm)->classInfo() == FunctionExecutable::info()) {
auto* executable = static_cast<const FunctionExecutable*>(this);
- if (executable->m_codeBlockForCall || executable->m_codeBlockForConstruct)
+ if (executable->eitherCodeBlock())
return true;
} else if (structure(vm)->classInfo() == EvalExecutable::info()) {
auto* executable = static_cast<const EvalExecutable*>(this);
- if (executable->m_evalCodeBlock || executable->m_unlinkedEvalCodeBlock)
+ if (executable->m_codeBlock || executable->m_unlinkedCodeBlock)
return true;
} else if (structure(vm)->classInfo() == ProgramExecutable::info()) {
auto* executable = static_cast<const ProgramExecutable*>(this);
- if (executable->m_programCodeBlock || executable->m_unlinkedProgramCodeBlock)
+ if (executable->m_codeBlock || executable->m_unlinkedCodeBlock)
return true;
} else if (structure(vm)->classInfo() == ModuleProgramExecutable::info()) {
auto* executable = static_cast<const ModuleProgramExecutable*>(this);
- if (executable->m_moduleProgramCodeBlock
- || executable->m_unlinkedModuleProgramCodeBlock
+ if (executable->m_codeBlock
+ || executable->m_unlinkedCodeBlock
|| executable->m_moduleEnvironmentSymbolTable)
return true;
}
@@ -261,25 +250,25 @@
if (classInfo(vm) == EvalExecutable::info()) {
EvalExecutable* executable = jsCast<EvalExecutable*>(this);
RELEASE_ASSERT(kind == CodeForCall);
- RELEASE_ASSERT(!executable->m_evalCodeBlock);
+ RELEASE_ASSERT(!executable->m_codeBlock);
RELEASE_ASSERT(!function);
- RELEASE_AND_RETURN(throwScope, EvalCodeBlock::create(vm, executable, executable->m_unlinkedEvalCodeBlock.get(), scope));
+ RELEASE_AND_RETURN(throwScope, EvalCodeBlock::create(vm, executable, executable->unlinkedCodeBlock(), scope));
}
if (classInfo(vm) == ProgramExecutable::info()) {
ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
RELEASE_ASSERT(kind == CodeForCall);
- RELEASE_ASSERT(!executable->m_programCodeBlock);
+ RELEASE_ASSERT(!executable->m_codeBlock);
RELEASE_ASSERT(!function);
- RELEASE_AND_RETURN(throwScope, ProgramCodeBlock::create(vm, executable, executable->m_unlinkedProgramCodeBlock.get(), scope));
+ RELEASE_AND_RETURN(throwScope, ProgramCodeBlock::create(vm, executable, executable->unlinkedCodeBlock(), scope));
}
if (classInfo(vm) == ModuleProgramExecutable::info()) {
ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);
RELEASE_ASSERT(kind == CodeForCall);
- RELEASE_ASSERT(!executable->m_moduleProgramCodeBlock);
+ RELEASE_ASSERT(!executable->m_codeBlock);
RELEASE_ASSERT(!function);
- RELEASE_AND_RETURN(throwScope, ModuleProgramCodeBlock::create(vm, executable, executable->m_unlinkedModuleProgramCodeBlock.get(), scope));
+ RELEASE_AND_RETURN(throwScope, ModuleProgramCodeBlock::create(vm, executable, executable->unlinkedCodeBlock(), scope));
}
RELEASE_ASSERT(classInfo(vm) == FunctionExecutable::info());
@@ -535,4 +524,62 @@
return 0;
}
+template<typename Visitor>
+void ScriptExecutable::runConstraint(const ConcurrentJSLocker& locker, Visitor& visitor, CodeBlock* codeBlock)
+{
+ ASSERT(codeBlock);
+ codeBlock->propagateTransitions(locker, visitor);
+ codeBlock->determineLiveness(locker, visitor);
+}
+
+template void ScriptExecutable::runConstraint(const ConcurrentJSLocker&, AbstractSlotVisitor&, CodeBlock*);
+template void ScriptExecutable::runConstraint(const ConcurrentJSLocker&, SlotVisitor&, CodeBlock*);
+
+template<typename Visitor>
+void ScriptExecutable::visitCodeBlockEdge(Visitor& visitor, CodeBlock* codeBlock)
+{
+ ASSERT(codeBlock);
+
+ ConcurrentJSLocker locker(codeBlock->m_lock);
+
+ if (codeBlock->shouldVisitStrongly(locker, visitor))
+ visitor.appendUnbarriered(codeBlock);
+
+ if (JITCode::isOptimizingJIT(codeBlock->jitType())) {
+ // If we jettison ourselves we'll install our alternative, so make sure that it
+ // survives GC even if we don't.
+ visitor.append(codeBlock->m_alternative);
+ }
+
+ // NOTE: There are two sides to this constraint, with different requirements for correctness.
+ // Because everything is ultimately protected with weak references and jettisoning, it's
+ // always "OK" to claim that something is dead prematurely and it's "OK" to keep things alive.
+ // But both choices could lead to bad perf - either recomp cycles or leaks.
+ //
+ // Determining CodeBlock liveness: This part is the most consequential. We want to keep the
+ // output constraint active so long as we think that we may yet prove that the CodeBlock is
+ // live but we haven't done it yet.
+ //
+ // Marking Structures if profitable: It's important that we do a pass of this. Logically, this
+ // seems like it is a constraint of CodeBlock. But we have always first run this as a result
+ // of the edge being marked even before we determine the liveness of the CodeBlock. This
+ // allows a CodeBlock to mark itself by first proving that all of the Structures it weakly
+ // depends on could be strongly marked. (This part is also called propagateTransitions.)
+ //
+ // As a weird caveat, we only fixpoint the constraints so long as the CodeBlock is not live.
+ // This means that we may overlook structure marking opportunities created by other marking
+ // that happens after the CodeBlock is marked. This was an accidental policy decision from a
+ // long time ago, but it is probably OK, since it's only worthwhile to keep fixpointing the
+ // structure marking if we still have unmarked structures after the first round. We almost
+ // never will because we will mark-if-profitable based on the owning global object being
+ // already marked. We mark it just in case that hadn't happened yet. And if the CodeBlock is
+ // not yet marked because it weakly depends on a structure that we did not yet mark, then we
+ // will keep fixpointing until the end.
+ visitor.appendUnbarriered(codeBlock->globalObject());
+ runConstraint(locker, visitor, codeBlock);
+}
+
+template void ScriptExecutable::visitCodeBlockEdge(AbstractSlotVisitor&, CodeBlock*);
+template void ScriptExecutable::visitCodeBlockEdge(SlotVisitor&, CodeBlock*);
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/ScriptExecutable.h (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/ScriptExecutable.h 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/ScriptExecutable.h 2022-04-01 00:33:33 UTC (rev 292191)
@@ -139,6 +139,12 @@
static TemplateObjectMap& ensureTemplateObjectMapImpl(std::unique_ptr<TemplateObjectMap>& dest);
+ template<typename Visitor>
+ static void runConstraint(const ConcurrentJSLocker&, Visitor&, CodeBlock*);
+ template<typename Visitor>
+ static void visitCodeBlockEdge(Visitor&, CodeBlock*);
+ void finalizeCodeBlockEdge(VM&, WriteBarrier<CodeBlock>&);
+
SourceCode m_source;
Intrinsic m_intrinsic { NoIntrinsic };
bool m_didTryToEnterInLoop { false };
Copied: trunk/Source/_javascript_Core/runtime/ScriptExecutableInlines.h (from rev 292190, trunk/Source/_javascript_Core/runtime/FunctionExecutableInlines.h) (0 => 292191)
--- trunk/Source/_javascript_Core/runtime/ScriptExecutableInlines.h (rev 0)
+++ trunk/Source/_javascript_Core/runtime/ScriptExecutableInlines.h 2022-04-01 00:33:33 UTC (rev 292191)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ScriptExecutable.h"
+
+namespace JSC {
+
+inline void ScriptExecutable::finalizeCodeBlockEdge(VM& vm, WriteBarrier<CodeBlock>& codeBlockEdge)
+{
+ auto* codeBlock = codeBlockEdge.get();
+ if (!codeBlock)
+ return;
+
+ if (!vm.heap.isMarked(codeBlock)) {
+ if (codeBlock->shouldJettisonDueToWeakReference(vm))
+ codeBlock->jettison(Profiler::JettisonDueToWeakReference);
+ else
+ codeBlock->jettison(Profiler::JettisonDueToOldAge);
+ if (codeBlock == codeBlockEdge.get())
+ codeBlockEdge.clear();
+ }
+}
+
+} // namespace JSC
+
Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/VM.cpp 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp 2022-04-01 00:33:33 UTC (rev 292191)
@@ -47,7 +47,6 @@
#include "ErrorInstance.h"
#include "EvalCodeBlock.h"
#include "Exception.h"
-#include "ExecutableToCodeBlockEdge.h"
#include "FTLThunks.h"
#include "FileBasedFuzzerAgent.h"
#include "FunctionCodeBlock.h"
@@ -298,7 +297,6 @@
hashMapBucketSetStructure.set(*this, HashMapBucket<HashMapBucketDataKey>::createStructure(*this, nullptr, jsNull()));
hashMapBucketMapStructure.set(*this, HashMapBucket<HashMapBucketDataKeyValue>::createStructure(*this, nullptr, jsNull()));
bigIntStructure.set(*this, JSBigInt::createStructure(*this, nullptr, jsNull()));
- executableToCodeBlockEdgeStructure.set(*this, ExecutableToCodeBlockEdge::createStructure(*this, nullptr, jsNull()));
// Eagerly initialize constant cells since the concurrent compiler can access them.
if (Options::useJIT()) {
Modified: trunk/Source/_javascript_Core/runtime/VM.h (292190 => 292191)
--- trunk/Source/_javascript_Core/runtime/VM.h 2022-04-01 00:28:42 UTC (rev 292190)
+++ trunk/Source/_javascript_Core/runtime/VM.h 2022-04-01 00:33:33 UTC (rev 292191)
@@ -373,9 +373,6 @@
FOR_EACH_JSC_DYNAMIC_ISO_SUBSPACE(DEFINE_DYNAMIC_ISO_SUBSPACE_ACCESSOR_IMPL)
- ALWAYS_INLINE IsoCellSet& executableToCodeBlockEdgesWithConstraints() { return heap.executableToCodeBlockEdgesWithConstraints; }
- ALWAYS_INLINE IsoCellSet& executableToCodeBlockEdgesWithFinalizers() { return heap.executableToCodeBlockEdgesWithFinalizers; }
-
ALWAYS_INLINE GCClient::IsoSubspace& codeBlockSpace() { return clientHeap.codeBlockSpace; }
DEFINE_DYNAMIC_ISO_SUBSPACE_ACCESSOR(evalExecutableSpace)
@@ -441,7 +438,6 @@
Strong<Structure> hashMapBucketSetStructure;
Strong<Structure> hashMapBucketMapStructure;
Strong<Structure> bigIntStructure;
- Strong<Structure> executableToCodeBlockEdgeStructure;
Strong<JSPropertyNameEnumerator> m_emptyPropertyNameEnumerator;