Commit 25da2dbf authored by siggi's avatar siggi Committed by Commit bot

Start refactoring Windows allocator shim in prep for hooking in generic allocator shim on Windows.

BUG=550886

Review-Url: https://codereview.chromium.org/2143693003
Cr-Commit-Position: refs/heads/master@{#405984}
parent 1ce44d25
......@@ -1986,6 +1986,7 @@ test("base_unittests") {
":base",
":i18n",
":message_loop_tests",
"//base/allocator:features",
"//base/test:run_all_unittests",
"//base/test:test_support",
"//base/third_party/dynamic_annotations",
......
......@@ -93,6 +93,8 @@ if (win_use_allocator_shim) {
sources = [
"allocator_shim_win.cc",
"allocator_shim_win.h",
"winheap_stubs_win.cc",
"winheap_stubs_win.h",
]
configs += [ ":allocator_shim_define" ]
}
......@@ -276,7 +278,10 @@ if (use_allocator == "tcmalloc") {
buildflag_header("features") {
header = "features.h"
flags = [ "USE_EXPERIMENTAL_ALLOCATOR_SHIM=$use_experimental_allocator_shim" ]
flags = [
"USE_EXPERIMENTAL_ALLOCATOR_SHIM=$use_experimental_allocator_shim",
"ENABLE_WIN_ALLOCATOR_SHIM_TESTS=($use_experimental_allocator_shim || $win_use_allocator_shim)",
]
}
if (use_experimental_allocator_shim) {
......
......@@ -55,6 +55,8 @@
'sources': [
'allocator_shim_win.cc',
'allocator_shim_win.h',
'winheap_stubs_win.cc',
'winheap_stubs_win.h',
],
'configurations': {
'Debug_Base': {
......@@ -387,6 +389,12 @@
'buildflag_flags': [
'USE_EXPERIMENTAL_ALLOCATOR_SHIM=<(use_experimental_allocator_shim)',
],
'conditions': [
['<(use_experimental_allocator_shim) or <(win_use_allocator_shim)',
{'buildflag_flags': [ 'ENABLE_WIN_ALLOCATOR_SHIM_TESTS=1' ],},
{'buildflag_flags': [ 'ENABLE_WIN_ALLOCATOR_SHIM_TESTS=0' ],}
],
],
},
}, # 'allocator_features' target.
], # targets.
......
......@@ -6,6 +6,7 @@
// This #if is needed as gyp can't have different compile
// targets between Debug and Release.
// TODO(wfh): Remove this once gyp is dead.
// TODO(siggi): Remove this file once the generic shim sticks.
#if defined(ALLOCATOR_SHIM)
#include <limits.h>
......@@ -14,7 +15,8 @@
#include <windows.h>
#include <stddef.h>
#include "allocator_shim_win.h"
#include "base/allocator/allocator_shim_win.h"
#include "base/allocator/winheap_stubs_win.h"
// This shim make it possible to perform additional checks on allocations
// before passing them to the Heap functions.
......@@ -26,66 +28,16 @@
// See definitions of original functions in ucrt\corecrt_malloc.h in SDK
// include directory.
namespace base {
namespace allocator {
bool g_is_win_shim_layer_initialized = false;
} // namespace allocator
} // namespace base
namespace {
const size_t kWindowsPageSize = 4096;
const size_t kMaxWindowsAllocation = INT_MAX - kWindowsPageSize;
int new_mode = 0;
inline HANDLE get_heap_handle() {
return reinterpret_cast<HANDLE>(_get_heap_handle());
}
void* win_heap_malloc(size_t size) {
if (size < kMaxWindowsAllocation)
return HeapAlloc(get_heap_handle(), 0, size);
return nullptr;
}
void win_heap_free(void* size) {
HeapFree(get_heap_handle(), 0, size);
}
void* win_heap_realloc(void* ptr, size_t size) {
if (!ptr)
return win_heap_malloc(size);
if (!size) {
win_heap_free(ptr);
return nullptr;
}
if (size < kMaxWindowsAllocation)
return HeapReAlloc(get_heap_handle(), 0, ptr, size);
return nullptr;
}
// Call the new handler, if one has been set.
// Returns true on successfully calling the handler, false otherwise.
inline bool call_new_handler(bool nothrow, size_t size) {
// Get the current new handler.
_PNH nh = _query_new_handler();
#if defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
if (!nh)
return false;
// Since exceptions are disabled, we don't really know if new_handler
// failed. Assume it will abort if it fails.
return nh(size) ? true : false;
#else
#error "Exceptions in allocator shim are not supported!"
#endif // defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
}
} // namespace
extern "C" {
// Symbol to allow weak linkage to win_heap_malloc from memory_win.cc.
void* (*malloc_unchecked)(size_t) = &win_heap_malloc;
// Symbol to allow weak linkage to WinHeapMalloc from allocator_impl_win.cc.
void* (*malloc_unchecked)(size_t) = &base::allocator::WinHeapMalloc;
// This function behaves similarly to MSVC's _set_new_mode.
// If flag is 0 (default), calls to malloc will behave normally.
......@@ -100,6 +52,7 @@ int _set_new_mode(int flag) {
base::allocator::g_is_win_shim_layer_initialized = true;
int old_mode = new_mode;
new_mode = flag;
return old_mode;
}
......@@ -112,11 +65,11 @@ int _query_new_mode() {
__declspec(restrict) void* malloc(size_t size) {
void* ptr;
for (;;) {
ptr = win_heap_malloc(size);
ptr = base::allocator::WinHeapMalloc(size);
if (ptr)
return ptr;
if (!new_mode || !call_new_handler(true, size))
if (!new_mode || base::allocator::WinCallNewHandler(size))
break;
}
return ptr;
......@@ -124,7 +77,7 @@ __declspec(restrict) void* malloc(size_t size) {
// Replaces free in ucrt\heap\free.cpp
void free(void* p) {
win_heap_free(p);
base::allocator::WinHeapFree(p);
return;
}
......@@ -138,14 +91,14 @@ __declspec(restrict) void* realloc(void* ptr, size_t size) {
void* new_ptr;
for (;;) {
new_ptr = win_heap_realloc(ptr, size);
new_ptr = base::allocator::WinHeapRealloc(ptr, size);
// Subtle warning: NULL return does not alwas indicate out-of-memory. If
// the requested new size is zero, realloc should free the ptr and return
// NULL.
if (new_ptr || !size)
return new_ptr;
if (!new_mode || !call_new_handler(true, size))
if (!new_mode || !base::allocator::WinCallNewHandler(size))
break;
}
return new_ptr;
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This code should move into the default Windows shim once the win-specific
// allocation shim has been removed, and the generic shim has becaome the
// default.
#include "winheap_stubs_win.h"
#include <limits.h>
#include <malloc.h>
#include <new.h>
#include <windows.h>
namespace base {
namespace allocator {
bool g_is_win_shim_layer_initialized = false;
namespace {
const size_t kWindowsPageSize = 4096;
const size_t kMaxWindowsAllocation = INT_MAX - kWindowsPageSize;
inline HANDLE get_heap_handle() {
return reinterpret_cast<HANDLE>(_get_heap_handle());
}
} // namespace
void* WinHeapMalloc(size_t size) {
if (size < kMaxWindowsAllocation)
return HeapAlloc(get_heap_handle(), 0, size);
return nullptr;
}
void WinHeapFree(void* size) {
HeapFree(get_heap_handle(), 0, size);
}
void* WinHeapRealloc(void* ptr, size_t size) {
if (!ptr)
return WinHeapMalloc(size);
if (!size) {
WinHeapFree(ptr);
return nullptr;
}
if (size < kMaxWindowsAllocation)
return HeapReAlloc(get_heap_handle(), 0, ptr, size);
return nullptr;
}
// Call the new handler, if one has been set.
// Returns true on successfully calling the handler, false otherwise.
bool WinCallNewHandler(size_t size) {
#if !defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS
#error "Exceptions in allocator shim are not supported!"
#endif // defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
// Get the current new handler.
_PNH nh = _query_new_handler();
if (!nh)
return false;
// Since exceptions are disabled, we don't really know if new_handler
// failed. Assume it will abort if it fails.
return nh(size) ? true : false;
}
} // namespace allocator
} // namespace base
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Thin allocation wrappers for the windows heap. This file should be deleted
// once the win-specific allocation shim has been removed, and the generic shim
// has becaome the default.
#ifndef BASE_ALLOCATOR_WINHEAP_STUBS_H_
#define BASE_ALLOCATOR_WINHEAP_STUBS_H_
#include <stdint.h>
namespace base {
namespace allocator {
// Set to true if the link-time magic has successfully hooked into the CRT's
// heap initialization.
extern bool g_is_win_shim_layer_initialized;
// Thin wrappers to implement the standard C allocation semantics on the
// CRT's Windows heap.
void* WinHeapMalloc(size_t size);
void WinHeapFree(void* size);
void* WinHeapRealloc(void* ptr, size_t size);
// Call the new handler, if one has been set.
// Returns true on successfully calling the handler, false otherwise.
bool WinCallNewHandler(size_t size);
} // namespace allocator
} // namespace base
#endif // BASE_ALLOCATOR_WINHEAP_STUBS_H_
\ No newline at end of file
......@@ -621,6 +621,7 @@
'<@(trace_event_test_sources)',
],
'dependencies': [
'allocator/allocator.gyp:allocator_features#target',
'base',
'base_i18n',
'base_message_loop_tests',
......
......@@ -11,6 +11,7 @@
#include <limits>
#include "base/allocator/allocator_check.h"
#include "base/allocator/features.h"
#include "base/compiler_specific.h"
#include "base/debug/alias.h"
#include "base/memory/aligned_memory.h"
......@@ -86,8 +87,8 @@ TEST(MemoryTest, AllocatorShimWorking) {
// Don't test these on ASan/TSan/MSan configurations: only test the real
// allocator.
// Windows only supports these tests with the allocator shim in place.
#if !defined(OS_ANDROID) && !defined(OS_OPENBSD) && \
!(defined(OS_WIN) && !defined(ALLOCATOR_SHIM)) && \
#if !defined(OS_ANDROID) && !defined(OS_OPENBSD) && \
BUILDFLAG(ENABLE_WIN_ALLOCATOR_SHIM_TESTS) && \
!defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
namespace {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment