Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (233038 => 233039)
--- trunk/Source/_javascript_Core/ChangeLog 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-06-21 15:09:40 UTC (rev 233039)
@@ -1,3 +1,83 @@
+2018-06-21 Mark Lam <mark....@apple.com>
+
+ Use IsoCellSets to track Executables with clearable code.
+ https://bugs.webkit.org/show_bug.cgi?id=186877
+
+ Reviewed by Filip Pizlo.
+
+ Here’s an example of the results that this fix may yield:
+ 1. The workload: load cnn.com, wait for it to fully load, scroll down and up.
+ 2. Statistics on memory touched and memory freed by VM::deleteAllCode():
+
+ Visiting Executables:
+ Old New
+ Number of objects visited: 70897 14264
+ Number of objects with deletable code: 14264 (20.1%) 14264 (100%)
+ Number of memory pages visited: 3224 1602
+ Number of memory pages with deletable code: 1602 (49.7%) 1602 (100%)
+
+ Visitng UnlinkedFunctionExecutables:
+ Old New
+ Number of objects visited: 105454 17231
+ Number of objects with deletable code: 42319 (20.1%) 17231 (100%) **
+ Number of memory pages visited: 4796 1349
+ Number of memory pages with deletable code: 4013 (83.7%) 1349 (100%)
+
+ ** The number of objects differ because the old code only visit unlinked
+ executables indirectly via linked executables, whereas the new behavior visit
+ all unlinked executables with deletable code directly. This means:
+
+ a. we used to not visit unlinked executables that have not been linked yet
+ i.e. deleteAllCode() may not delete all code (especially code that is not
+ used).
+ b. we had to visit all linked executables to check if they of type
+ FunctionExecutable, before going on to visit their unlinked executable, and
+ this includes the ones that do not have deletable code. This means that we
+ would touch more memory in the process.
+
+ Both of these these issues are now fixed with the new code.
+
+ This code was tested with manually inserted instrumentation to track the above
+ statistics. It is not feasible to write an automated test for this without
+ leaving a lot of invasive instrumentation in the code.
+
+ * bytecode/UnlinkedFunctionExecutable.cpp:
+ (JSC::UnlinkedFunctionExecutable::unlinkedCodeBlockFor):
+ * bytecode/UnlinkedFunctionExecutable.h:
+ * heap/CodeBlockSetInlines.h:
+ (JSC::CodeBlockSet::iterateViaSubspaces):
+ * heap/Heap.cpp:
+ (JSC::Heap::deleteAllCodeBlocks):
+ (JSC::Heap::deleteAllUnlinkedCodeBlocks):
+ (JSC::Heap::deleteUnmarkedCompiledCode):
+ (JSC::Heap::clearUnmarkedExecutables): Deleted.
+ (JSC::Heap::addExecutable): Deleted.
+ * heap/Heap.h:
+ * runtime/DirectEvalExecutable.h:
+
+ * runtime/ExecutableBase.cpp:
+ (JSC::ExecutableBase::hasClearableCode const):
+ - this is written based on the implementation of ExecutableBase::clearCode().
+
+ * runtime/ExecutableBase.h:
+ * runtime/FunctionExecutable.h:
+ * runtime/IndirectEvalExecutable.h:
+ * runtime/ModuleProgramExecutable.h:
+ * runtime/ProgramExecutable.h:
+ * runtime/ScriptExecutable.cpp:
+ (JSC::ScriptExecutable::clearCode):
+ (JSC::ScriptExecutable::installCode):
+ * runtime/ScriptExecutable.h:
+ (JSC::ScriptExecutable::finishCreation):
+ * runtime/VM.cpp:
+ (JSC::VM::VM):
+ * runtime/VM.h:
+ (JSC::VM::ScriptExecutableSpaceAndSet::ScriptExecutableSpaceAndSet):
+ (JSC::VM::ScriptExecutableSpaceAndSet::clearableCodeSetFor):
+ (JSC::VM::forEachScriptExecutableSpace):
+ (JSC::VM::UnlinkedFunctionExecutableSpaceAndSet::UnlinkedFunctionExecutableSpaceAndSet):
+ (JSC::VM::UnlinkedFunctionExecutableSpaceAndSet::clearableCodeSetFor):
+
2018-06-21 Zan Dobersek <zdober...@igalia.com>
[GTK] WebDriver: allow applying host-specific TLS certificates for automated sessions
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp (233038 => 233039)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp 2018-06-21 15:09:40 UTC (rev 233039)
@@ -33,6 +33,7 @@
#include "Debugger.h"
#include "ExecutableInfo.h"
#include "FunctionOverrides.h"
+#include "IsoCellSetInlines.h"
#include "JSCInlines.h"
#include "Parser.h"
#include "SourceProvider.h"
@@ -224,6 +225,7 @@
m_unlinkedCodeBlockForConstruct.set(vm, this, result);
break;
}
+ vm.unlinkedFunctionExecutableSpace.clearableCodeSet.add(this);
return result;
}
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h (233038 => 233039)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h 2018-06-21 15:09:40 UTC (rev 233039)
@@ -58,6 +58,12 @@
typedef JSCell Base;
static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+ template<typename CellType>
+ static IsoSubspace* subspaceFor(VM& vm)
+ {
+ return &vm.unlinkedFunctionExecutableSpace.space;
+ }
+
static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, VariableEnvironment& parentScopeTDZVariables, DerivedContextType derivedContextType, bool isBuiltinDefaultClassConstructor = false)
{
UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap))
@@ -105,10 +111,11 @@
JS_EXPORT_PRIVATE FunctionExecutable* link(VM&, const SourceCode& parentSource, std::optional<int> overrideLineNumber = std::nullopt, Intrinsic = NoIntrinsic);
- void clearCode()
+ void clearCode(VM& vm)
{
m_unlinkedCodeBlockForCall.clear();
m_unlinkedCodeBlockForConstruct.clear();
+ vm.unlinkedFunctionExecutableSpace.clearableCodeSet.remove(this);
}
void recordParse(CodeFeatures features, bool hasCapturedVariables)
Modified: trunk/Source/_javascript_Core/heap/CodeBlockSetInlines.h (233038 => 233039)
--- trunk/Source/_javascript_Core/heap/CodeBlockSetInlines.h 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/heap/CodeBlockSetInlines.h 2018-06-21 15:09:40 UTC (rev 233039)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -59,8 +59,8 @@
void CodeBlockSet::iterateViaSubspaces(VM& vm, const Functor& functor)
{
vm.forEachCodeBlockSpace(
- [&] (IsoSubspace& space) {
- space.forEachLiveCell(
+ [&] (auto& spaceAndSet) {
+ spaceAndSet.space.forEachLiveCell(
[&] (HeapCell* cell, HeapCell::Kind) {
functor(jsCast<CodeBlock*>(static_cast<JSCell*>(cell)));
});
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (233038 => 233039)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2018-06-21 15:09:40 UTC (rev 233039)
@@ -884,18 +884,27 @@
{
if (m_collectionScope && effort == DeleteAllCodeIfNotCollecting)
return;
-
+
+ VM& vm = *m_vm;
PreventCollectionScope preventCollectionScope(*this);
// If _javascript_ is running, it's not safe to delete all _javascript_ code, since
// we'll end up returning to deleted code.
- RELEASE_ASSERT(!m_vm->entryScope);
+ RELEASE_ASSERT(!vm.entryScope);
RELEASE_ASSERT(!m_collectionScope);
completeAllJITPlans();
- for (ExecutableBase* executable : m_executables)
- executable->clearCode();
+ vm.forEachScriptExecutableSpace(
+ [&] (auto& spaceAndSet) {
+ HeapIterationScope heapIterationScope(*this);
+ auto& clearableCodeSet = spaceAndSet.clearableCodeSet;
+ clearableCodeSet.forEachLiveCell(
+ [&] (HeapCell* cell, HeapCell::Kind) {
+ ScriptExecutable* executable = static_cast<ScriptExecutable*>(cell);
+ executable->clearCode(clearableCodeSet);
+ });
+ });
#if ENABLE(WEBASSEMBLY)
{
@@ -905,10 +914,10 @@
// points into a CodeBlock that could be dead. The IC will still succeed because
// it uses a callee check, but then it will call into dead code.
HeapIterationScope heapIterationScope(*this);
- m_vm->webAssemblyCodeBlockSpace.forEachLiveCell([&] (HeapCell* cell, HeapCell::Kind kind) {
+ vm.webAssemblyCodeBlockSpace.forEachLiveCell([&] (HeapCell* cell, HeapCell::Kind kind) {
ASSERT_UNUSED(kind, kind == HeapCell::Kind::JSCell);
JSWebAssemblyCodeBlock* codeBlock = static_cast<JSWebAssemblyCodeBlock*>(cell);
- codeBlock->clearJSCallICs(*m_vm);
+ codeBlock->clearJSCallICs(vm);
});
}
#endif
@@ -918,38 +927,23 @@
{
if (m_collectionScope && effort == DeleteAllCodeIfNotCollecting)
return;
-
+
+ VM& vm = *m_vm;
PreventCollectionScope preventCollectionScope(*this);
RELEASE_ASSERT(!m_collectionScope);
-
- for (ExecutableBase* current : m_executables) {
- if (!current->isFunctionExecutable())
- continue;
- static_cast<FunctionExecutable*>(current)->unlinkedExecutable()->clearCode();
- }
-}
-void Heap::clearUnmarkedExecutables()
-{
- for (unsigned i = m_executables.size(); i--;) {
- ExecutableBase* current = m_executables[i];
- if (isMarked(current))
- continue;
-
- // Eagerly dereference the Executable's JITCode in order to run watchpoint
- // destructors. Otherwise, watchpoints might fire for deleted CodeBlocks.
- current->clearCode();
- std::swap(m_executables[i], m_executables.last());
- m_executables.removeLast();
- }
-
- m_executables.shrinkToFit();
+ HeapIterationScope heapIterationScope(*this);
+ vm.unlinkedFunctionExecutableSpace.clearableCodeSet.forEachLiveCell(
+ [&] (HeapCell* cell, HeapCell::Kind) {
+ UnlinkedFunctionExecutable* executable = static_cast<UnlinkedFunctionExecutable*>(cell);
+ executable->clearCode(vm);
+ });
}
void Heap::deleteUnmarkedCompiledCode()
{
- clearUnmarkedExecutables();
+ vm()->forEachScriptExecutableSpace([] (auto& space) { space.space.sweep(); });
vm()->forEachCodeBlockSpace([] (auto& space) { space.space.sweep(); }); // Sweeping must occur before deleting stubs, otherwise the stubs might still think they're alive as they get deleted.
m_jitStubRoutines->deleteUnmarkedJettisonedStubRoutines();
}
@@ -2380,11 +2374,6 @@
WeakSet::deallocate(WeakImpl::asWeakImpl(slot));
}
-void Heap::addExecutable(ExecutableBase* executable)
-{
- m_executables.append(executable);
-}
-
void Heap::collectNowFullIfNotDoneRecently(Synchronousness synchronousness)
{
if (!m_fullActivityCallback) {
Modified: trunk/Source/_javascript_Core/heap/Heap.h (233038 => 233039)
--- trunk/Source/_javascript_Core/heap/Heap.h 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/heap/Heap.h 2018-06-21 15:09:40 UTC (rev 233039)
@@ -55,7 +55,6 @@
class ConservativeRoots;
class GCDeferralContext;
class EdenGCActivityCallback;
-class ExecutableBase;
class FullGCActivityCallback;
class GCActivityCallback;
class GCAwareJITStubRoutine;
@@ -165,7 +164,6 @@
typedef void (*Finalizer)(JSCell*);
JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer);
- void addExecutable(ExecutableBase*);
void notifyIsSafeToCollect();
bool isSafeToCollect() const { return m_isSafeToCollect; }
@@ -509,8 +507,7 @@
void finalizeMarkedUnconditionalFinalizers(CellSet&);
void finalizeUnconditionalFinalizers();
-
- void clearUnmarkedExecutables();
+
void deleteUnmarkedCompiledCode();
JS_EXPORT_PRIVATE void addToRememberedSet(const JSCell*);
void updateAllocationLimits();
@@ -628,8 +625,6 @@
Seconds m_lastFullGCLength;
Seconds m_lastEdenGCLength;
- Vector<ExecutableBase*> m_executables;
-
Vector<WeakBlock*> m_logicallyEmptyWeakBlocks;
size_t m_indexOfNextLogicallyEmptyWeakBlockToSweep { WTF::notFound };
Modified: trunk/Source/_javascript_Core/runtime/DirectEvalExecutable.h (233038 => 233039)
--- trunk/Source/_javascript_Core/runtime/DirectEvalExecutable.h 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/runtime/DirectEvalExecutable.h 2018-06-21 15:09:40 UTC (rev 233039)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,7 +34,7 @@
template<typename CellType>
static IsoSubspace* subspaceFor(VM& vm)
{
- return &vm.directEvalExecutableSpace;
+ return &vm.directEvalExecutableSpace.space;
}
static DirectEvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType, const VariableEnvironment*);
Modified: trunk/Source/_javascript_Core/runtime/ExecutableBase.cpp (233038 => 233039)
--- trunk/Source/_javascript_Core/runtime/ExecutableBase.cpp 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/runtime/ExecutableBase.cpp 2018-06-21 15:09:40 UTC (rev 233039)
@@ -49,6 +49,43 @@
static_cast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
}
+bool ExecutableBase::hasClearableCode() const
+{
+ VM& vm = *this->vm();
+
+#if ENABLE(JIT)
+ if (m_jitCodeForCall
+ || m_jitCodeForConstruct
+ || m_jitCodeForCallWithArityCheck
+ || m_jitCodeForConstructWithArityCheck)
+ return true;
+#endif
+
+ if (structure(vm)->classInfo() == FunctionExecutable::info()) {
+ auto* executable = static_cast<const FunctionExecutable*>(this);
+ if (executable->m_codeBlockForCall || executable->m_codeBlockForConstruct)
+ return true;
+
+ } else if (structure(vm)->classInfo() == EvalExecutable::info()) {
+ auto* executable = static_cast<const EvalExecutable*>(this);
+ if (executable->m_evalCodeBlock || executable->m_unlinkedEvalCodeBlock)
+ return true;
+
+ } else if (structure(vm)->classInfo() == ProgramExecutable::info()) {
+ auto* executable = static_cast<const ProgramExecutable*>(this);
+ if (executable->m_programCodeBlock || executable->m_unlinkedProgramCodeBlock)
+ return true;
+
+ } else if (structure(vm)->classInfo() == ModuleProgramExecutable::info()) {
+ auto* executable = static_cast<const ModuleProgramExecutable*>(this);
+ if (executable->m_moduleProgramCodeBlock
+ || executable->m_unlinkedModuleProgramCodeBlock
+ || executable->m_moduleEnvironmentSymbolTable)
+ return true;
+ }
+ return false;
+}
+
void ExecutableBase::clearCode()
{
#if ENABLE(JIT)
Modified: trunk/Source/_javascript_Core/runtime/ExecutableBase.h (233038 => 233039)
--- trunk/Source/_javascript_Core/runtime/ExecutableBase.h 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/runtime/ExecutableBase.h 2018-06-21 15:09:40 UTC (rev 233039)
@@ -114,7 +114,8 @@
}
static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); }
-
+
+ bool hasClearableCode() const;
void clearCode();
DECLARE_EXPORT_INFO;
Modified: trunk/Source/_javascript_Core/runtime/FunctionExecutable.h (233038 => 233039)
--- trunk/Source/_javascript_Core/runtime/FunctionExecutable.h 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/runtime/FunctionExecutable.h 2018-06-21 15:09:40 UTC (rev 233039)
@@ -42,7 +42,7 @@
template<typename CellType>
static IsoSubspace* subspaceFor(VM& vm)
{
- return &vm.functionExecutableSpace;
+ return &vm.functionExecutableSpace.space;
}
static FunctionExecutable* create(
Modified: trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.h (233038 => 233039)
--- trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.h 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.h 2018-06-21 15:09:40 UTC (rev 233039)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,7 +34,7 @@
template<typename CellType>
static IsoSubspace* subspaceFor(VM& vm)
{
- return &vm.indirectEvalExecutableSpace;
+ return &vm.indirectEvalExecutableSpace.space;
}
static IndirectEvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType);
Modified: trunk/Source/_javascript_Core/runtime/ModuleProgramExecutable.h (233038 => 233039)
--- trunk/Source/_javascript_Core/runtime/ModuleProgramExecutable.h 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/runtime/ModuleProgramExecutable.h 2018-06-21 15:09:40 UTC (rev 233039)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2009-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -39,7 +39,7 @@
template<typename CellType>
static IsoSubspace* subspaceFor(VM& vm)
{
- return &vm.moduleProgramExecutableSpace;
+ return &vm.moduleProgramExecutableSpace.space;
}
static ModuleProgramExecutable* create(ExecState*, const SourceCode&);
Modified: trunk/Source/_javascript_Core/runtime/ProgramExecutable.h (233038 => 233039)
--- trunk/Source/_javascript_Core/runtime/ProgramExecutable.h 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/runtime/ProgramExecutable.h 2018-06-21 15:09:40 UTC (rev 233039)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2009-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -39,7 +39,7 @@
template<typename CellType>
static IsoSubspace* subspaceFor(VM& vm)
{
- return &vm.programExecutableSpace;
+ return &vm.programExecutableSpace.space;
}
static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
Modified: trunk/Source/_javascript_Core/runtime/ScriptExecutable.cpp (233038 => 233039)
--- trunk/Source/_javascript_Core/runtime/ScriptExecutable.cpp 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/runtime/ScriptExecutable.cpp 2018-06-21 15:09:40 UTC (rev 233039)
@@ -30,6 +30,7 @@
#include "Debugger.h"
#include "EvalCodeBlock.h"
#include "FunctionCodeBlock.h"
+#include "IsoCellSetInlines.h"
#include "JIT.h"
#include "JSCInlines.h"
#include "LLIntEntrypoint.h"
@@ -70,6 +71,13 @@
static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
}
+void ScriptExecutable::clearCode(IsoCellSet& clearableCodeSet)
+{
+ Base::clearCode();
+ ASSERT(&VM::ScriptExecutableSpaceAndSet::clearableCodeSetFor(*subspace()) == &clearableCodeSet);
+ clearableCodeSet.remove(this);
+}
+
void ScriptExecutable::installCode(CodeBlock* codeBlock)
{
installCode(*codeBlock->vm(), codeBlock, codeBlock->codeType(), codeBlock->specializationKind());
@@ -147,6 +155,12 @@
break;
}
+ auto& clearableCodeSet = VM::ScriptExecutableSpaceAndSet::clearableCodeSetFor(*subspace());
+ if (hasClearableCode())
+ clearableCodeSet.add(this);
+ else
+ clearableCodeSet.remove(this);
+
if (genericCodeBlock) {
RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);
RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock->jitType()));
Modified: trunk/Source/_javascript_Core/runtime/ScriptExecutable.h (233038 => 233039)
--- trunk/Source/_javascript_Core/runtime/ScriptExecutable.h 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/runtime/ScriptExecutable.h 2018-06-21 15:09:40 UTC (rev 233039)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2010, 2013-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2009-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,6 +29,8 @@
namespace JSC {
+class IsoCellSet;
+
class ScriptExecutable : public ExecutableBase {
public:
typedef ExecutableBase Base;
@@ -94,6 +96,8 @@
CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception);
CodeBlock* newReplacementCodeBlockFor(CodeSpecializationKind);
+ void clearCode(IsoCellSet&);
+
// This function has an interesting GC story. Callers of this function are asking us to create a CodeBlock
// that is not jettisoned before this function returns. Callers are essentially asking for a strong reference
// to the CodeBlock. Because the Executable may be allocating the CodeBlock, we require callers to pass in
@@ -113,7 +117,6 @@
void finishCreation(VM& vm)
{
Base::finishCreation(vm);
- vm.heap.addExecutable(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
#if ENABLE(CODEBLOCK_SAMPLING)
if (SamplingTool* sampler = vm.interpreter->sampler())
Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (233038 => 233039)
--- trunk/Source/_javascript_Core/runtime/VM.cpp 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp 2018-06-21 15:09:40 UTC (rev 233039)
@@ -278,13 +278,10 @@
, boundFunctionSpace ISO_SUBSPACE_INIT(heap, cellJSValueOOBHeapCellType.get(), JSBoundFunction)
, callbackFunctionSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), JSCallbackFunction)
, customGetterSetterFunctionSpace ISO_SUBSPACE_INIT(heap, cellJSValueOOBHeapCellType.get(), JSCustomGetterSetterFunction)
- , directEvalExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), DirectEvalExecutable)
, errorConstructorSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), ErrorConstructor)
, executableToCodeBlockEdgeSpace ISO_SUBSPACE_INIT(heap, cellDangerousBitsHeapCellType.get(), ExecutableToCodeBlockEdge)
- , functionExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), FunctionExecutable)
, functionSpace ISO_SUBSPACE_INIT(heap, cellJSValueOOBHeapCellType.get(), JSFunction)
, generatorFunctionSpace ISO_SUBSPACE_INIT(heap, cellJSValueOOBHeapCellType.get(), JSGeneratorFunction)
- , indirectEvalExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), IndirectEvalExecutable)
, inferredTypeSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), InferredType)
, inferredValueSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), InferredValue)
, internalFunctionSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), InternalFunction)
@@ -294,7 +291,6 @@
, intlNumberFormatConstructorSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), IntlNumberFormatConstructor)
, intlPluralRulesConstructorSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), IntlPluralRulesConstructor)
#endif
- , moduleProgramExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), ModuleProgramExecutable)
, nativeErrorConstructorSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), NativeErrorConstructor)
, nativeExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), NativeExecutable)
, nativeStdFunctionSpace ISO_SUBSPACE_INIT(heap, cellJSValueOOBHeapCellType.get(), JSNativeStdFunction)
@@ -301,7 +297,6 @@
#if JSC_OBJC_API_ENABLED
, objCCallbackFunctionSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), ObjCCallbackFunction)
#endif
- , programExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), ProgramExecutable)
, propertyTableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), PropertyTable)
, proxyRevokeSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), ProxyRevoke)
, regExpConstructorSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), RegExpConstructor)
@@ -324,6 +319,12 @@
, functionCodeBlockSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), FunctionCodeBlock)
, moduleProgramCodeBlockSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), ModuleProgramCodeBlock)
, programCodeBlockSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), ProgramCodeBlock)
+ , directEvalExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), DirectEvalExecutable)
+ , functionExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), FunctionExecutable)
+ , indirectEvalExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), IndirectEvalExecutable)
+ , moduleProgramExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), ModuleProgramExecutable)
+ , programExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), ProgramExecutable)
+ , unlinkedFunctionExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), UnlinkedFunctionExecutable)
, vmType(vmType)
, clientData(0)
, topEntryFrame(nullptr)
Modified: trunk/Source/_javascript_Core/runtime/VM.h (233038 => 233039)
--- trunk/Source/_javascript_Core/runtime/VM.h 2018-06-21 14:00:51 UTC (rev 233038)
+++ trunk/Source/_javascript_Core/runtime/VM.h 2018-06-21 15:09:40 UTC (rev 233039)
@@ -352,13 +352,10 @@
IsoSubspace boundFunctionSpace;
IsoSubspace callbackFunctionSpace;
IsoSubspace customGetterSetterFunctionSpace;
- IsoSubspace directEvalExecutableSpace;
IsoSubspace errorConstructorSpace;
IsoSubspace executableToCodeBlockEdgeSpace;
- IsoSubspace functionExecutableSpace;
IsoSubspace functionSpace;
IsoSubspace generatorFunctionSpace;
- IsoSubspace indirectEvalExecutableSpace;
IsoSubspace inferredTypeSpace;
IsoSubspace inferredValueSpace;
IsoSubspace internalFunctionSpace;
@@ -368,7 +365,6 @@
IsoSubspace intlNumberFormatConstructorSpace;
IsoSubspace intlPluralRulesConstructorSpace;
#endif
- IsoSubspace moduleProgramExecutableSpace;
IsoSubspace nativeErrorConstructorSpace;
IsoSubspace nativeExecutableSpace;
IsoSubspace nativeStdFunctionSpace;
@@ -375,7 +371,6 @@
#if JSC_OBJC_API_ENABLED
IsoSubspace objCCallbackFunctionSpace;
#endif
- IsoSubspace programExecutableSpace;
IsoSubspace propertyTableSpace;
IsoSubspace proxyRevokeSpace;
IsoSubspace regExpConstructorSpace;
@@ -431,7 +426,63 @@
func(moduleProgramCodeBlockSpace);
func(programCodeBlockSpace);
}
-
+
+ struct ScriptExecutableSpaceAndSet {
+ IsoSubspace space;
+ IsoCellSet clearableCodeSet;
+
+ template<typename... Arguments>
+ ScriptExecutableSpaceAndSet(Arguments&&... arguments)
+ : space(std::forward<Arguments>(arguments)...)
+ , clearableCodeSet(space)
+ { }
+
+ static IsoCellSet& clearableCodeSetFor(Subspace& space)
+ {
+ return *bitwise_cast<IsoCellSet*>(
+ bitwise_cast<char*>(&space) -
+ OBJECT_OFFSETOF(ScriptExecutableSpaceAndSet, space) +
+ OBJECT_OFFSETOF(ScriptExecutableSpaceAndSet, clearableCodeSet));
+ }
+ };
+
+ ScriptExecutableSpaceAndSet directEvalExecutableSpace;
+ ScriptExecutableSpaceAndSet functionExecutableSpace;
+ ScriptExecutableSpaceAndSet indirectEvalExecutableSpace;
+ ScriptExecutableSpaceAndSet moduleProgramExecutableSpace;
+ ScriptExecutableSpaceAndSet programExecutableSpace;
+
+ template<typename Func>
+ void forEachScriptExecutableSpace(const Func& func)
+ {
+ func(directEvalExecutableSpace);
+ func(functionExecutableSpace);
+ func(indirectEvalExecutableSpace);
+ func(moduleProgramExecutableSpace);
+ func(programExecutableSpace);
+ }
+
+ struct UnlinkedFunctionExecutableSpaceAndSet {
+ IsoSubspace space;
+ IsoCellSet clearableCodeSet;
+
+ template<typename... Arguments>
+ UnlinkedFunctionExecutableSpaceAndSet(Arguments&&... arguments)
+ : space(std::forward<Arguments>(arguments)...)
+ , clearableCodeSet(space)
+ { }
+
+ static IsoCellSet& clearableCodeSetFor(Subspace& space)
+ {
+ return *bitwise_cast<IsoCellSet*>(
+ bitwise_cast<char*>(&space) -
+ OBJECT_OFFSETOF(UnlinkedFunctionExecutableSpaceAndSet, space) +
+ OBJECT_OFFSETOF(UnlinkedFunctionExecutableSpaceAndSet, clearableCodeSet));
+ }
+ };
+
+ UnlinkedFunctionExecutableSpaceAndSet unlinkedFunctionExecutableSpace;
+
VMType vmType;
ClientData* clientData;
EntryFrame* topEntryFrame;