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 FreeBSD goes here. For the POSIX-compatible
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// parts, the implementation is in platform-posix.cc.
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <pthread.h>
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <semaphore.h>
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <signal.h>
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <stdlib.h>
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/resource.h>
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/time.h>
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/types.h>
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/ucontext.h>
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/fcntl.h>  // open
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/mman.h>   // mmap & munmap
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/stat.h>   // open
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/types.h>  // mmap & munmap
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <unistd.h>     // getpagesize
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// If you don't have execinfo.h then you need devel/libexecinfo from ports.
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <errno.h>
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <limits.h>
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <stdarg.h>
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <strings.h>    // index
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <cmath>
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef MAP_TYPE
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/macros.h"
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/platform.h"
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace base {
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst char* OS::LocalTimezone(double time, TimezoneCache* cache) {
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (std::isnan(time)) return "";
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  struct tm* t = localtime(&tv);
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (NULL == t) return "";
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return t->tm_zone;
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble OS::LocalTimeOffset(TimezoneCache* cache) {
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  time_t tv = time(NULL);
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  struct tm* t = localtime(&tv);
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // tm_gmtoff includes any daylight savings offset, so subtract it.
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return static_cast<double>(t->tm_gmtoff * msPerSecond -
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             (t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid* OS::Allocate(const size_t requested,
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   size_t* allocated,
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   bool executable) {
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const size_t msize = RoundUp(requested, getpagesize());
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0);
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
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(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return new PosixMemoryMappedFile(file, memory, size);
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void* initial) {
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FILE* file = fopen(name, "w+");
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (file == NULL) return NULL;
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int result = fwrite(initial, size, 1, file);
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (result < 1) {
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fclose(file);
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return NULL;
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* memory =
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return new PosixMemoryMappedFile(file, memory, size);
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochPosixMemoryMappedFile::~PosixMemoryMappedFile() {
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (memory_) munmap(memory_, size_);
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fclose(file_);
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic unsigned StringToLong(char* buffer) {
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return static_cast<unsigned>(strtol(buffer, NULL, 16));  // NOLINT
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstd::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  std::vector<SharedLibraryAddress> result;
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int MAP_LENGTH = 1024;
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int fd = open("/proc/self/maps", O_RDONLY);
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (fd < 0) return result;
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (true) {
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char addr_buffer[11];
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addr_buffer[0] = '0';
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addr_buffer[1] = 'x';
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addr_buffer[10] = 0;
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ssize_t bytes_read = read(fd, addr_buffer + 2, 8);
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (bytes_read < 8) break;
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    unsigned start = StringToLong(addr_buffer);
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bytes_read = read(fd, addr_buffer + 2, 1);
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (bytes_read < 1) break;
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (addr_buffer[2] != '-') break;
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bytes_read = read(fd, addr_buffer + 2, 8);
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (bytes_read < 8) break;
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    unsigned end = StringToLong(addr_buffer);
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char buffer[MAP_LENGTH];
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int bytes_read = -1;
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    do {
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      bytes_read++;
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (bytes_read >= MAP_LENGTH - 1)
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      bytes_read = read(fd, buffer + bytes_read, 1);
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (bytes_read < 1) break;
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } while (buffer[bytes_read] != '\n');
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    buffer[bytes_read] = 0;
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Ignore mappings that are not executable.
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (buffer[3] != 'x') continue;
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char* start_of_path = index(buffer, '/');
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // There may be no filename in this line.  Skip to next.
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (start_of_path == NULL) continue;
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    buffer[bytes_read] = 0;
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    result.push_back(SharedLibraryAddress(start_of_path, start, end));
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  close(fd);
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::SignalCodeMovingGC() {
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Constants used for mmap.
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int kMmapFd = -1;
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int kMmapFdOffset = 0;
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochVirtualMemory::VirtualMemory(size_t size)
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : address_(ReserveRegion(size)), size_(size) { }
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochVirtualMemory::VirtualMemory(size_t size, size_t alignment)
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : address_(NULL), size_(0) {
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((alignment % OS::AllocateAlignment()) == 0);
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t request_size = RoundUp(size + alignment,
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                static_cast<intptr_t>(OS::AllocateAlignment()));
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* reservation = mmap(OS::GetRandomMmapAddr(),
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           request_size,
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           PROT_NONE,
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           kMmapFd,
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           kMmapFdOffset);
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reservation == MAP_FAILED) return;
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint8_t* base = static_cast<uint8_t*>(reservation);
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint8_t* aligned_base = RoundUp(base, alignment);
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_LE(base, aligned_base);
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Unmap extra memory reserved before and after the desired block.
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (aligned_base != base) {
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    size_t prefix_size = static_cast<size_t>(aligned_base - base);
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OS::Free(base, prefix_size);
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    request_size -= prefix_size;
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_LE(aligned_size, request_size);
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (aligned_size != request_size) {
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    size_t suffix_size = request_size - aligned_size;
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OS::Free(aligned_base + aligned_size, suffix_size);
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    request_size -= suffix_size;
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(aligned_size == request_size);
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  address_ = static_cast<void*>(aligned_base);
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_ = aligned_size;
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochVirtualMemory::~VirtualMemory() {
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsReserved()) {
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool result = ReleaseRegion(address(), size());
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(result);
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    USE(result);
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::IsReserved() {
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return address_ != NULL;
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid VirtualMemory::Reset() {
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  address_ = NULL;
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_ = 0;
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return CommitRegion(address, size, is_executable);
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::Uncommit(void* address, size_t size) {
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return UncommitRegion(address, size);
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::Guard(void* address) {
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OS::Guard(address, OS::CommitPageSize());
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid* VirtualMemory::ReserveRegion(size_t size) {
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* result = mmap(OS::GetRandomMmapAddr(),
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      size,
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      PROT_NONE,
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      kMmapFd,
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      kMmapFdOffset);
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (result == MAP_FAILED) return NULL;
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (MAP_FAILED == mmap(base,
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         size,
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         prot,
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         MAP_PRIVATE | MAP_ANON | MAP_FIXED,
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         kMmapFd,
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         kMmapFdOffset)) {
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return false;
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::UncommitRegion(void* base, size_t size) {
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return mmap(base,
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              size,
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              PROT_NONE,
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED,
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              kMmapFd,
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              kMmapFdOffset) != MAP_FAILED;
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::ReleaseRegion(void* base, size_t size) {
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return munmap(base, size) == 0;
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::HasLazyCommits() {
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(alph): implement for the platform.
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return false;
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} }  // namespace v8::base
308