memory/mozalloc/VolatileBufferWindows.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/memory/mozalloc/VolatileBufferWindows.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,157 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#if defined(XP_WIN)
     1.9 +#  define MOZALLOC_EXPORT __declspec(dllexport)
    1.10 +#endif
    1.11 +
    1.12 +#include "VolatileBuffer.h"
    1.13 +#include "mozilla/Assertions.h"
    1.14 +#include "mozilla/mozalloc.h"
    1.15 +#include "mozilla/WindowsVersion.h"
    1.16 +
    1.17 +#include <windows.h>
    1.18 +
    1.19 +#ifdef MOZ_MEMORY
    1.20 +extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size);
    1.21 +#endif
    1.22 +
    1.23 +#ifndef MEM_RESET_UNDO
    1.24 +#define MEM_RESET_UNDO 0x1000000
    1.25 +#endif
    1.26 +
    1.27 +#define MIN_VOLATILE_ALLOC_SIZE 8192
    1.28 +
    1.29 +namespace mozilla {
    1.30 +
    1.31 +VolatileBuffer::VolatileBuffer()
    1.32 +  : mBuf(nullptr)
    1.33 +  , mSize(0)
    1.34 +  , mLockCount(0)
    1.35 +  , mHeap(false)
    1.36 +  , mFirstLock(true)
    1.37 +{
    1.38 +}
    1.39 +
    1.40 +bool
    1.41 +VolatileBuffer::Init(size_t aSize, size_t aAlignment)
    1.42 +{
    1.43 +  MOZ_ASSERT(!mSize && !mBuf, "Init called twice");
    1.44 +  MOZ_ASSERT(!(aAlignment % sizeof(void *)),
    1.45 +             "Alignment must be multiple of pointer size");
    1.46 +
    1.47 +  mSize = aSize;
    1.48 +  if (aSize < MIN_VOLATILE_ALLOC_SIZE) {
    1.49 +    goto heap_alloc;
    1.50 +  }
    1.51 +
    1.52 +  static bool sUndoSupported = IsWin8OrLater();
    1.53 +  if (!sUndoSupported) {
    1.54 +    goto heap_alloc;
    1.55 +  }
    1.56 +
    1.57 +  mBuf = VirtualAllocEx(GetCurrentProcess(),
    1.58 +                        nullptr,
    1.59 +                        mSize,
    1.60 +                        MEM_COMMIT | MEM_RESERVE,
    1.61 +                        PAGE_READWRITE);
    1.62 +  if (mBuf) {
    1.63 +    return true;
    1.64 +  }
    1.65 +
    1.66 +heap_alloc:
    1.67 +#ifdef MOZ_MEMORY
    1.68 +  posix_memalign(&mBuf, aAlignment, aSize);
    1.69 +#else
    1.70 +  mBuf = _aligned_malloc(aSize, aAlignment);
    1.71 +#endif
    1.72 +  mHeap = true;
    1.73 +  return !!mBuf;
    1.74 +}
    1.75 +
    1.76 +VolatileBuffer::~VolatileBuffer()
    1.77 +{
    1.78 +  if (OnHeap()) {
    1.79 +#ifdef MOZ_MEMORY
    1.80 +    free(mBuf);
    1.81 +#else
    1.82 +    _aligned_free(mBuf);
    1.83 +#endif
    1.84 +  } else {
    1.85 +    VirtualFreeEx(GetCurrentProcess(), mBuf, 0, MEM_RELEASE);
    1.86 +  }
    1.87 +}
    1.88 +
    1.89 +bool
    1.90 +VolatileBuffer::Lock(void** aBuf)
    1.91 +{
    1.92 +  MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer");
    1.93 +
    1.94 +  *aBuf = mBuf;
    1.95 +  if (++mLockCount > 1 || OnHeap()) {
    1.96 +    return true;
    1.97 +  }
    1.98 +
    1.99 +  // MEM_RESET_UNDO's behavior is undefined when called on memory that
   1.100 +  // hasn't been MEM_RESET.
   1.101 +  if (mFirstLock) {
   1.102 +    mFirstLock = false;
   1.103 +    return true;
   1.104 +  }
   1.105 +
   1.106 +  void* addr = VirtualAllocEx(GetCurrentProcess(),
   1.107 +                              mBuf,
   1.108 +                              mSize,
   1.109 +                              MEM_RESET_UNDO,
   1.110 +                              PAGE_READWRITE);
   1.111 +  return !!addr;
   1.112 +}
   1.113 +
   1.114 +void
   1.115 +VolatileBuffer::Unlock()
   1.116 +{
   1.117 +  MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!");
   1.118 +  if (--mLockCount || OnHeap()) {
   1.119 +    return;
   1.120 +  }
   1.121 +
   1.122 +  void* addr = VirtualAllocEx(GetCurrentProcess(),
   1.123 +                              mBuf,
   1.124 +                              mSize,
   1.125 +                              MEM_RESET,
   1.126 +                              PAGE_READWRITE);
   1.127 +  MOZ_ASSERT(addr, "Failed to MEM_RESET");
   1.128 +}
   1.129 +
   1.130 +bool
   1.131 +VolatileBuffer::OnHeap() const
   1.132 +{
   1.133 +  return mHeap;
   1.134 +}
   1.135 +
   1.136 +size_t
   1.137 +VolatileBuffer::HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
   1.138 +{
   1.139 +  if (OnHeap()) {
   1.140 +#ifdef MOZ_MEMORY
   1.141 +    return aMallocSizeOf(mBuf);
   1.142 +#else
   1.143 +    return mSize;
   1.144 +#endif
   1.145 +  }
   1.146 +
   1.147 +  return 0;
   1.148 +}
   1.149 +
   1.150 +size_t
   1.151 +VolatileBuffer::NonHeapSizeOfExcludingThis() const
   1.152 +{
   1.153 +  if (OnHeap()) {
   1.154 +    return 0;
   1.155 +  }
   1.156 +
   1.157 +  return (mSize + 4095) & ~4095;
   1.158 +}
   1.159 +
   1.160 +} // namespace mozilla

mercurial