105ed9ddc6ff3a1ab3983c50d378cddfa257869b6jkummerow@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
4a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org// Platform-specific code for FreeBSD goes here. For the POSIX-compatible
6e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org// parts, the implementation is in platform-posix.cc.
7a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
8a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <pthread.h>
9a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <semaphore.h>
10a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <signal.h>
11a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <sys/time.h>
12a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <sys/resource.h>
13381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org#include <sys/types.h>
14a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <sys/ucontext.h>
15a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <stdlib.h>
16a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
17a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <sys/types.h>  // mmap & munmap
18a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <sys/mman.h>   // mmap & munmap
19a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <sys/stat.h>   // open
20a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <sys/fcntl.h>  // open
21a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <unistd.h>     // getpagesize
22badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org// If you don't have execinfo.h then you need devel/libexecinfo from ports.
23a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <strings.h>    // index
24a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <errno.h>
25a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <stdarg.h>
26a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <limits.h>
27a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
28a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#undef MAP_TYPE
29a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
30196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
31a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
32196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/platform.h"
33a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
34a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
3571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
3671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal {
37a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
38a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
396b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgconst char* OS::LocalTimezone(double time, TimezoneCache* cache) {
4077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  if (std::isnan(time)) return "";
41e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
42b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  struct tm* t = localtime(&tv);
43b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  if (NULL == t) return "";
44b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  return t->tm_zone;
45b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
46b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
47b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
486b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgdouble OS::LocalTimeOffset(TimezoneCache* cache) {
49b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  time_t tv = time(NULL);
50b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  struct tm* t = localtime(&tv);
51b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // tm_gmtoff includes any daylight savings offset, so subtract it.
52b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  return static_cast<double>(t->tm_gmtoff * msPerSecond -
53b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org                             (t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
54b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
55b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
56b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
57a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid* OS::Allocate(const size_t requested,
58a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                   size_t* allocated,
59a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                   bool executable) {
60a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  const size_t msize = RoundUp(requested, getpagesize());
61a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0);
62a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
63a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
641845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  if (mbase == MAP_FAILED) return NULL;
65a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  *allocated = msize;
66a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return mbase;
67a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
68a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
69a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
70a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgclass PosixMemoryMappedFile : public OS::MemoryMappedFile {
71a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org public:
72a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  PosixMemoryMappedFile(FILE* file, void* memory, int size)
73a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    : file_(file), memory_(memory), size_(size) { }
74a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  virtual ~PosixMemoryMappedFile();
75a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  virtual void* memory() { return memory_; }
760a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  virtual int size() { return size_; }
77a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org private:
78a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  FILE* file_;
79a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  void* memory_;
80a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int size_;
81a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org};
82a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
83a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
840a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.orgOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
853a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  FILE* file = fopen(name, "r+");
860a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  if (file == NULL) return NULL;
870a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
880a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  fseek(file, 0, SEEK_END);
890a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  int size = ftell(file);
900a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
910a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  void* memory =
920a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
930a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  return new PosixMemoryMappedFile(file, memory, size);
940a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org}
950a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
960a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
97a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
98a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    void* initial) {
99a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  FILE* file = fopen(name, "w+");
100a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (file == NULL) return NULL;
101a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int result = fwrite(initial, size, 1, file);
102a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (result < 1) {
103a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    fclose(file);
104a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return NULL;
105a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
106a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  void* memory =
107a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
108a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return new PosixMemoryMappedFile(file, memory, size);
109a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
110a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
111a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
112a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgPosixMemoryMappedFile::~PosixMemoryMappedFile() {
113a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (memory_) munmap(memory_, size_);
114a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  fclose(file_);
115a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
116a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
117a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
118a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatic unsigned StringToLong(char* buffer) {
119a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return static_cast<unsigned>(strtol(buffer, NULL, 16));  // NOLINT
120a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
121a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
122a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1231845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgstd::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
1241845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  std::vector<SharedLibraryAddress> result;
125a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  static const int MAP_LENGTH = 1024;
126a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int fd = open("/proc/self/maps", O_RDONLY);
1271845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  if (fd < 0) return result;
128a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  while (true) {
129a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    char addr_buffer[11];
130a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    addr_buffer[0] = '0';
131a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    addr_buffer[1] = 'x';
132a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    addr_buffer[10] = 0;
133a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    int result = read(fd, addr_buffer + 2, 8);
134a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (result < 8) break;
135a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    unsigned start = StringToLong(addr_buffer);
136a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    result = read(fd, addr_buffer + 2, 1);
137a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (result < 1) break;
138a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (addr_buffer[2] != '-') break;
139a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    result = read(fd, addr_buffer + 2, 8);
140a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (result < 8) break;
141a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    unsigned end = StringToLong(addr_buffer);
142a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    char buffer[MAP_LENGTH];
143a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    int bytes_read = -1;
144a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    do {
145a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      bytes_read++;
146a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (bytes_read >= MAP_LENGTH - 1)
147a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
148a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      result = read(fd, buffer + bytes_read, 1);
149a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (result < 1) break;
150a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    } while (buffer[bytes_read] != '\n');
151a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    buffer[bytes_read] = 0;
152a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // Ignore mappings that are not executable.
153a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (buffer[3] != 'x') continue;
154a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    char* start_of_path = index(buffer, '/');
155a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // There may be no filename in this line.  Skip to next.
156a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (start_of_path == NULL) continue;
157a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    buffer[bytes_read] = 0;
1581845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    result.push_back(SharedLibraryAddress(start_of_path, start, end));
159a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
160a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  close(fd);
1611845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  return result;
162a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
163a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
164a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1654a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.orgvoid OS::SignalCodeMovingGC() {
1664a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org}
1674a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org
1684a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org
169a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
170a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Constants used for mmap.
171a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatic const int kMmapFd = -1;
172a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatic const int kMmapFdOffset = 0;
173a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
174e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
175c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
176a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
177e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
178e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgVirtualMemory::VirtualMemory(size_t size)
179e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    : address_(ReserveRegion(size)), size_(size) { }
180a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
181a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
182c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgVirtualMemory::VirtualMemory(size_t size, size_t alignment)
183c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    : address_(NULL), size_(0) {
184c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment())));
185c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  size_t request_size = RoundUp(size + alignment,
186c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                static_cast<intptr_t>(OS::AllocateAlignment()));
187c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  void* reservation = mmap(OS::GetRandomMmapAddr(),
188c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                           request_size,
189c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                           PROT_NONE,
190c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                           MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
191c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                           kMmapFd,
192c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                           kMmapFdOffset);
193c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (reservation == MAP_FAILED) return;
194c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
195c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Address base = static_cast<Address>(reservation);
196c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Address aligned_base = RoundUp(base, alignment);
197c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ASSERT_LE(base, aligned_base);
198c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
199c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // Unmap extra memory reserved before and after the desired block.
200c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (aligned_base != base) {
201c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    size_t prefix_size = static_cast<size_t>(aligned_base - base);
202c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    OS::Free(base, prefix_size);
203c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    request_size -= prefix_size;
204c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  }
205c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
206c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
207c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ASSERT_LE(aligned_size, request_size);
208c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
209c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (aligned_size != request_size) {
210c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    size_t suffix_size = request_size - aligned_size;
211c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    OS::Free(aligned_base + aligned_size, suffix_size);
212c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    request_size -= suffix_size;
213c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  }
214c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
215c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ASSERT(aligned_size == request_size);
216c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
217c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  address_ = static_cast<void*>(aligned_base);
218c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  size_ = aligned_size;
219c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
220c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
221c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
222a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgVirtualMemory::~VirtualMemory() {
223a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (IsReserved()) {
224c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    bool result = ReleaseRegion(address(), size());
225c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    ASSERT(result);
226c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    USE(result);
227a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
228a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
229a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
230a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
231a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgbool VirtualMemory::IsReserved() {
232c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  return address_ != NULL;
233a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
234a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
235a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
236c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid VirtualMemory::Reset() {
237c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  address_ = NULL;
238c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  size_ = 0;
239c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
240c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
241c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
242c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
243c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  return CommitRegion(address, size, is_executable);
244c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
245c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
246c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
247c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgbool VirtualMemory::Uncommit(void* address, size_t size) {
248c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  return UncommitRegion(address, size);
249c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
250c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
251c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
252ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.orgbool VirtualMemory::Guard(void* address) {
253ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org  OS::Guard(address, OS::CommitPageSize());
254ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org  return true;
255ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org}
256ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org
257ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org
258c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid* VirtualMemory::ReserveRegion(size_t size) {
259c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  void* result = mmap(OS::GetRandomMmapAddr(),
260c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                      size,
261c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                      PROT_NONE,
262c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                      MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
263c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                      kMmapFd,
264c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                      kMmapFdOffset);
265c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
266c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (result == MAP_FAILED) return NULL;
267c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
268c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  return result;
269c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
270c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
271c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
272c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgbool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
273c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
274c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (MAP_FAILED == mmap(base,
275c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                         size,
276c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                         prot,
277a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                         MAP_PRIVATE | MAP_ANON | MAP_FIXED,
278c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                         kMmapFd,
279c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                         kMmapFdOffset)) {
280a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return false;
281a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
282a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return true;
283a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
284a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
285a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
286c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgbool VirtualMemory::UncommitRegion(void* base, size_t size) {
287c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  return mmap(base,
288c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org              size,
289c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org              PROT_NONE,
290a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org              MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED,
291c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org              kMmapFd,
292c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org              kMmapFdOffset) != MAP_FAILED;
293c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
294c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
295c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
296c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgbool VirtualMemory::ReleaseRegion(void* base, size_t size) {
297c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  return munmap(base, size) == 0;
298a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
299a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
300a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
30172204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.orgbool VirtualMemory::HasLazyCommits() {
30272204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org  // TODO(alph): implement for the platform.
30372204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org  return false;
30472204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org}
30572204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org
306a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org} }  // namespace v8::internal
307