V8 Project
platform-openbsd.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Platform-specific code for OpenBSD and NetBSD goes here. For the
6 // POSIX-compatible parts, the implementation is in platform-posix.cc.
7 
8 #include <pthread.h>
9 #include <semaphore.h>
10 #include <signal.h>
11 #include <stdlib.h>
12 #include <sys/resource.h>
13 #include <sys/syscall.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 
17 #include <errno.h>
18 #include <fcntl.h> // open
19 #include <stdarg.h>
20 #include <strings.h> // index
21 #include <sys/mman.h> // mmap & munmap
22 #include <sys/stat.h> // open
23 #include <sys/types.h> // mmap & munmap
24 #include <unistd.h> // sysconf
25 
26 #include <cmath>
27 
28 #undef MAP_TYPE
29 
30 #include "src/base/macros.h"
32 
33 
34 namespace v8 {
35 namespace base {
36 
37 
38 const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
39  if (std::isnan(time)) return "";
40  time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
41  struct tm* t = localtime(&tv);
42  if (NULL == t) return "";
43  return t->tm_zone;
44 }
45 
46 
47 double OS::LocalTimeOffset(TimezoneCache* cache) {
48  time_t tv = time(NULL);
49  struct tm* t = localtime(&tv);
50  // tm_gmtoff includes any daylight savings offset, so subtract it.
51  return static_cast<double>(t->tm_gmtoff * msPerSecond -
52  (t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
53 }
54 
55 
56 void* OS::Allocate(const size_t requested,
57  size_t* allocated,
58  bool is_executable) {
59  const size_t msize = RoundUp(requested, AllocateAlignment());
60  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
61  void* addr = OS::GetRandomMmapAddr();
62  void* mbase = mmap(addr, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
63  if (mbase == MAP_FAILED) return NULL;
64  *allocated = msize;
65  return mbase;
66 }
67 
68 
69 class PosixMemoryMappedFile : public OS::MemoryMappedFile {
70  public:
72  : file_(file), memory_(memory), size_(size) { }
74  virtual void* memory() { return memory_; }
75  virtual int size() { return size_; }
76  private:
77  FILE* file_;
78  void* memory_;
79  int size_;
80 };
81 
82 
83 OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
84  FILE* file = fopen(name, "r+");
85  if (file == NULL) return NULL;
86 
87  fseek(file, 0, SEEK_END);
88  int size = ftell(file);
89 
90  void* memory =
91  mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
92  return new PosixMemoryMappedFile(file, memory, size);
93 }
94 
95 
96 OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
97  void* initial) {
98  FILE* file = fopen(name, "w+");
99  if (file == NULL) return NULL;
100  int result = fwrite(initial, size, 1, file);
101  if (result < 1) {
102  fclose(file);
103  return NULL;
104  }
105  void* memory =
106  mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
107  return new PosixMemoryMappedFile(file, memory, size);
108 }
109 
110 
112  if (memory_) OS::Free(memory_, size_);
113  fclose(file_);
114 }
115 
116 
117 std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
118  std::vector<SharedLibraryAddress> result;
119  // This function assumes that the layout of the file is as follows:
120  // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
121  // If we encounter an unexpected situation we abort scanning further entries.
122  FILE* fp = fopen("/proc/self/maps", "r");
123  if (fp == NULL) return result;
124 
125  // Allocate enough room to be able to store a full file name.
126  const int kLibNameLen = FILENAME_MAX + 1;
127  char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
128 
129  // This loop will terminate once the scanning hits an EOF.
130  while (true) {
131  uintptr_t start, end;
132  char attr_r, attr_w, attr_x, attr_p;
133  // Parse the addresses and permission bits at the beginning of the line.
134  if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break;
135  if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break;
136 
137  int c;
138  if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') {
139  // Found a read-only executable entry. Skip characters until we reach
140  // the beginning of the filename or the end of the line.
141  do {
142  c = getc(fp);
143  } while ((c != EOF) && (c != '\n') && (c != '/'));
144  if (c == EOF) break; // EOF: Was unexpected, just exit.
145 
146  // Process the filename if found.
147  if (c == '/') {
148  ungetc(c, fp); // Push the '/' back into the stream to be read below.
149 
150  // Read to the end of the line. Exit if the read fails.
151  if (fgets(lib_name, kLibNameLen, fp) == NULL) break;
152 
153  // Drop the newline character read by fgets. We do not need to check
154  // for a zero-length string because we know that we at least read the
155  // '/' character.
156  lib_name[strlen(lib_name) - 1] = '\0';
157  } else {
158  // No library name found, just record the raw address range.
159  snprintf(lib_name, kLibNameLen,
160  "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end);
161  }
162  result.push_back(SharedLibraryAddress(lib_name, start, end));
163  } else {
164  // Entry not describing executable data. Skip to end of line to set up
165  // reading the next entry.
166  do {
167  c = getc(fp);
168  } while ((c != EOF) && (c != '\n'));
169  if (c == EOF) break;
170  }
171  }
172  free(lib_name);
173  fclose(fp);
174  return result;
175 }
176 
177 
178 void OS::SignalCodeMovingGC() {
179  // Support for ll_prof.py.
180  //
181  // The Linux profiler built into the kernel logs all mmap's with
182  // PROT_EXEC so that analysis tools can properly attribute ticks. We
183  // do a mmap with a name known by ll_prof.py and immediately munmap
184  // it. This injects a GC marker into the stream of events generated
185  // by the kernel and allows us to synchronize V8 code log and the
186  // kernel log.
187  int size = sysconf(_SC_PAGESIZE);
188  FILE* f = fopen(OS::GetGCFakeMMapFile(), "w+");
189  if (f == NULL) {
190  OS::PrintError("Failed to open %s\n", OS::GetGCFakeMMapFile());
191  OS::Abort();
192  }
193  void* addr = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_PRIVATE,
194  fileno(f), 0);
195  DCHECK(addr != MAP_FAILED);
196  OS::Free(addr, size);
197  fclose(f);
198 }
199 
200 
201 
202 // Constants used for mmap.
203 static const int kMmapFd = -1;
204 static const int kMmapFdOffset = 0;
205 
206 
207 VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
208 
209 
210 VirtualMemory::VirtualMemory(size_t size)
211  : address_(ReserveRegion(size)), size_(size) { }
212 
213 
214 VirtualMemory::VirtualMemory(size_t size, size_t alignment)
215  : address_(NULL), size_(0) {
216  DCHECK((alignment % OS::AllocateAlignment()) == 0);
217  size_t request_size = RoundUp(size + alignment,
218  static_cast<intptr_t>(OS::AllocateAlignment()));
219  void* reservation = mmap(OS::GetRandomMmapAddr(),
220  request_size,
221  PROT_NONE,
222  MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
223  kMmapFd,
224  kMmapFdOffset);
225  if (reservation == MAP_FAILED) return;
226 
227  uint8_t* base = static_cast<uint8_t*>(reservation);
228  uint8_t* aligned_base = RoundUp(base, alignment);
229  DCHECK_LE(base, aligned_base);
230 
231  // Unmap extra memory reserved before and after the desired block.
232  if (aligned_base != base) {
233  size_t prefix_size = static_cast<size_t>(aligned_base - base);
234  OS::Free(base, prefix_size);
235  request_size -= prefix_size;
236  }
237 
238  size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
239  DCHECK_LE(aligned_size, request_size);
240 
241  if (aligned_size != request_size) {
242  size_t suffix_size = request_size - aligned_size;
243  OS::Free(aligned_base + aligned_size, suffix_size);
244  request_size -= suffix_size;
245  }
246 
247  DCHECK(aligned_size == request_size);
248 
249  address_ = static_cast<void*>(aligned_base);
250  size_ = aligned_size;
251 }
252 
253 
254 VirtualMemory::~VirtualMemory() {
255  if (IsReserved()) {
256  bool result = ReleaseRegion(address(), size());
257  DCHECK(result);
258  USE(result);
259  }
260 }
261 
262 
263 bool VirtualMemory::IsReserved() {
264  return address_ != NULL;
265 }
266 
267 
268 void VirtualMemory::Reset() {
269  address_ = NULL;
270  size_ = 0;
271 }
272 
273 
274 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
275  return CommitRegion(address, size, is_executable);
276 }
277 
278 
279 bool VirtualMemory::Uncommit(void* address, size_t size) {
280  return UncommitRegion(address, size);
281 }
282 
283 
284 bool VirtualMemory::Guard(void* address) {
285  OS::Guard(address, OS::CommitPageSize());
286  return true;
287 }
288 
289 
290 void* VirtualMemory::ReserveRegion(size_t size) {
291  void* result = mmap(OS::GetRandomMmapAddr(),
292  size,
293  PROT_NONE,
294  MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
295  kMmapFd,
296  kMmapFdOffset);
297 
298  if (result == MAP_FAILED) return NULL;
299 
300  return result;
301 }
302 
303 
304 bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
305  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
306  if (MAP_FAILED == mmap(base,
307  size,
308  prot,
309  MAP_PRIVATE | MAP_ANON | MAP_FIXED,
310  kMmapFd,
311  kMmapFdOffset)) {
312  return false;
313  }
314  return true;
315 }
316 
317 
318 bool VirtualMemory::UncommitRegion(void* base, size_t size) {
319  return mmap(base,
320  size,
321  PROT_NONE,
322  MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED,
323  kMmapFd,
324  kMmapFdOffset) != MAP_FAILED;
325 }
326 
327 
328 bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
329  return munmap(base, size) == 0;
330 }
331 
332 
333 bool VirtualMemory::HasLazyCommits() {
334  // TODO(alph): implement for the platform.
335  return false;
336 }
337 
338 } } // namespace v8::base
static MemoryMappedFile * create(const char *name, int size, void *initial)
static MemoryMappedFile * open(const char *name)
static void * GetRandomMmapAddr()
static size_t AllocateAlignment()
static void SignalCodeMovingGC()
static void Abort()
static void * Allocate(const size_t requested, size_t *allocated, bool is_executable)
static const char * LocalTimezone(double time, TimezoneCache *cache)
static std::vector< SharedLibraryAddress > GetSharedLibraryAddresses()
static double LocalTimeOffset(TimezoneCache *cache)
static void PrintError(const char *format,...)
static void Free(void *address, const size_t size)
static const int msPerSecond
Definition: platform.h:303
PosixMemoryMappedFile(FILE *file, void *memory, int size)
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes A file to write the raw context snapshot bytes Write V8 startup blob file(mksnapshot only)") DEFINE_BOOL(profile_hydrogen_code_stub_compilation
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK_LE(v1, v2)
Definition: logging.h:210
#define DCHECK(condition)
Definition: logging.h:205
void USE(T)
Definition: macros.h:322
T RoundUp(T x, intptr_t m)
Definition: macros.h:407
#define V8PRIxPTR
Definition: macros.h:363
static const int kMmapFdOffset
static const int kMmapFd
const Register fp
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20