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 345814 87c0b92cae4244ff7f0156f1fc90cb161f9243e9
parent 345813 8c0991c44fdeca661c7d1d7058b68bda209acafd
child 345815 0a822e7f78cbb140a6172b134ba05b4c0a83e6e4
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs1280578
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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