Put the ScopedArgumentsTable's ScopeOffset array in some gigacage
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 Aug 2017 18:33:16 +0000 (18:33 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 Aug 2017 18:33:16 +0000 (18:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=174921

Reviewed by Mark Lam.

Source/JavaScriptCore:

Uses CagedUniquePtr<> to cage the ScopeOffset array.

* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileGetByValOnScopedArguments):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emitScopedArgumentsGetByVal):
* runtime/ScopedArgumentsTable.cpp:
(JSC::ScopedArgumentsTable::create):
(JSC::ScopedArgumentsTable::setLength):
* runtime/ScopedArgumentsTable.h:

Source/WTF:

If you want to std::unique_ptr a class that knows that it should be in the Gigacage, then we
would create the Gigacage equivalent of WTF_MAKE_FAST_ALLOCATED and it would just work.

But this does not work if we want to std::unique_ptr a primitive type. So, this patch adds a
solution for this problem: CagedUniquePtr<>. This will handle allocation
(CagedUniquePtr<>::create()) and deallocation (in the style of std::unique_ptr). It has three
variants:

- Non-array types.
- Arrays that don't have destructors.
- Arrays that have destructors.

Just like std::unique_ptr, the array case is triggered by saying "[]" at the end of the type.

Unlike std::unique_ptr and most other smart pointers, the whole point of this smart pointer is
to dictate where the thing you're pointing at is allocated. For this reason, it has to know how
to do things like the array destructor protocol. So it creates its own: the CagedUniquePtr for
arrays with destructors is a fat pointer that remembers the length of the array.

CagedUniquePtr<> makes it impossible to leak/release the pointer. This is stricter than what
std::unique_ptr does, and is probably appropriate for all of the places where we would use this
type.

So far, we only use it for ScopedArgumentsTable::m_arguments, but I suspect that it will be
useful in other places.

* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/CagedUniquePtr.h: Added.
(WTF::CagedUniquePtr::CagedUniquePtr):
(WTF::CagedUniquePtr::create):
(WTF::CagedUniquePtr::operator=):
(WTF::CagedUniquePtr::~CagedUniquePtr):
(WTF::CagedUniquePtr::get const):
(WTF::CagedUniquePtr::getMayBeNull const):
(WTF::CagedUniquePtr::operator== const):
(WTF::CagedUniquePtr::operator!= const):
(WTF::CagedUniquePtr::operator bool const):
(WTF::CagedUniquePtr::operator* const):
(WTF::CagedUniquePtr::operator-> const):
(WTF::CagedUniquePtr::operator[] const):
(WTF::CagedUniquePtr::destroy):
* wtf/Gigacage.cpp:
(Gigacage::tryMallocArray):
(Gigacage::malloc):
(Gigacage::mallocArray):
* wtf/Gigacage.h:

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

13 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/jit/JITPropertyAccess.cpp
Source/JavaScriptCore/runtime/ScopedArgumentsTable.cpp
Source/JavaScriptCore/runtime/ScopedArgumentsTable.h
Source/WTF/ChangeLog
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/CMakeLists.txt
Source/WTF/wtf/CagedPtr.h
Source/WTF/wtf/CagedUniquePtr.h [new file with mode: 0644]
Source/WTF/wtf/Gigacage.cpp
Source/WTF/wtf/Gigacage.h

index 5ea19f3d5dae25b7d4416e278940abb65628b056..1f6f514c6c02cae2976d94bb27026b9efdbdab61 100644 (file)
@@ -1,3 +1,23 @@
+2017-08-12  Filip Pizlo  <fpizlo@apple.com>
+
+        Put the ScopedArgumentsTable's ScopeOffset array in some gigacage
+        https://bugs.webkit.org/show_bug.cgi?id=174921
+
+        Reviewed by Mark Lam.
+        
+        Uses CagedUniquePtr<> to cage the ScopeOffset array.
+
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileGetByValOnScopedArguments):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emitScopedArgumentsGetByVal):
+        * runtime/ScopedArgumentsTable.cpp:
+        (JSC::ScopedArgumentsTable::create):
+        (JSC::ScopedArgumentsTable::setLength):
+        * runtime/ScopedArgumentsTable.h:
+
 2017-08-14  Mark Lam  <mark.lam@apple.com>
 
         Gardening: fix Windows build.
index 08d4329f40ea7475957d65b90a01f5463fc970cc..9618252e4417ed58a363748496ac8119ae1f9f8f 100644 (file)
@@ -6304,6 +6304,7 @@ void SpeculativeJIT::compileGetByValOnScopedArguments(Node* node)
     m_jit.loadPtr(
         MacroAssembler::Address(scratchReg, ScopedArgumentsTable::offsetOfArguments()),
         scratchReg);
+    m_jit.cage(ScopedArgumentsTable::ArgumentsPtr::kind, scratchReg);
     m_jit.load32(
         MacroAssembler::BaseIndex(scratchReg, propertyReg, MacroAssembler::TimesFour),
         scratchReg);
index 8349c5e0ff07fb0b4cfc003b6e82994ef790f8c3..5d52118d8499a532410ed9751c20db9e7514b282 100644 (file)
@@ -3547,10 +3547,10 @@ private:
             LBasicBlock lastNext = m_out.appendTo(namedCase, overflowCase);
             
             LValue scope = m_out.loadPtr(base, m_heaps.ScopedArguments_scope);
-            LValue arguments = m_out.loadPtr(table, m_heaps.ScopedArgumentsTable_arguments);
+            LValue arguments = caged(
+                ScopedArgumentsTable::ArgumentsPtr::kind,
+                m_out.loadPtr(table, m_heaps.ScopedArgumentsTable_arguments));
             
-            // FIXME: I guess we need to cage ScopedArguments?
-            // https://bugs.webkit.org/show_bug.cgi?id=174921
             TypedPointer address = m_out.baseIndex(
                 m_heaps.scopedArgumentsTableArguments, arguments, m_out.zeroExtPtr(index));
             LValue scopeOffset = m_out.load32(address);
index e261978457eb665d2dca3fb4ff124da1c8cc3f8f..0052e6b7d9716eee2bc21ea743d57db3ff18cdb0 100644 (file)
@@ -1544,6 +1544,7 @@ JIT::JumpList JIT::emitScopedArgumentsGetByVal(Instruction*, PatchableJump& badT
     Jump overflowCase = branch32(AboveOrEqual, property, scratch2);
     loadPtr(Address(base, ScopedArguments::offsetOfScope()), scratch2);
     loadPtr(Address(scratch, ScopedArgumentsTable::offsetOfArguments()), scratch);
+    cage(ScopedArgumentsTable::ArgumentsPtr::kind, scratch);
     load32(BaseIndex(scratch, property, TimesFour), scratch);
     slowCases.append(branch32(Equal, scratch, TrustedImm32(ScopeOffset::invalidOffset)));
     loadValue(BaseIndex(scratch2, scratch, TimesEight, JSEnvironmentRecord::offsetOfVariables()), result);
index a6d45e427d34a0b7a50e94d420326bcdf17c6d3f..955a307d23e1669efba4c03229ee1e52c7604d15 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-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
@@ -60,7 +60,7 @@ ScopedArgumentsTable* ScopedArgumentsTable::create(VM& vm, uint32_t length)
 {
     ScopedArgumentsTable* result = create(vm);
     result->m_length = length;
-    result->m_arguments = std::make_unique<ScopeOffset[]>(length);
+    result->m_arguments = ArgumentsPtr::create(length);
     return result;
 }
 
@@ -75,7 +75,7 @@ ScopedArgumentsTable* ScopedArgumentsTable::clone(VM& vm)
 ScopedArgumentsTable* ScopedArgumentsTable::setLength(VM& vm, uint32_t newLength)
 {
     if (LIKELY(!m_locked)) {
-        std::unique_ptr<ScopeOffset[]> newArguments = std::make_unique<ScopeOffset[]>(newLength);
+        ArgumentsPtr newArguments = ArgumentsPtr::create(newLength);
         for (unsigned i = std::min(m_length, newLength); i--;)
             newArguments[i] = m_arguments[i];
         m_length = newLength;
index ba1a122ec239477522eb98d7bade53ff19326d2e..7c7207b605f4989b08e360128595ab90a918c275 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-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
@@ -28,6 +28,7 @@
 #include "JSCell.h"
 #include "ScopeOffset.h"
 #include <wtf/Assertions.h>
+#include <wtf/CagedUniquePtr.h>
 
 namespace JSC {
 
@@ -77,6 +78,8 @@ public:
     static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(ScopedArgumentsTable, m_length); }
     static ptrdiff_t offsetOfArguments() { return OBJECT_OFFSETOF(ScopedArgumentsTable, m_arguments); }
 
+    typedef CagedUniquePtr<Gigacage::Primitive, ScopeOffset[]> ArgumentsPtr;
+
 private:
     ScopeOffset& at(uint32_t i)
     {
@@ -86,9 +89,7 @@ private:
     
     uint32_t m_length;
     bool m_locked; // Being locked means that there are multiple references to this object and none of them expect to see the others' modifications. This means that modifications need to make a copy first.
-    // FIXME: Allocate this in the primitive gigacage
-    // https://bugs.webkit.org/show_bug.cgi?id=174921
-    std::unique_ptr<ScopeOffset[]> m_arguments;
+    ArgumentsPtr m_arguments;
 };
 
 } // namespace JSC
index ffe4dd9f0a64726ed5413ba107acae06ba20ddfb..0bf124c226cb1067d6a67b78335b5093a7a3d7f3 100644 (file)
@@ -1,3 +1,58 @@
+2017-08-12  Filip Pizlo  <fpizlo@apple.com>
+
+        Put the ScopedArgumentsTable's ScopeOffset array in some gigacage
+        https://bugs.webkit.org/show_bug.cgi?id=174921
+
+        Reviewed by Mark Lam.
+        
+        If you want to std::unique_ptr a class that knows that it should be in the Gigacage, then we
+        would create the Gigacage equivalent of WTF_MAKE_FAST_ALLOCATED and it would just work.
+        
+        But this does not work if we want to std::unique_ptr a primitive type. So, this patch adds a
+        solution for this problem: CagedUniquePtr<>. This will handle allocation
+        (CagedUniquePtr<>::create()) and deallocation (in the style of std::unique_ptr). It has three
+        variants:
+        
+        - Non-array types.
+        - Arrays that don't have destructors.
+        - Arrays that have destructors.
+        
+        Just like std::unique_ptr, the array case is triggered by saying "[]" at the end of the type.
+        
+        Unlike std::unique_ptr and most other smart pointers, the whole point of this smart pointer is
+        to dictate where the thing you're pointing at is allocated. For this reason, it has to know how
+        to do things like the array destructor protocol. So it creates its own: the CagedUniquePtr for
+        arrays with destructors is a fat pointer that remembers the length of the array.
+        
+        CagedUniquePtr<> makes it impossible to leak/release the pointer. This is stricter than what
+        std::unique_ptr does, and is probably appropriate for all of the places where we would use this
+        type.
+        
+        So far, we only use it for ScopedArgumentsTable::m_arguments, but I suspect that it will be
+        useful in other places.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CMakeLists.txt:
+        * wtf/CagedUniquePtr.h: Added.
+        (WTF::CagedUniquePtr::CagedUniquePtr):
+        (WTF::CagedUniquePtr::create):
+        (WTF::CagedUniquePtr::operator=):
+        (WTF::CagedUniquePtr::~CagedUniquePtr):
+        (WTF::CagedUniquePtr::get const):
+        (WTF::CagedUniquePtr::getMayBeNull const):
+        (WTF::CagedUniquePtr::operator== const):
+        (WTF::CagedUniquePtr::operator!= const):
+        (WTF::CagedUniquePtr::operator bool const):
+        (WTF::CagedUniquePtr::operator* const):
+        (WTF::CagedUniquePtr::operator-> const):
+        (WTF::CagedUniquePtr::operator[] const):
+        (WTF::CagedUniquePtr::destroy):
+        * wtf/Gigacage.cpp:
+        (Gigacage::tryMallocArray):
+        (Gigacage::malloc):
+        (Gigacage::mallocArray):
+        * wtf/Gigacage.h:
+
 2017-08-11  Ryosuke Niwa  <rniwa@webkit.org>
 
         Replace DATA_TRANSFER_ITEMS by a runtime flag and add a stub implementation
index 06bb3d1088e493cd9aff606a2e35566a65f7d99c..4317b452dcab9712fbc4ad53f2cd85ef8086cf78 100644 (file)
                0F5BF1651F2317830029D91D /* NaturalLoops.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NaturalLoops.h; sourceTree = "<group>"; };
                0F5BF1741F23D49A0029D91D /* Gigacage.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Gigacage.cpp; sourceTree = "<group>"; };
                0F5BF1751F23D49A0029D91D /* Gigacage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Gigacage.h; sourceTree = "<group>"; };
+               0F5F3D681F3FEBA600B115A2 /* CagedUniquePtr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CagedUniquePtr.h; sourceTree = "<group>"; };
                0F60F32D1DFCBD1B00416D6C /* LockedPrintStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LockedPrintStream.cpp; sourceTree = "<group>"; };
                0F60F32E1DFCBD1B00416D6C /* LockedPrintStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LockedPrintStream.h; sourceTree = "<group>"; };
                0F66B2801DC97BAB004A1D3F /* ClockType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClockType.cpp; sourceTree = "<group>"; };
                                A8A47267151A825A004123FF /* BumpPointerAllocator.h */,
                                EB95E1EF161A72410089A2F5 /* ByteOrder.h */,
                                0FEC3C4F1F323C6800F59B6C /* CagedPtr.h */,
+                               0F5F3D681F3FEBA600B115A2 /* CagedUniquePtr.h */,
                                A8A4726A151A825A004123FF /* CheckedArithmetic.h */,
                                A8A4726B151A825A004123FF /* CheckedBoolean.h */,
                                0F66B2801DC97BAB004A1D3F /* ClockType.cpp */,
index 4f92d548199f0da338b6bb53a61988d9f56c1d7b..30d4fa9f01a08db53d804e7eb4458e3793001015 100644 (file)
@@ -14,6 +14,7 @@ set(WTF_HEADERS
     ByteOrder.h
     CPUTime.h
     CagedPtr.h
+    CagedUniquePtr.h
     ClockType.h
     CompilationThread.h
     Compiler.h
index 031a69413ce09b2b6cae58c771f7a3aad2ed5fb3..6e00abe9df56f66a2fbd05a14342f57dc7f552a0 100644 (file)
@@ -73,7 +73,7 @@ public:
     template<typename IndexType>
     T& operator[](IndexType index) const { return get()[index]; }
     
-private:
+protected:
     T* m_ptr;
 };
 
diff --git a/Source/WTF/wtf/CagedUniquePtr.h b/Source/WTF/wtf/CagedUniquePtr.h
new file mode 100644 (file)
index 0000000..4aae287
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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 <wtf/CagedPtr.h>
+
+namespace WTF {
+
+template<Gigacage::Kind kind, typename T, typename Enable = void>
+class CagedUniquePtr : public CagedPtr<kind, T> {
+public:
+    CagedUniquePtr(T* ptr = nullptr)
+        : CagedPtr<kind, T>(ptr)
+    {
+    }
+    
+    CagedUniquePtr(CagedUniquePtr&& ptr)
+        : CagedPtr<kind, T>(ptr.m_ptr)
+    {
+        ptr.m_ptr = nullptr;
+    }
+    
+    CagedUniquePtr(const CagedUniquePtr&) = delete;
+    
+    template<typename... Arguments>
+    static CagedUniquePtr create(Arguments&&... arguments)
+    {
+        T* result = static_cast<T*>(Gigacage::malloc(kind, sizeof(T)));
+        new (result) T(std::forward<Arguments>(arguments)...);
+        return CagedUniquePtr(result);
+    }
+    
+    CagedUniquePtr& operator=(CagedUniquePtr&& ptr)
+    {
+        destroy();
+        this->m_ptr = ptr.m_ptr;
+        ptr.m_ptr = nullptr;
+        return *this;
+    }
+    
+    CagedUniquePtr& operator=(const CagedUniquePtr&) = delete;
+    
+    ~CagedUniquePtr()
+    {
+        destroy();
+    }
+    
+private:
+    void destroy()
+    {
+        if (!this->m_ptr)
+            return;
+        this->m_ptr->~T();
+        Gigacage::free(kind, this->m_ptr);
+    }
+};
+
+template<Gigacage::Kind kind, typename T>
+class CagedUniquePtr<kind, T[], typename std::enable_if<std::is_trivially_destructible<T>::value>::type> : public CagedPtr<kind, T> {
+public:
+    CagedUniquePtr() : CagedPtr<kind, T>() { }
+    
+    CagedUniquePtr(T* ptr)
+        : CagedPtr<kind, T>(ptr)
+    {
+    }
+    
+    CagedUniquePtr(CagedUniquePtr&& ptr)
+        : CagedPtr<kind, T>(ptr.m_ptr)
+    {
+        ptr.m_ptr = nullptr;
+    }
+    
+    CagedUniquePtr(const CagedUniquePtr&) = delete;
+    
+    template<typename... Arguments>
+    static CagedUniquePtr create(size_t count, Arguments&&... arguments)
+    {
+        T* result = static_cast<T*>(Gigacage::mallocArray(kind, count, sizeof(T)));
+        while (count--)
+            new (result + count) T(std::forward<Arguments>(arguments)...);
+        return CagedUniquePtr(result);
+    }
+    
+    CagedUniquePtr& operator=(CagedUniquePtr&& ptr)
+    {
+        destroy();
+        this->m_ptr = ptr.m_ptr;
+        ptr.m_ptr = nullptr;
+        return *this;
+    }
+    
+    CagedUniquePtr& operator=(const CagedUniquePtr&) = delete;
+    
+    ~CagedUniquePtr()
+    {
+        destroy();
+    }
+    
+private:
+    void destroy()
+    {
+        if (!this->m_ptr)
+            return;
+        Gigacage::free(kind, this->m_ptr);
+    }
+};
+
+template<Gigacage::Kind kind, typename T>
+class CagedUniquePtr<kind, T[], typename std::enable_if<!std::is_trivially_destructible<T>::value>::type> : public CagedPtr<kind, T> {
+public:
+    CagedUniquePtr() : CagedPtr<kind, T>() { }
+    
+    CagedUniquePtr(T* ptr, size_t count)
+        : CagedPtr<kind, T>(ptr)
+        , m_count(count)
+    {
+    }
+    
+    CagedUniquePtr(CagedUniquePtr&& ptr)
+        : CagedPtr<kind, T>(ptr.m_ptr)
+        , m_count(ptr.m_count)
+    {
+        ptr.clear();
+    }
+    
+    CagedUniquePtr(const CagedUniquePtr&) = delete;
+    
+    template<typename... Arguments>
+    static CagedUniquePtr create(size_t count, Arguments&&... arguments)
+    {
+        T* result = static_cast<T*>(Gigacage::mallocArray(kind, count, sizeof(T)));
+        while (count--)
+            new (result + count) T(std::forward<Arguments>(arguments)...);
+        return CagedUniquePtr(result, count);
+    }
+    
+    CagedUniquePtr& operator=(CagedUniquePtr&& ptr)
+    {
+        destroy();
+        this->m_ptr = ptr.m_ptr;
+        m_count = ptr.m_count;
+        ptr.clear();
+        return *this;
+    }
+    
+    CagedUniquePtr& operator=(const CagedUniquePtr&) = delete;
+    
+    ~CagedUniquePtr()
+    {
+        destroy();
+    }
+    
+    // FIXME: It's weird that we inherit CagedPtr::operator== and friends, which don't do anything
+    // about m_count. It "works" because pointer equality is enough so long as everything is sane, but
+    // it seems like a missed opportunity to assert things.
+    // https://bugs.webkit.org/show_bug.cgi?id=175541
+    
+private:
+    void destroy()
+    {
+        if (!this->m_ptr)
+            return;
+        while (m_count--)
+            this->m_ptr[m_count].~T();
+        Gigacage::free(kind, this->m_ptr);
+    }
+    
+    void clear()
+    {
+        this->m_ptr = nullptr;
+        m_count = 0;
+    }
+    
+    size_t m_count { 0 };
+};
+
+} // namespace WTF
+
+using WTF::CagedUniquePtr;
+
index 3e7010701e685f95109a6a48c335b79b63368cad..d3401c34370c5560a315e4e583dec3aaa9726275 100644 (file)
@@ -118,3 +118,30 @@ void freeVirtualPages(Kind kind, void* basePtr, size_t)
 } // namespace Gigacage
 #endif
 
+namespace Gigacage {
+
+void* tryMallocArray(Kind kind, size_t numElements, size_t elementSize)
+{
+    Checked<size_t, RecordOverflow> checkedSize = elementSize;
+    checkedSize *= numElements;
+    if (checkedSize.hasOverflowed())
+        return nullptr;
+    return tryMalloc(kind, checkedSize.unsafeGet());
+}
+
+void* malloc(Kind kind, size_t size)
+{
+    void* result = tryMalloc(kind, size);
+    RELEASE_ASSERT(result);
+    return result;
+}
+
+void* mallocArray(Kind kind, size_t numElements, size_t elementSize)
+{
+    void* result = tryMallocArray(kind, numElements, elementSize);
+    RELEASE_ASSERT(result);
+    return result;
+}
+
+} // namespace Gigacage
+
index c2ba92997a90bae0f37faff0b8a043b684a1e6c1..7aa8ae6873519b4af83e691456f2a78f3406614a 100644 (file)
@@ -102,3 +102,13 @@ WTF_EXPORT_PRIVATE void freeVirtualPages(Kind, void* basePtr, size_t size);
 } // namespace Gigacage
 #endif
 
+namespace Gigacage {
+
+WTF_EXPORT_PRIVATE void* tryMallocArray(Kind, size_t numElements, size_t elementSize);
+
+WTF_EXPORT_PRIVATE void* malloc(Kind, size_t);
+WTF_EXPORT_PRIVATE void* mallocArray(Kind, size_t numElements, size_t elementSize);
+
+} // namespace Gigacage
+
+