CallLinkInfos belonging to Wasm->JS stubs need to be informed when we clearCode(...
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 May 2017 07:15:01 +0000 (07:15 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 May 2017 07:15:01 +0000 (07:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=171707
<rdar://problem/31891649>

Reviewed by Filip Pizlo.

This patch fixes a bug where a Wasm->JS IC call stub would go stale
and point into a CodeBlock no longer owned by any executable. The
problematic scenario is this:

1. We generate the call IC which has a branch on a callee check. This
   callee owns the Executable in question. If the branch succeeds, it
   will call code belonging to a particular CodeBlock associated with
   that Executable.

2. Heap::deleteAllCodeBlocks is called. This leads the Executable to clear
   its various CodeBlock references.

3. Wasm has no idea this happened, so now it has stale ICs that point into
   code from a CodeBlock no longer belonging to an Executable.

This patch fixes the bug by informing all JSWebAssemblyCodeBlocks to unlink
their CallLinkInfo when Heap::deleteAllCodeBlocks is called.

We track all JSWebAssemblyCodeBlocks by creating a new subspace for them.
This allows us to quickly iterate over the live JSWebAssemblyCodeBlocks in the
heap.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* heap/Heap.cpp:
(JSC::Heap::deleteAllCodeBlocks):
* heap/Subspace.h:
* heap/SubspaceInlines.h:
(JSC::Subspace::forEachLiveCell):
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:
* wasm/js/JSWebAssemblyCodeBlock.cpp:
(JSC::JSWebAssemblyCodeBlock::clearJSCallICs):
* wasm/js/JSWebAssemblyCodeBlock.h:
(JSC::JSWebAssemblyCodeBlock::createStructure): Deleted.
(JSC::JSWebAssemblyCodeBlock::functionImportCount): Deleted.
(JSC::JSWebAssemblyCodeBlock::module): Deleted.
(JSC::JSWebAssemblyCodeBlock::jsEntrypointCalleeFromFunctionIndexSpace): Deleted.
(JSC::JSWebAssemblyCodeBlock::wasmEntrypointLoadLocationFromFunctionIndexSpace): Deleted.
(JSC::JSWebAssemblyCodeBlock::wasmToJsCallStubForImport): Deleted.
(JSC::JSWebAssemblyCodeBlock::offsetOfImportWasmToJSStub): Deleted.
(JSC::JSWebAssemblyCodeBlock::codeBlock): Deleted.
(JSC::JSWebAssemblyCodeBlock::offsetOfImportStubs): Deleted.
(JSC::JSWebAssemblyCodeBlock::allocationSize): Deleted.
(JSC::JSWebAssemblyCodeBlock::importWasmToJSStub): Deleted.
* wasm/js/JSWebAssemblyCodeBlockSubspace.cpp: Added.
(JSC::JSWebAssemblyCodeBlockSubspace::JSWebAssemblyCodeBlockSubspace):
(JSC::JSWebAssemblyCodeBlockSubspace::~JSWebAssemblyCodeBlockSubspace):
(JSC::JSWebAssemblyCodeBlockSubspace::finishSweep):
(JSC::JSWebAssemblyCodeBlockSubspace::destroy):
* wasm/js/JSWebAssemblyCodeBlockSubspace.h: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@216481 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/heap/Subspace.h
Source/JavaScriptCore/heap/SubspaceInlines.h
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlockSubspace.cpp [new file with mode: 0644]
Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlockSubspace.h [new file with mode: 0644]

index 42d0c4a..691c0e5 100644 (file)
@@ -967,6 +967,7 @@ set(JavaScriptCore_SOURCES
     wasm/WasmWorklist.cpp
 
     wasm/js/JSWebAssemblyCodeBlock.cpp
+    wasm/js/JSWebAssemblyCodeBlockSubspace.cpp
     wasm/js/JSWebAssemblyCompileError.cpp
     wasm/js/JSWebAssemblyInstance.cpp
     wasm/js/JSWebAssemblyLinkError.cpp
index e9dcd4e..974a4db 100644 (file)
@@ -1,3 +1,64 @@
+2017-05-09  Saam Barati  <sbarati@apple.com>
+
+        CallLinkInfos belonging to Wasm->JS stubs need to be informed when we clearCode() from all Executables
+        https://bugs.webkit.org/show_bug.cgi?id=171707
+        <rdar://problem/31891649>
+
+        Reviewed by Filip Pizlo.
+
+        This patch fixes a bug where a Wasm->JS IC call stub would go stale
+        and point into a CodeBlock no longer owned by any executable. The
+        problematic scenario is this:
+
+        1. We generate the call IC which has a branch on a callee check. This
+           callee owns the Executable in question. If the branch succeeds, it
+           will call code belonging to a particular CodeBlock associated with
+           that Executable.
+
+        2. Heap::deleteAllCodeBlocks is called. This leads the Executable to clear
+           its various CodeBlock references.
+
+        3. Wasm has no idea this happened, so now it has stale ICs that point into
+           code from a CodeBlock no longer belonging to an Executable.
+
+        This patch fixes the bug by informing all JSWebAssemblyCodeBlocks to unlink
+        their CallLinkInfo when Heap::deleteAllCodeBlocks is called.
+
+        We track all JSWebAssemblyCodeBlocks by creating a new subspace for them.
+        This allows us to quickly iterate over the live JSWebAssemblyCodeBlocks in the
+        heap.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * heap/Heap.cpp:
+        (JSC::Heap::deleteAllCodeBlocks):
+        * heap/Subspace.h:
+        * heap/SubspaceInlines.h:
+        (JSC::Subspace::forEachLiveCell):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+        * wasm/js/JSWebAssemblyCodeBlock.cpp:
+        (JSC::JSWebAssemblyCodeBlock::clearJSCallICs):
+        * wasm/js/JSWebAssemblyCodeBlock.h:
+        (JSC::JSWebAssemblyCodeBlock::createStructure): Deleted.
+        (JSC::JSWebAssemblyCodeBlock::functionImportCount): Deleted.
+        (JSC::JSWebAssemblyCodeBlock::module): Deleted.
+        (JSC::JSWebAssemblyCodeBlock::jsEntrypointCalleeFromFunctionIndexSpace): Deleted.
+        (JSC::JSWebAssemblyCodeBlock::wasmEntrypointLoadLocationFromFunctionIndexSpace): Deleted.
+        (JSC::JSWebAssemblyCodeBlock::wasmToJsCallStubForImport): Deleted.
+        (JSC::JSWebAssemblyCodeBlock::offsetOfImportWasmToJSStub): Deleted.
+        (JSC::JSWebAssemblyCodeBlock::codeBlock): Deleted.
+        (JSC::JSWebAssemblyCodeBlock::offsetOfImportStubs): Deleted.
+        (JSC::JSWebAssemblyCodeBlock::allocationSize): Deleted.
+        (JSC::JSWebAssemblyCodeBlock::importWasmToJSStub): Deleted.
+        * wasm/js/JSWebAssemblyCodeBlockSubspace.cpp: Added.
+        (JSC::JSWebAssemblyCodeBlockSubspace::JSWebAssemblyCodeBlockSubspace):
+        (JSC::JSWebAssemblyCodeBlockSubspace::~JSWebAssemblyCodeBlockSubspace):
+        (JSC::JSWebAssemblyCodeBlockSubspace::finishSweep):
+        (JSC::JSWebAssemblyCodeBlockSubspace::destroy):
+        * wasm/js/JSWebAssemblyCodeBlockSubspace.h: Added.
+
 2017-05-08  Saam Barati  <sbarati@apple.com>
 
         testWasmBoundsCheck and testCallFunctionWithHellaArguments is broken in testb3
index 89ebf54..c5389fd 100644 (file)
                79DFCBDB1D88C59600527D03 /* HasOwnPropertyCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 79DFCBDA1D88C59600527D03 /* HasOwnPropertyCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
                79EE0BFF1B4AFB85000385C9 /* VariableEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79EE0BFD1B4AFB85000385C9 /* VariableEnvironment.cpp */; };
                79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EE0BFE1B4AFB85000385C9 /* VariableEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               79EFD4831EBC045C00F3DFEA /* JSWebAssemblyCodeBlockSubspace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79EFD4811EBC045C00F3DFEA /* JSWebAssemblyCodeBlockSubspace.cpp */; };
+               79EFD4841EBC045C00F3DFEA /* JSWebAssemblyCodeBlockSubspace.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EFD4821EBC045C00F3DFEA /* JSWebAssemblyCodeBlockSubspace.h */; settings = {ATTRIBUTES = (Private, ); }; };
                79F8FC1E1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79F8FC1C1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp */; };
                79F8FC1F1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 79F8FC1D1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.h */; };
                79FC8A081E32E9F000D88F0E /* DFGRegisteredStructure.h in Headers */ = {isa = PBXBuildFile; fileRef = 79FC8A071E32E9F000D88F0E /* DFGRegisteredStructure.h */; settings = {ATTRIBUTES = (Private, ); }; };
                79DFCBDA1D88C59600527D03 /* HasOwnPropertyCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HasOwnPropertyCache.h; sourceTree = "<group>"; };
                79EE0BFD1B4AFB85000385C9 /* VariableEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VariableEnvironment.cpp; sourceTree = "<group>"; };
                79EE0BFE1B4AFB85000385C9 /* VariableEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VariableEnvironment.h; sourceTree = "<group>"; };
+               79EFD4811EBC045C00F3DFEA /* JSWebAssemblyCodeBlockSubspace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSWebAssemblyCodeBlockSubspace.cpp; path = js/JSWebAssemblyCodeBlockSubspace.cpp; sourceTree = "<group>"; };
+               79EFD4821EBC045C00F3DFEA /* JSWebAssemblyCodeBlockSubspace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSWebAssemblyCodeBlockSubspace.h; path = js/JSWebAssemblyCodeBlockSubspace.h; sourceTree = "<group>"; };
                79F8FC1C1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGMaximalFlushInsertionPhase.cpp; path = dfg/DFGMaximalFlushInsertionPhase.cpp; sourceTree = "<group>"; };
                79F8FC1D1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGMaximalFlushInsertionPhase.h; path = dfg/DFGMaximalFlushInsertionPhase.h; sourceTree = "<group>"; };
                79FC8A071E32E9F000D88F0E /* DFGRegisteredStructure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGRegisteredStructure.h; path = dfg/DFGRegisteredStructure.h; sourceTree = "<group>"; };
                        children = (
                                5383AA2F1E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp */,
                                AD9E852E1E8A0C6E008DE39E /* JSWebAssemblyCodeBlock.h */,
+                               79EFD4811EBC045C00F3DFEA /* JSWebAssemblyCodeBlockSubspace.cpp */,
+                               79EFD4821EBC045C00F3DFEA /* JSWebAssemblyCodeBlockSubspace.h */,
                                AD2FCBA61DB58DA400B3E736 /* JSWebAssemblyCompileError.cpp */,
                                AD2FCBA71DB58DA400B3E736 /* JSWebAssemblyCompileError.h */,
                                796FB4391DFF8C3F0039C95D /* JSWebAssemblyHelpers.h */,
                                0FB14E1F18124ACE009B6B4D /* JITInlineCacheGenerator.h in Headers */,
                                86CC85A10EE79A4700288682 /* JITInlines.h in Headers */,
                                FE3A06BE1C11041200390FDD /* JITLeftShiftGenerator.h in Headers */,
+                               79EFD4841EBC045C00F3DFEA /* JSWebAssemblyCodeBlockSubspace.h in Headers */,
                                79233C2B1D34715700C5A834 /* JITMathIC.h in Headers */,
                                79B1788E1D399B8000B1A567 /* JITMathICForwards.h in Headers */,
                                79AF0BE41D3EFD4C00E95FA5 /* JITMathICInlineResult.h in Headers */,
                                658824B11E5CFDF400FB7359 /* ConfigFile.cpp in Sources */,
                                A700874117CBE8EB00C3E643 /* JSMap.cpp in Sources */,
                                A74DEF95182D991400522C22 /* JSMapIterator.cpp in Sources */,
+                               79EFD4831EBC045C00F3DFEA /* JSWebAssemblyCodeBlockSubspace.cpp in Sources */,
                                E3D239C81B829C1C00BBEF67 /* JSModuleEnvironment.cpp in Sources */,
                                13FECE06D3B445FCB6C93461 /* JSModuleLoader.cpp in Sources */,
                                E318CBC01B8AEF5100A2929D /* JSModuleNamespaceObject.cpp in Sources */,
index 79bc9c0..c436a8b 100644 (file)
 #include "JSGlobalObject.h"
 #include "JSLock.h"
 #include "JSVirtualMachineInternal.h"
+#include "JSWebAssemblyCodeBlock.h"
 #include "MachineStackMarker.h"
+#include "MarkedAllocatorInlines.h"
 #include "MarkedSpaceInlines.h"
 #include "MarkingConstraintSet.h"
 #include "PreventCollectionScope.h"
 #include "SamplingProfiler.h"
 #include "ShadowChicken.h"
 #include "SpaceTimeMutatorScheduler.h"
+#include "SubspaceInlines.h"
 #include "SuperSampler.h"
 #include "StochasticSpaceTimeMutatorScheduler.h"
 #include "StopIfNecessaryTimer.h"
@@ -828,6 +831,22 @@ void Heap::deleteAllCodeBlocks(DeleteAllCodeEffort effort)
 
     for (ExecutableBase* executable : m_executables)
         executable->clearCode();
+
+#if ENABLE(WEBASSEMBLY)
+    {
+        // We must ensure that we clear the JS call ICs from Wasm. Otherwise, Wasm will
+        // have no idea that we cleared the code from all of the Executables in the
+        // VM. This could leave Wasm in an inconsistent state where it has an IC that
+        // 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) {
+            ASSERT_UNUSED(kind, kind == HeapCell::Kind::JSCell);
+            JSWebAssemblyCodeBlock* codeBlock = static_cast<JSWebAssemblyCodeBlock*>(cell);
+            codeBlock->clearJSCallICs(*m_vm);
+        });
+    }
+#endif
 }
 
 void Heap::deleteAllUnlinkedCodeBlocks(DeleteAllCodeEffort effort)
index d95f71b..39f31e8 100644 (file)
@@ -79,6 +79,9 @@ public:
     
     template<typename Func>
     void forEachMarkedCell(const Func&);
+
+    template<typename Func>
+    void forEachLiveCell(const Func&);
     
     static ptrdiff_t offsetOfAllocatorForSizeStep() { return OBJECT_OFFSETOF(Subspace, m_allocatorForSizeStep); }
     
index b6851c3..e2fa4b5 100644 (file)
@@ -72,5 +72,23 @@ void Subspace::forEachMarkedCell(const Func& func)
         });
 }
 
+template<typename Func>
+void Subspace::forEachLiveCell(const Func& func)
+{
+    forEachMarkedBlock(
+        [&] (MarkedBlock::Handle* handle) {
+            handle->forEachLiveCell(
+                [&] (HeapCell* cell, HeapCell::Kind kind) -> IterationStatus { 
+                    func(cell, kind);
+                    return IterationStatus::Continue;
+                });
+        });
+    forEachLargeAllocation(
+        [&] (LargeAllocation* allocation) {
+            if (allocation->isLive())
+                func(allocation->cell(), m_attributes.cellKind);
+        });
+}
+
 } // namespace JSC
 
index 95325a4..c3fc541 100644 (file)
@@ -172,6 +172,9 @@ VM::VM(VMType vmType, HeapType heapType)
     , stringSpace("JSString", heap)
     , destructibleObjectSpace("JSDestructibleObject", heap)
     , segmentedVariableObjectSpace("JSSegmentedVariableObjectSpace", heap)
+#if ENABLE(WEBASSEMBLY)
+    , webAssemblyCodeBlockSpace("JSWebAssemblyCodeBlockSpace", heap)
+#endif
     , vmType(vmType)
     , clientData(0)
     , topVMEntryFrame(nullptr)
index f9840c8..178a3e2 100644 (file)
@@ -44,6 +44,7 @@
 #include "JSLock.h"
 #include "JSSegmentedVariableObjectSubspace.h"
 #include "JSStringSubspace.h"
+#include "JSWebAssemblyCodeBlockSubspace.h"
 #include "MacroAssemblerCodeRef.h"
 #include "Microtask.h"
 #include "NumericStrings.h"
@@ -295,6 +296,9 @@ public:
     JSStringSubspace stringSpace;
     JSDestructibleObjectSubspace destructibleObjectSpace;
     JSSegmentedVariableObjectSubspace segmentedVariableObjectSpace;
+#if ENABLE(WEBASSEMBLY)
+    JSWebAssemblyCodeBlockSubspace webAssemblyCodeBlockSpace;
+#endif
 
 #if ENABLE(DFG_JIT)
     std::unique_ptr<DFG::LongLivedState> dfgState;
index a38f482..5ba31ce 100644 (file)
@@ -79,6 +79,12 @@ bool JSWebAssemblyCodeBlock::isSafeToRun(JSWebAssemblyMemory* memory) const
     return m_codeBlock->isSafeToRun(memory->memory().mode());
 }
 
+void JSWebAssemblyCodeBlock::clearJSCallICs(VM& vm)
+{
+    for (auto iter = m_callLinkInfos.begin(); !!iter; ++iter)
+        (*iter)->unlink(vm);
+}
+
 void JSWebAssemblyCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
     JSWebAssemblyCodeBlock* thisObject = jsCast<JSWebAssemblyCodeBlock*>(cell);
index adb748b..ce7b995 100644 (file)
@@ -46,7 +46,7 @@ namespace Wasm {
 class Plan;
 }
 
-class JSWebAssemblyCodeBlock : public JSCell {
+class JSWebAssemblyCodeBlock final : public JSCell {
 public:
     typedef JSCell Base;
     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
@@ -57,6 +57,12 @@ public:
         return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
     }
 
+    template<typename CellType>
+    static Subspace* subspaceFor(VM& vm)
+    {
+        return &vm.webAssemblyCodeBlockSpace;
+    }
+
     unsigned functionImportCount() const { return m_codeBlock->functionImportCount(); }
     JSWebAssemblyModule* module() const { return m_module.get(); }
 
@@ -87,6 +93,8 @@ public:
 
     Wasm::CodeBlock& codeBlock() { return m_codeBlock.get(); }
 
+    void clearJSCallICs(VM&);
+
 private:
     JSWebAssemblyCodeBlock(VM&, Ref<Wasm::CodeBlock>&&, const Wasm::ModuleInformation&);
     DECLARE_EXPORT_INFO;
diff --git a/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlockSubspace.cpp b/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlockSubspace.cpp
new file mode 100644 (file)
index 0000000..a786ef0
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2017 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 "JSWebAssemblyCodeBlockSubspace.h"
+
+#if ENABLE(WEBASSEMBLY)
+
+#include "JSCInlines.h"
+#include "JSWebAssemblyCodeBlock.h"
+#include "MarkedBlockInlines.h"
+#include "SubspaceInlines.h"
+
+namespace JSC {
+
+namespace {
+
+struct DestroyFunc {
+    ALWAYS_INLINE void operator()(VM&, JSCell* cell) const
+    {
+        static_assert(std::is_final<JSWebAssemblyCodeBlock>::value, "Otherwise, this code would not be correct.");
+        JSWebAssemblyCodeBlock::info()->methodTable.destroy(cell);
+    }
+};
+
+} // anonymous namespace
+
+JSWebAssemblyCodeBlockSubspace::JSWebAssemblyCodeBlockSubspace(CString name, Heap& heap)
+    : Subspace(name, heap, AllocatorAttributes(NeedsDestruction, HeapCell::JSCell))
+{
+}
+
+JSWebAssemblyCodeBlockSubspace::~JSWebAssemblyCodeBlockSubspace()
+{
+}
+
+FreeList JSWebAssemblyCodeBlockSubspace::finishSweep(MarkedBlock::Handle& handle, MarkedBlock::Handle::SweepMode sweepMode)
+{
+    return handle.finishSweepKnowingSubspace(sweepMode, DestroyFunc());
+}
+
+void JSWebAssemblyCodeBlockSubspace::destroy(VM& vm, JSCell* cell)
+{
+    DestroyFunc()(vm, cell);
+}
+
+} // namespace JSC
+
+#endif // ENABLE(WEBASSEMBLY)
diff --git a/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlockSubspace.h b/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlockSubspace.h
new file mode 100644 (file)
index 0000000..8e24379
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 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
+
+#if ENABLE(WEBASSEMBLY)
+
+#include "Subspace.h"
+
+namespace JSC {
+
+class JSWebAssemblyCodeBlockSubspace : public Subspace {
+public:
+    JSWebAssemblyCodeBlockSubspace(CString name, Heap&);
+    virtual ~JSWebAssemblyCodeBlockSubspace();
+    
+    FreeList finishSweep(MarkedBlock::Handle&, MarkedBlock::Handle::SweepMode) override;
+    void destroy(VM&, JSCell*) override;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(WEBASSEMBLY)