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/time.h>
143a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <sys/mman.h>   // mmap & munmap
153a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#include <unistd.h>     // sysconf
163a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
173a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#undef MAP_TYPE
183a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
19196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
203a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
211e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/win32-headers.h"
22196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/platform.h"
233a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
243a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgnamespace v8 {
253a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgnamespace internal {
263a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
273a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
286b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgconst char* OS::LocalTimezone(double time, TimezoneCache* cache) {
2977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  if (std::isnan(time)) return "";
30e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
313a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  struct tm* t = localtime(&tv);
323a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if (NULL == t) return "";
333a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  return tzname[0];  // The location of the timezone string on Cygwin.
343a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
353a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
363a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
376b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgdouble OS::LocalTimeOffset(TimezoneCache* cache) {
383a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // On Cygwin, struct tm does not contain a tm_gmtoff field.
393a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  time_t utc = time(NULL);
403a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  ASSERT(utc != -1);
413a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  struct tm* loc = localtime(&utc);
423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  ASSERT(loc != NULL);
433a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // time - localtime includes any daylight savings offset, so subtract it.
443a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  return static_cast<double>((mktime(loc) - utc) * msPerSecond -
453a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                             (loc->tm_isdst > 0 ? 3600 * msPerSecond : 0));
463a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
473a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
483a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
493a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgvoid* OS::Allocate(const size_t requested,
503a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                   size_t* allocated,
513a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                   bool is_executable) {
523a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  const size_t msize = RoundUp(requested, sysconf(_SC_PAGESIZE));
533a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
543a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
551845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  if (mbase == MAP_FAILED) return NULL;
563a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  *allocated = msize;
573a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  return mbase;
583a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
593a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
603a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
613a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgclass PosixMemoryMappedFile : public OS::MemoryMappedFile {
623a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org public:
633a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  PosixMemoryMappedFile(FILE* file, void* memory, int size)
643a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    : file_(file), memory_(memory), size_(size) { }
653a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  virtual ~PosixMemoryMappedFile();
663a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  virtual void* memory() { return memory_; }
673a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  virtual int size() { return size_; }
683a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org private:
693a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  FILE* file_;
703a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void* memory_;
713a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  int size_;
723a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org};
733a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
743a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
753a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
763a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  FILE* file = fopen(name, "r+");
773a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if (file == NULL) return NULL;
783a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
793a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  fseek(file, 0, SEEK_END);
803a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  int size = ftell(file);
813a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
823a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void* memory =
833a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
843a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  return new PosixMemoryMappedFile(file, memory, size);
853a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
863a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
873a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
883a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
893a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    void* initial) {
903a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  FILE* file = fopen(name, "w+");
913a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if (file == NULL) return NULL;
923a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  int result = fwrite(initial, size, 1, file);
933a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if (result < 1) {
943a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    fclose(file);
953a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    return NULL;
963a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  }
973a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void* memory =
983a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
993a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  return new PosixMemoryMappedFile(file, memory, size);
1003a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
1013a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1023a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1033a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgPosixMemoryMappedFile::~PosixMemoryMappedFile() {
1043a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if (memory_) munmap(memory_, size_);
1053a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  fclose(file_);
1063a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
1073a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1083a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1091845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgstd::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
1101845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  std::vector<SharedLibraryAddresses> result;
1113a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // This function assumes that the layout of the file is as follows:
1123a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
1133a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // If we encounter an unexpected situation we abort scanning further entries.
1143a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  FILE* fp = fopen("/proc/self/maps", "r");
1151845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  if (fp == NULL) return result;
1163a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1173a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // Allocate enough room to be able to store a full file name.
1183a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  const int kLibNameLen = FILENAME_MAX + 1;
1193a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
1203a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1213a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // This loop will terminate once the scanning hits an EOF.
1223a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  while (true) {
1233a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    uintptr_t start, end;
1243a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    char attr_r, attr_w, attr_x, attr_p;
1253a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    // Parse the addresses and permission bits at the beginning of the line.
1263a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break;
1273a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break;
1283a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1293a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    int c;
1303a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') {
1313a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      // Found a read-only executable entry. Skip characters until we reach
1323a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      // the beginning of the filename or the end of the line.
1333a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      do {
1343a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        c = getc(fp);
1353a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      } while ((c != EOF) && (c != '\n') && (c != '/'));
1363a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      if (c == EOF) break;  // EOF: Was unexpected, just exit.
1373a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1383a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      // Process the filename if found.
1393a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      if (c == '/') {
1403a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        ungetc(c, fp);  // Push the '/' back into the stream to be read below.
1413a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        // Read to the end of the line. Exit if the read fails.
1433a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        if (fgets(lib_name, kLibNameLen, fp) == NULL) break;
1443a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1453a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        // Drop the newline character read by fgets. We do not need to check
1463a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        // for a zero-length string because we know that we at least read the
1473a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        // '/' character.
1483a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        lib_name[strlen(lib_name) - 1] = '\0';
1493a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      } else {
1503a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        // No library name found, just record the raw address range.
1513a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        snprintf(lib_name, kLibNameLen,
1523a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                 "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end);
1533a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      }
1541845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org      result.push_back(SharedLibraryAddress(lib_name, start, end));
1553a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    } else {
156f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com      // Entry not describing executable data. Skip to end of line to set up
1573a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      // reading the next entry.
1583a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      do {
1593a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        c = getc(fp);
1603a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      } while ((c != EOF) && (c != '\n'));
1613a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      if (c == EOF) break;
1623a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    }
1633a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  }
1643a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  free(lib_name);
1653a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  fclose(fp);
1661845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  return result;
1673a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
1683a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1693a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1703a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgvoid OS::SignalCodeMovingGC() {
1713a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // Nothing to do on Cygwin.
1723a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
1733a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
1743a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
175c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// The VirtualMemory implementation is taken from platform-win32.cc.
176c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// The mmap-based virtual memory implementation as it is used on most posix
177c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// platforms does not work well because Cygwin does not support MAP_FIXED.
178c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// This causes VirtualMemory::Commit to not always commit the memory region
179c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org// specified.
180c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org
181e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgstatic void* GetRandomAddr() {
182e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Isolate* isolate = Isolate::UncheckedCurrent();
183e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Note that the current isolate isn't set up in a call path via
184e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // CpuFeatures::Probe. We don't care about randomization in this case because
185e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // the code page is immediately freed.
186e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (isolate != NULL) {
187e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // The address range used to randomize RWX allocations in OS::Allocate
188e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Try not to map pages into the default range that windows loads DLLs
189e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Use a multiple of 64k to prevent committing unused memory.
190e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Note: This does not guarantee RWX regions will be within the
191e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // range kAllocationRandomAddressMin to kAllocationRandomAddressMax
192e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#ifdef V8_HOST_ARCH_64_BIT
193e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    static const intptr_t kAllocationRandomAddressMin = 0x0000000080000000;
194e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    static const intptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000;
195e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#else
196e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    static const intptr_t kAllocationRandomAddressMin = 0x04000000;
197e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000;
198e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#endif
199c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    uintptr_t address =
200c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org        (isolate->random_number_generator()->NextInt() << kPageSizeBits) |
201c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org        kAllocationRandomAddressMin;
202e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    address &= kAllocationRandomAddressMax;
203e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    return reinterpret_cast<void *>(address);
204e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
205e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return NULL;
206e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
207e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
208e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
209e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgstatic void* RandomizedVirtualAlloc(size_t size, int action, int protection) {
210e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  LPVOID base = NULL;
211e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
212e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_NOACCESS) {
213e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // For exectutable pages try and randomize the allocation address
214e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    for (size_t attempts = 0; base == NULL && attempts < 3; ++attempts) {
215e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      base = VirtualAlloc(GetRandomAddr(), size, action, protection);
216e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    }
217e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
218e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
219e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // After three attempts give up and let the OS find an address to use.
220e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (base == NULL) base = VirtualAlloc(NULL, size, action, protection);
221e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
222e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return base;
223c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org}
2243a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
2253a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
226e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
227e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
228e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
229e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgVirtualMemory::VirtualMemory(size_t size)
230e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    : address_(ReserveRegion(size)), size_(size) { }
231e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
232e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
233e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgVirtualMemory::VirtualMemory(size_t size, size_t alignment)
234e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    : address_(NULL), size_(0) {
235e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment())));
236e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  size_t request_size = RoundUp(size + alignment,
237e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                static_cast<intptr_t>(OS::AllocateAlignment()));
238e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  void* address = ReserveRegion(request_size);
239e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (address == NULL) return;
240e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Address base = RoundUp(static_cast<Address>(address), alignment);
241e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Try reducing the size by freeing and then reallocating a specific area.
242e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  bool result = ReleaseRegion(address, request_size);
243e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  USE(result);
244e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(result);
245e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  address = VirtualAlloc(base, size, MEM_RESERVE, PAGE_NOACCESS);
246e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (address != NULL) {
247e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    request_size = size;
248e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    ASSERT(base == static_cast<Address>(address));
249e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  } else {
250e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Resizing failed, just go with a bigger area.
251e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    address = ReserveRegion(request_size);
252e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    if (address == NULL) return;
253e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
254e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  address_ = address;
255e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  size_ = request_size;
2563a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
2573a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
2583a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
2593a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgVirtualMemory::~VirtualMemory() {
2603a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if (IsReserved()) {
261e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    bool result = ReleaseRegion(address_, size_);
262e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    ASSERT(result);
263e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    USE(result);
2643a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  }
2653a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
2663a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
2673a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
268e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::IsReserved() {
269e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return address_ != NULL;
270e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
2713a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
272e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
273e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgvoid VirtualMemory::Reset() {
274e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  address_ = NULL;
275e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  size_ = 0;
276e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
277e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
278e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
279e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
280e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return CommitRegion(address, size, is_executable);
2813a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
2823a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
2833a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
2843a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgbool VirtualMemory::Uncommit(void* address, size_t size) {
285c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  ASSERT(IsReserved());
286e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return UncommitRegion(address, size);
287e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
288e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
289e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
290e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgvoid* VirtualMemory::ReserveRegion(size_t size) {
291e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return RandomizedVirtualAlloc(size, MEM_RESERVE, PAGE_NOACCESS);
292e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
293e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
294e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
295e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
296e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
297e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (NULL == VirtualAlloc(base, size, MEM_COMMIT, prot)) {
298e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    return false;
299e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
300e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return true;
3013a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
3023a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
3033a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
304ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.orgbool VirtualMemory::Guard(void* address) {
305ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org  if (NULL == VirtualAlloc(address,
306ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org                           OS::CommitPageSize(),
307ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org                           MEM_COMMIT,
308c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                           PAGE_NOACCESS)) {
309ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org    return false;
310ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org  }
311ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org  return true;
312ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org}
313ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org
314ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org
315e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::UncommitRegion(void* base, size_t size) {
316e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return VirtualFree(base, size, MEM_DECOMMIT) != 0;
317e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
318e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
319e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
320e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool VirtualMemory::ReleaseRegion(void* base, size_t size) {
321e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return VirtualFree(base, 0, MEM_RELEASE) != 0;
322e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
323e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
324e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
32572204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.orgbool VirtualMemory::HasLazyCommits() {
32672204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org  // TODO(alph): implement for the platform.
32772204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org  return false;
32872204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org}
32972204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org
3303a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} }  // namespace v8::internal
331