1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Platform-specific code for MacOS goes here. For the POSIX-compatible
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// parts, the implementation is in platform-posix.cc.
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <dlfcn.h>
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <mach/mach_init.h>
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <mach-o/dyld.h>
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <mach-o/getsect.h>
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/mman.h>
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <unistd.h>
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <AvailabilityMacros.h>
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <errno.h>
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <libkern/OSAtomic.h>
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <mach/mach.h>
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <mach/semaphore.h>
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <mach/task.h>
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <mach/vm_statistics.h>
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <pthread.h>
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <semaphore.h>
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <signal.h>
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <stdarg.h>
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <stdlib.h>
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <string.h>
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/resource.h>
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/sysctl.h>
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/time.h>
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/types.h>
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <cmath>
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef MAP_TYPE
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/macros.h"
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/platform.h"
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace base {
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Constants used for mmap.
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// kMmapFd is used to pass vm_alloc flags to tag the region with the user
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// defined tag 255 This helps identify V8-allocated regions in memory analysis
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// tools like vmmap(1).
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int kMmapFd = VM_MAKE_TAG(255);
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const off_t kMmapFdOffset = 0;
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid* OS::Allocate(const size_t requested,
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   size_t* allocated,
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   bool is_executable) {
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const size_t msize = RoundUp(requested, getpagesize());
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* mbase = mmap(OS::GetRandomMmapAddr(),
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     msize,
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     prot,
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     MAP_PRIVATE | MAP_ANON,
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     kMmapFd,
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     kMmapFdOffset);
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mbase == MAP_FAILED) return NULL;
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *allocated = msize;
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return mbase;
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass PosixMemoryMappedFile : public OS::MemoryMappedFile {
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PosixMemoryMappedFile(FILE* file, void* memory, int size)
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : file_(file), memory_(memory), size_(size) { }
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual ~PosixMemoryMappedFile();
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void* memory() { return memory_; }
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual int size() { return size_; }
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FILE* file_;
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* memory_;
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size_;
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FILE* file = fopen(name, "r+");
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (file == NULL) return NULL;
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fseek(file, 0, SEEK_END);
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = ftell(file);
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* memory =
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mmap(OS::GetRandomMmapAddr(),
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           size,
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           PROT_READ | PROT_WRITE,
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           MAP_SHARED,
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           fileno(file),
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           0);
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return new PosixMemoryMappedFile(file, memory, size);
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void* initial) {
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FILE* file = fopen(name, "w+");
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (file == NULL) return NULL;
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int result = fwrite(initial, size, 1, file);
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (result < 1) {
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fclose(file);
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return NULL;
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* memory =
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mmap(OS::GetRandomMmapAddr(),
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          size,
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          PROT_READ | PROT_WRITE,
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          MAP_SHARED,
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          fileno(file),
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          0);
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return new PosixMemoryMappedFile(file, memory, size);
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochPosixMemoryMappedFile::~PosixMemoryMappedFile() {
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (memory_) OS::Free(memory_, size_);
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fclose(file_);
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstd::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  std::vector<SharedLibraryAddress> result;
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned int images_count = _dyld_image_count();
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (unsigned int i = 0; i < images_count; ++i) {
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const mach_header* header = _dyld_get_image_header(i);
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (header == NULL) continue;
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_HOST_ARCH_X64
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint64_t size;
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char* code_ptr = getsectdatafromheader_64(
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        reinterpret_cast<const mach_header_64*>(header),
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        SEG_TEXT,
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        SECT_TEXT,
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        &size);
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    unsigned int size;
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char* code_ptr = getsectdatafromheader(header, SEG_TEXT, SECT_TEXT, &size);
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (code_ptr == NULL) continue;
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const uintptr_t slide = _dyld_get_image_vmaddr_slide(i);
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const uintptr_t start = reinterpret_cast<uintptr_t>(code_ptr) + slide;
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    result.push_back(
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        SharedLibraryAddress(_dyld_get_image_name(i), start, start + size));
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::SignalCodeMovingGC() {
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst char* OS::LocalTimezone(double time, TimezoneCache* cache) {
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (std::isnan(time)) return "";
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  struct tm* t = localtime(&tv);
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (NULL == t) return "";
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return t->tm_zone;
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble OS::LocalTimeOffset(TimezoneCache* cache) {
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  time_t tv = time(NULL);
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  struct tm* t = localtime(&tv);
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // tm_gmtoff includes any daylight savings offset, so subtract it.
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return static_cast<double>(t->tm_gmtoff * msPerSecond -
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             (t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochVirtualMemory::VirtualMemory(size_t size)
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : address_(ReserveRegion(size)), size_(size) { }
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochVirtualMemory::VirtualMemory(size_t size, size_t alignment)
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : address_(NULL), size_(0) {
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((alignment % OS::AllocateAlignment()) == 0);
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t request_size = RoundUp(size + alignment,
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                static_cast<intptr_t>(OS::AllocateAlignment()));
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* reservation = mmap(OS::GetRandomMmapAddr(),
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           request_size,
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           PROT_NONE,
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           kMmapFd,
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           kMmapFdOffset);
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reservation == MAP_FAILED) return;
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint8_t* base = static_cast<uint8_t*>(reservation);
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint8_t* aligned_base = RoundUp(base, alignment);
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_LE(base, aligned_base);
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Unmap extra memory reserved before and after the desired block.
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (aligned_base != base) {
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    size_t prefix_size = static_cast<size_t>(aligned_base - base);
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OS::Free(base, prefix_size);
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    request_size -= prefix_size;
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_LE(aligned_size, request_size);
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (aligned_size != request_size) {
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    size_t suffix_size = request_size - aligned_size;
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OS::Free(aligned_base + aligned_size, suffix_size);
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    request_size -= suffix_size;
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(aligned_size == request_size);
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  address_ = static_cast<void*>(aligned_base);
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_ = aligned_size;
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochVirtualMemory::~VirtualMemory() {
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsReserved()) {
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool result = ReleaseRegion(address(), size());
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(result);
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    USE(result);
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::IsReserved() {
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return address_ != NULL;
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid VirtualMemory::Reset() {
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  address_ = NULL;
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_ = 0;
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return CommitRegion(address, size, is_executable);
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::Uncommit(void* address, size_t size) {
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return UncommitRegion(address, size);
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::Guard(void* address) {
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OS::Guard(address, OS::CommitPageSize());
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid* VirtualMemory::ReserveRegion(size_t size) {
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* result = mmap(OS::GetRandomMmapAddr(),
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      size,
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      PROT_NONE,
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      kMmapFd,
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      kMmapFdOffset);
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (result == MAP_FAILED) return NULL;
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::CommitRegion(void* address,
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 size_t size,
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 bool is_executable) {
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (MAP_FAILED == mmap(address,
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         size,
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         prot,
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         MAP_PRIVATE | MAP_ANON | MAP_FIXED,
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         kMmapFd,
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         kMmapFdOffset)) {
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return false;
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::UncommitRegion(void* address, size_t size) {
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return mmap(address,
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              size,
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              PROT_NONE,
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED,
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              kMmapFd,
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              kMmapFdOffset) != MAP_FAILED;
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::ReleaseRegion(void* address, size_t size) {
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return munmap(address, size) == 0;
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::HasLazyCommits() {
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return false;
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} }  // namespace v8::base
311