b11f2d8e69
Instead of implementing separate aligned and unaligned memory allocation primitives for each OS, just change the unaligned allocator into a wrapper around the aligned primitive. While here, we can optimize the AllocateAligned logic slightly: if we want an N-page-aligned allocation, we only need to increase the allocation size by N-1 pages instead of N. Notably, this means 1-page-aligned allocations don't require any extra alignment pages, so the new logic behaves identically as before on Android, Fuchsia, Linux, and macOS. On Windows, it behaves slightly differently only in that unaligned requests used to be handled as a single VirtualAlloc call with MEM_RESERVE | MEM_COMMIT, but now they're handled as two separate calls (reserve *then* commit). Naively, I don't expect this matters in practice, but if it does, we can always add a fast path for alignment==page_size_ without affecting the OS-independent API. Change-Id: I42b2cf5dfc6e137546d8acfb6cc8939a01687948 Reviewed-on: https://dart-review.googlesource.com/c/91081 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
98 lines
3.3 KiB
C++
98 lines
3.3 KiB
C++
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#ifndef RUNTIME_VM_VIRTUAL_MEMORY_H_
|
|
#define RUNTIME_VM_VIRTUAL_MEMORY_H_
|
|
|
|
#include "platform/utils.h"
|
|
#include "vm/globals.h"
|
|
#include "vm/memory_region.h"
|
|
|
|
namespace dart {
|
|
|
|
class VirtualMemory {
|
|
public:
|
|
enum Protection {
|
|
kNoAccess,
|
|
kReadOnly,
|
|
kReadWrite,
|
|
kReadExecute,
|
|
kReadWriteExecute
|
|
};
|
|
|
|
// The reserved memory is unmapped on destruction.
|
|
~VirtualMemory();
|
|
|
|
uword start() const { return region_.start(); }
|
|
uword end() const { return region_.end(); }
|
|
void* address() const { return region_.pointer(); }
|
|
intptr_t size() const { return region_.size(); }
|
|
|
|
static void Init();
|
|
|
|
bool Contains(uword addr) const { return region_.Contains(addr); }
|
|
|
|
// Changes the protection of the virtual memory area.
|
|
static void Protect(void* address, intptr_t size, Protection mode);
|
|
void Protect(Protection mode) { return Protect(address(), size(), mode); }
|
|
|
|
// Reserves and commits a virtual memory segment with size. If a segment of
|
|
// the requested size cannot be allocated, NULL is returned.
|
|
static VirtualMemory* Allocate(intptr_t size,
|
|
bool is_executable,
|
|
const char* name) {
|
|
return AllocateAligned(size, PageSize(), is_executable, name);
|
|
}
|
|
static VirtualMemory* AllocateAligned(intptr_t size,
|
|
intptr_t alignment,
|
|
bool is_executable,
|
|
const char* name);
|
|
|
|
static intptr_t PageSize() {
|
|
ASSERT(page_size_ != 0);
|
|
ASSERT(Utils::IsPowerOfTwo(page_size_));
|
|
return page_size_;
|
|
}
|
|
|
|
static bool InSamePage(uword address0, uword address1);
|
|
|
|
// Truncate this virtual memory segment. If try_unmap is false, the
|
|
// memory beyond the new end is still accessible, but will be returned
|
|
// upon destruction.
|
|
void Truncate(intptr_t new_size, bool try_unmap = true);
|
|
|
|
// False for a part of a snapshot added directly to the Dart heap, which
|
|
// belongs to the embedder and must not be deallocated or have its
|
|
// protection status changed by the VM.
|
|
bool vm_owns_region() const { return reserved_.pointer() != NULL; }
|
|
|
|
static VirtualMemory* ForImagePage(void* pointer, uword size);
|
|
|
|
private:
|
|
// Free a sub segment. On operating systems that support it this
|
|
// can give back the virtual memory to the system. Returns true on success.
|
|
static bool FreeSubSegment(void* address, intptr_t size);
|
|
|
|
// This constructor is only used internally when reserving new virtual spaces.
|
|
// It does not reserve any virtual address space on its own.
|
|
VirtualMemory(const MemoryRegion& region,
|
|
const MemoryRegion& reserved)
|
|
: region_(region), reserved_(reserved) {}
|
|
|
|
MemoryRegion region_;
|
|
|
|
// The underlying reservation not yet given back to the OS.
|
|
// Its address might disagree with region_ due to aligned allocations.
|
|
// Its size might disagree with region_ due to Truncate.
|
|
MemoryRegion reserved_;
|
|
|
|
static uword page_size_;
|
|
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(VirtualMemory);
|
|
};
|
|
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_VM_VIRTUAL_MEMORY_H_
|