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 5ea19f3..1f6f514 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 08d4329..9618252 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 8349c5e..5d52118 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 e261978..0052e6b 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 a6d45e4..955a307 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 ba1a122..7c7207b 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 ffe4dd9..0bf124c 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 06bb3d1..4317b45 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 4f92d54..30d4fa9 100644 (file)
@@ -14,6 +14,7 @@ set(WTF_HEADERS
     ByteOrder.h
     CPUTime.h
     CagedPtr.h
+    CagedUniquePtr.h
     ClockType.h
     CompilationThread.h
     Compiler.h
index 031a694..6e00abe 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 3e70107..d3401c3 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 c2ba929..7aa8ae6 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
+
+