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.
43a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
5e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org// Platform-specific code for Cygwin goes here. For the POSIX-compatible
6e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org// parts, the implementation is in platform-posix.cc.
73a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
83a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <errno.h>
93a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <pthread.h>
103a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <semaphore.h>
113a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <stdarg.h>
123a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <strings.h>    // index
133a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <sys/mman.h>   // mmap & munmap
144b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include <sys/time.h>
153a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <unistd.h>     // sysconf
163a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
17248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org#include <cmath>
183a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
19248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org#undef MAP_TYPE
203a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
215de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/macros.h"
225de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/platform.h"
231e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/win32-headers.h"
243a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
253a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgnamespace v8 {
265de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.orgnamespace base {
273a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
283a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
296b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgconst char* OS::LocalTimezone(double time, TimezoneCache* cache) {
3077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  if (std::isnan(time)) return "";
31e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
323a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  struct tm* t = localtime(&tv);
333a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if (NULL == t) return "";
343a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  return tzname[0];  // The location of the timezone string on Cygwin.
353a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
363a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
373a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
386b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgdouble OS::LocalTimeOffset(TimezoneCache* cache) {
393a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // On Cygwin, struct tm does not contain a tm_gmtoff field.
403a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  time_t utc = time(NULL);
41e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(utc != -1);
423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  struct tm* loc = localtime(&utc);
43e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(loc != NULL);
443a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // time - localtime includes any daylight savings offset, so subtract it.
453a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  return static_cast<double>((mktime(loc) - utc) * msPerSecond -
463a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                             (loc->tm_isdst > 0 ? 3600 * msPerSecond : 0));
473a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
483a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
493a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
503a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgvoid* OS::Allocate(const size_t requested,
513a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                   size_t* allocated,
523a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                   bool is_executable) {
533a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  const size_t msize = RoundUp(requested, sysconf(_SC_PAGESIZE));
543a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
553a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
561845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  if (mbase == MAP_FAILED) return NULL;
573a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  *allocated = msize;
583a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  return mbase;
593a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
603a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
613a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
623a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgclass PosixMemoryMappedFile : public OS::MemoryMappedFile {
633a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org public:
643a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  PosixMemoryMappedFile(FILE* file, void* memory, int size)
653a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    : file_(file), memory_(memory), size_(size) { }
663a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  virtual ~PosixMemoryMappedFile();
673a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  virtual void* memory() { return memory_; }
683a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  virtual int size() { return size_; }
693a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org private:
703a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  FILE* file_;
713a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void* memory_;
723a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  int size_;
733a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org};
743a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
753a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
763a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
773a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  FILE* file = fopen(name, "r+");
783a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if (file == NULL) return NULL;
793a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
803a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  fseek(file, 0, SEEK_END);
813a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  int size = ftell(file);
823a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
833a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void* memory =
843a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
853a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  return new PosixMemoryMappedFile(file, memory, size);
863a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
873a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
883a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
893a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
903a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    void* initial) {
913a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  FILE* file = fopen(name, "w+");
923a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if (file == NULL) return NULL;
933a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  int result = fwrite(initial, size, 1, file);
943a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if (result < 1) {
953a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    fclose(file);
963a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    return NULL;
973a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  }
983a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void* memory =
993a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
1003a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  return new PosixMemoryMappedFile(file, memory, size);
1013a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
1023a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1033a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1043a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgPosixMemoryMappedFile::~PosixMemoryMappedFile() {
1053a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if (memory_) munmap(memory_, size_);
1063a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  fclose(file_);
1073a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
1083a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1093a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1101845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgstd::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
1111845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  std::vector<SharedLibraryAddresses> result;
1123a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // This function assumes that the layout of the file is as follows:
1133a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
1143a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // If we encounter an unexpected situation we abort scanning further entries.
1153a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  FILE* fp = fopen("/proc/self/maps", "r");
1161845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  if (fp == NULL) return result;
1173a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1183a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // Allocate enough room to be able to store a full file name.
1193a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  const int kLibNameLen = FILENAME_MAX + 1;
1203a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
1213a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1223a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // This loop will terminate once the scanning hits an EOF.
1233a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  while (true) {
1243a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    uintptr_t start, end;
1253a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    char attr_r, attr_w, attr_x, attr_p;
1263a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    // Parse the addresses and permission bits at the beginning of the line.
1273a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break;
1283a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break;
1293a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1303a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    int c;
1313a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') {
1323a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      // Found a read-only executable entry. Skip characters until we reach
1333a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      // the beginning of the filename or the end of the line.
1343a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      do {
1353a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        c = getc(fp);
1363a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      } while ((c != EOF) && (c != '\n') && (c != '/'));
1373a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      if (c == EOF) break;  // EOF: Was unexpected, just exit.
1383a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1393a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      // Process the filename if found.
1403a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      if (c == '/') {
1413a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        ungetc(c, fp);  // Push the '/' back into the stream to be read below.
1423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1433a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        // Read to the end of the line. Exit if the read fails.
1443a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        if (fgets(lib_name, kLibNameLen, fp) == NULL) break;
1453a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1463a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        // Drop the newline character read by fgets. We do not need to check
1473a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        // for a zero-length string because we know that we at least read the
1483a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        // '/' character.
1493a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        lib_name[strlen(lib_name) - 1] = '\0';
1503a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      } else {
1513a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        // No library name found, just record the raw address range.
1523a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        snprintf(lib_name, kLibNameLen,
1533a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                 "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end);
1543a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      }
1551845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org      result.push_back(SharedLibraryAddress(lib_name, start, end));
1563a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    } else {
157f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com      // Entry not describing executable data. Skip to end of line to set up
1583a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      // reading the next entry.
1593a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      do {
1603a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        c = getc(fp);
1613a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      } while ((c != EOF) && (c != '\n'));
1623a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      if (c == EOF) break;
1633a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    }
1643a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  }
1653a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  free(lib_name);
1663a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  fclose(fp);
1671845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  return result;
1683a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
1693a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1703a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1713a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgvoid OS::SignalCodeMovingGC() {
1723a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // Nothing to do on Cygwin.
1733a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
1743a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1753a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
176c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// The VirtualMemory implementation is taken from platform-win32.cc.
177c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// The mmap-based virtual memory implementation as it is used on most posix
178c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// platforms does not work well because Cygwin does not support MAP_FIXED.
179c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// This causes VirtualMemory::Commit to not always commit the memory region
180c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// specified.
181c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org
182e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgstatic void* RandomizedVirtualAlloc(size_t size, int action, int protection) {
183e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  LPVOID base = NULL;
184e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
185e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_NOACCESS) {
186e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // For exectutable pages try and randomize the allocation address
187e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    for (size_t attempts = 0; base == NULL && attempts < 3; ++attempts) {
188d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      base = VirtualAlloc(OS::GetRandomMmapAddr(), size, action, protection);
189e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    }
190e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
191e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
192e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // After three attempts give up and let the OS find an address to use.
193e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (base == NULL) base = VirtualAlloc(NULL, size, action, protection);
194e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
195e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return base;
196c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org}
1973a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1983a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
199e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
200e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
201e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
202e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgVirtualMemory::VirtualMemory(size_t size)
203e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    : address_(ReserveRegion(size)), size_(size) { }
204e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
205e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
206e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgVirtualMemory::VirtualMemory(size_t size, size_t alignment)
207e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    : address_(NULL), size_(0) {
208e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org  DCHECK((alignment % OS::AllocateAlignment()) == 0);
209e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  size_t request_size = RoundUp(size + alignment,
210e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                static_cast<intptr_t>(OS::AllocateAlignment()));
211e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  void* address = ReserveRegion(request_size);
212e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (address == NULL) return;
213248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org  uint8_t* base = RoundUp(static_cast<uint8_t*>(address), alignment);
214e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Try reducing the size by freeing and then reallocating a specific area.
215e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  bool result = ReleaseRegion(address, request_size);
216e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  USE(result);
217e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(result);
218e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  address = VirtualAlloc(base, size, MEM_RESERVE, PAGE_NOACCESS);
219e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (address != NULL) {
220e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    request_size = size;
221e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(base == static_cast<uint8_t*>(address));
222e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  } else {
223e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Resizing failed, just go with a bigger area.
224e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    address = ReserveRegion(request_size);
225e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    if (address == NULL) return;
226e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
227e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  address_ = address;
228e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  size_ = request_size;
2293a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
2303a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
2313a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
2323a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgVirtualMemory::~VirtualMemory() {
2333a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if (IsReserved()) {
234e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    bool result = ReleaseRegion(address_, size_);
235e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(result);
236e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    USE(result);
2373a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  }
2383a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
2393a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
2403a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
241e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::IsReserved() {
242e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return address_ != NULL;
243e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
2443a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
245e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
246e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgvoid VirtualMemory::Reset() {
247e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  address_ = NULL;
248e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  size_ = 0;
249e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
250e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
251e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
252e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
253e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return CommitRegion(address, size, is_executable);
2543a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
2553a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
2563a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
2573a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgbool VirtualMemory::Uncommit(void* address, size_t size) {
258e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(IsReserved());
259e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return UncommitRegion(address, size);
260e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
261e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
262e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
263e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgvoid* VirtualMemory::ReserveRegion(size_t size) {
264e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return RandomizedVirtualAlloc(size, MEM_RESERVE, PAGE_NOACCESS);
265e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
266e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
267e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
268e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
269e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
270e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (NULL == VirtualAlloc(base, size, MEM_COMMIT, prot)) {
271e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    return false;
272e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
273e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return true;
2743a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
2753a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
2763a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
277ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.orgbool VirtualMemory::Guard(void* address) {
278ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org  if (NULL == VirtualAlloc(address,
279ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org                           OS::CommitPageSize(),
280ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org                           MEM_COMMIT,
281c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                           PAGE_NOACCESS)) {
282ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org    return false;
283ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org  }
284ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org  return true;
285ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org}
286ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org
287ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org
288e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::UncommitRegion(void* base, size_t size) {
289e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return VirtualFree(base, size, MEM_DECOMMIT) != 0;
290e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
291e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
292e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
293e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::ReleaseRegion(void* base, size_t size) {
294e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return VirtualFree(base, 0, MEM_RELEASE) != 0;
295e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
296e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
297e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
29872204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.orgbool VirtualMemory::HasLazyCommits() {
29972204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org  // TODO(alph): implement for the platform.
30072204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org  return false;
30172204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org}
30272204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org
3035de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org} }  // namespace v8::base
304