15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is a simple allocator based on the windows heap. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" { 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HANDLE win_heap; 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool win_heap_init(bool use_lfh) { 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) win_heap = HeapCreate(0, 0, 0); 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (win_heap == NULL) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_lfh) { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG enable_lfh = 2; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapSetInformation(win_heap, HeapCompatibilityInformation, 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &enable_lfh, sizeof(enable_lfh)); 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: Setting LFH may fail. Vista already has it enabled. 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And under the debugger, it won't use LFH. So we 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ignore any errors. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* win_heap_malloc(size_t size) { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HeapAlloc(win_heap, 0, size); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void win_heap_free(void* size) { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapFree(win_heap, 0, size); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* win_heap_realloc(void* ptr, size_t size) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ptr) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return win_heap_malloc(size); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!size) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) win_heap_free(ptr); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HeapReAlloc(win_heap, 0, ptr, size); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t win_heap_msize(void* ptr) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HeapSize(win_heap, 0, ptr); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* win_heap_memalign(size_t alignment, size_t size) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reserve enough space to ensure we can align and set aligned_ptr[-1] to the 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // original allocation for use with win_heap_memalign_free() later. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t allocation_size = size + (alignment - 1) + sizeof(void*); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for overflow. Alignment and size are checked in allocator_shim. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(size, allocation_size); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(alignment, allocation_size); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Since we're directly calling the allocator function, before OOM handling, 601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // we need to NULL check to ensure the allocation succeeded. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* ptr = win_heap_malloc(allocation_size); 621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!ptr) 631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return ptr; 641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* aligned_ptr = static_cast<char*>(ptr) + sizeof(void*); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aligned_ptr += 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alignment - reinterpret_cast<uintptr_t>(aligned_ptr) & (alignment - 1); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void**>(aligned_ptr)[-1] = ptr; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return aligned_ptr; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void win_heap_memalign_free(void* ptr) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ptr) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) win_heap_free(static_cast<void**>(ptr)[-1]); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // extern "C" 79