Bug 1280578 - Wrap HeapAlloc, HeapFree and HeapReAlloc on Windows. r=njn
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 19 Jul 2016 09:45:26 +0900
changeset 330848 87c0b92cae4244ff7f0156f1fc90cb161f9243e9
parent 330847 8c0991c44fdeca661c7d1d7058b68bda209acafd
child 330849 0a822e7f78cbb140a6172b134ba05b4c0a83e6e4
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs1280578
milestone50.0a1
Bug 1280578 - Wrap HeapAlloc, HeapFree and HeapReAlloc on Windows. r=njn The Win32 has non-malloc based heap allocation functions. They are not widely used in the Gecko code base, but there are a few places that do use them. They could be replaced with uses of malloc/free/realloc or new/delete, but there is now an entirely separate problem that requires wrapping those functions: the Rust static libraries are using those functions to allocate memory.
memory/mozalloc/moz.build
memory/mozalloc/staticruntime/moz.build
memory/mozalloc/winheap.cpp
--- a/memory/mozalloc/moz.build
+++ b/memory/mozalloc/moz.build
@@ -20,16 +20,22 @@ if CONFIG['WRAP_STL_INCLUDES']:
             EXPORTS.mozilla += [
                 'msvc_raise_wrappers.h',
                 'throw_msvc.h',
             ]
             SOURCES += [
                 'msvc_raise_wrappers.cpp',
             ]
 
+if CONFIG['OS_TARGET'] == 'WINNT':
+    # Keep this file separate to avoid #include'ing windows.h everywhere.
+    SOURCES += [
+        'winheap.cpp',
+    ]
+
 UNIFIED_SOURCES += [
     'mozalloc.cpp',
     'mozalloc_abort.cpp',
     'mozalloc_oom.cpp',
 ]
 
 FINAL_LIBRARY = 'mozglue'
 
--- a/memory/mozalloc/staticruntime/moz.build
+++ b/memory/mozalloc/staticruntime/moz.build
@@ -14,16 +14,21 @@ if CONFIG['WRAP_STL_INCLUDES']:
         ]
 
 UNIFIED_SOURCES += [
     '../mozalloc.cpp',
     '../mozalloc_abort.cpp',
     '../mozalloc_oom.cpp',
 ]
 
+# Keep this file separate to avoid #include'ing windows.h everywhere.
+SOURCES += [
+    '../winheap.cpp',
+]
+
 LOCAL_INCLUDES += ['!/xpcom']
 
 DISABLE_STL_WRAPPING = True
 
 DEFINES['IMPL_MFBT'] = True
 
 USE_STATIC_LIBS = True
 
new file mode 100644
--- /dev/null
+++ b/memory/mozalloc/winheap.cpp
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: sw=4 ts=4 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/Types.h"
+#include <windows.h>
+
+// Building with USE_STATIC_LIBS = True sets -MT instead of -MD. -MT sets _MT,
+// while -MD sets _MT and _DLL.
+#if defined(_MT) && !defined(_DLL)
+#define MOZ_STATIC_RUNTIME
+#endif
+
+#if defined(MOZ_MEMORY) && !defined(MOZ_STATIC_RUNTIME)
+// mozalloc.cpp is part of the same library as mozmemory, thus MOZ_MEMORY_IMPL
+// is needed.
+#define MOZ_MEMORY_IMPL
+#include "mozmemory_wrap.h"
+
+// See mozmemory_wrap.h for more details. This file is part of libmozglue, so
+// it needs to use _impl suffixes. However, with libmozglue growing, this is
+// becoming cumbersome, so we will likely use a malloc.h wrapper of some sort
+// and allow the use of the functions without a _impl suffix.
+#define MALLOC_DECL(name, return_type, ...) \
+  extern "C" MOZ_MEMORY_API return_type name ## _impl(__VA_ARGS__);
+#define MALLOC_FUNS MALLOC_FUNCS_MALLOC
+#include "malloc_decls.h"
+
+// Warning: C4273: 'HeapAlloc': inconsistent dll linkage
+// The Windows headers define HeapAlloc as dllimport, but we define it as
+// dllexport, which is a voluntary inconsistency.
+#pragma warning(disable: 4273)
+
+MFBT_API
+LPVOID WINAPI HeapAlloc(_In_ HANDLE hHeap, _In_ DWORD dwFlags,
+                        _In_ SIZE_T dwBytes)
+{
+    if (dwFlags & HEAP_ZERO_MEMORY) {
+        return calloc_impl(1, dwBytes);
+    }
+    return malloc_impl(dwBytes);
+}
+
+MFBT_API
+LPVOID WINAPI HeapReAlloc(_In_ HANDLE hHeap, _In_ DWORD dwFlags,
+                          _In_ LPVOID lpMem, _In_ SIZE_T dwBytes)
+{
+    // The HeapReAlloc contract is that failures preserve the existing
+    // allocation. We can't try to realloc in-place without possibly
+    // freeing the original allocation, breaking the contract.
+    // We also can't guarantee we zero all the memory from the end of
+    // the original allocation to the end of the new one because of the
+    // difference between the originally requested size and what
+    // malloc_usable_size would return us.
+    // So for both cases, just tell the caller we can't do what they
+    // requested.
+    if (dwFlags & (HEAP_REALLOC_IN_PLACE_ONLY | HEAP_ZERO_MEMORY)) {
+        return NULL;
+    }
+    return realloc_impl(lpMem, dwBytes);
+}
+
+MFBT_API
+BOOL WINAPI HeapFree(_In_ HANDLE hHeap, _In_ DWORD dwFlags,
+                     _In_ LPVOID lpMem)
+{
+    free_impl(lpMem);
+    return true;
+}
+
+#endif