v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
platform-posix.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 // Platform specific code for POSIX goes here. This is not a platform on its
29 // own but contains the parts which are the same across POSIX platforms Linux,
30 // Mac OS, FreeBSD and OpenBSD.
31 
32 #include "platform-posix.h"
33 
34 #include <unistd.h>
35 #include <errno.h>
36 #include <time.h>
37 
38 #include <sys/mman.h>
39 #include <sys/socket.h>
40 #include <sys/resource.h>
41 #include <sys/time.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 
45 #include <arpa/inet.h>
46 #include <netinet/in.h>
47 #include <netdb.h>
48 
49 #undef MAP_TYPE
50 
51 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
52 #define LOG_TAG "v8"
53 #include <android/log.h>
54 #endif
55 
56 #include "v8.h"
57 
58 #include "codegen.h"
59 #include "platform.h"
60 
61 namespace v8 {
62 namespace internal {
63 
64 
65 // Maximum size of the virtual memory. 0 means there is no artificial
66 // limit.
67 
69  struct rlimit limit;
70  int result = getrlimit(RLIMIT_DATA, &limit);
71  if (result != 0) return 0;
72  return limit.rlim_cur;
73 }
74 
75 
76 intptr_t OS::CommitPageSize() {
77  static intptr_t page_size = getpagesize();
78  return page_size;
79 }
80 
81 
82 #ifndef __CYGWIN__
83 // Get rid of writable permission on code allocations.
84 void OS::ProtectCode(void* address, const size_t size) {
85  mprotect(address, size, PROT_READ | PROT_EXEC);
86 }
87 
88 
89 // Create guard pages.
90 void OS::Guard(void* address, const size_t size) {
91  mprotect(address, size, PROT_NONE);
92 }
93 #endif // __CYGWIN__
94 
95 
97  Isolate* isolate = Isolate::UncheckedCurrent();
98  // Note that the current isolate isn't set up in a call path via
99  // CpuFeatures::Probe. We don't care about randomization in this case because
100  // the code page is immediately freed.
101  if (isolate != NULL) {
102 #ifdef V8_TARGET_ARCH_X64
103  uint64_t rnd1 = V8::RandomPrivate(isolate);
104  uint64_t rnd2 = V8::RandomPrivate(isolate);
105  uint64_t raw_addr = (rnd1 << 32) ^ rnd2;
106  // Currently available CPUs have 48 bits of virtual addressing. Truncate
107  // the hint address to 46 bits to give the kernel a fighting chance of
108  // fulfilling our placement request.
109  raw_addr &= V8_UINT64_C(0x3ffffffff000);
110 #else
111  uint32_t raw_addr = V8::RandomPrivate(isolate);
112  // The range 0x20000000 - 0x60000000 is relatively unpopulated across a
113  // variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macos
114  // 10.6 and 10.7.
115  raw_addr &= 0x3ffff000;
116  raw_addr += 0x20000000;
117 #endif
118  return reinterpret_cast<void*>(raw_addr);
119  }
120  return NULL;
121 }
122 
123 
124 // ----------------------------------------------------------------------------
125 // Math functions
126 
127 double modulo(double x, double y) {
128  return fmod(x, y);
129 }
130 
131 
132 #define UNARY_MATH_FUNCTION(name, generator) \
133 static UnaryMathFunction fast_##name##_function = NULL; \
134 void init_fast_##name##_function() { \
135  fast_##name##_function = generator; \
136 } \
137 double fast_##name(double x) { \
138  return (*fast_##name##_function)(x); \
139 }
140 
142 UNARY_MATH_FUNCTION(cos, CreateTranscendentalFunction(TranscendentalCache::COS))
143 UNARY_MATH_FUNCTION(tan, CreateTranscendentalFunction(TranscendentalCache::TAN))
144 UNARY_MATH_FUNCTION(log, CreateTranscendentalFunction(TranscendentalCache::LOG))
146 
147 #undef MATH_FUNCTION
148 
149 
150 double OS::nan_value() {
151  // NAN from math.h is defined in C99 and not in POSIX.
152  return NAN;
153 }
154 
155 
157  return static_cast<int>(getpid());
158 }
159 
160 
161 // ----------------------------------------------------------------------------
162 // POSIX date/time support.
163 //
164 
165 int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) {
166  struct rusage usage;
167 
168  if (getrusage(RUSAGE_SELF, &usage) < 0) return -1;
169  *secs = usage.ru_utime.tv_sec;
170  *usecs = usage.ru_utime.tv_usec;
171  return 0;
172 }
173 
174 
175 double OS::TimeCurrentMillis() {
176  struct timeval tv;
177  if (gettimeofday(&tv, NULL) < 0) return 0.0;
178  return (static_cast<double>(tv.tv_sec) * 1000) +
179  (static_cast<double>(tv.tv_usec) / 1000);
180 }
181 
182 
183 int64_t OS::Ticks() {
184  // gettimeofday has microsecond resolution.
185  struct timeval tv;
186  if (gettimeofday(&tv, NULL) < 0)
187  return 0;
188  return (static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec;
189 }
190 
191 
192 double OS::DaylightSavingsOffset(double time) {
193  if (isnan(time)) return nan_value();
194  time_t tv = static_cast<time_t>(floor(time/msPerSecond));
195  struct tm* t = localtime(&tv);
196  if (NULL == t) return nan_value();
197  return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;
198 }
199 
200 
201 int OS::GetLastError() {
202  return errno;
203 }
204 
205 
206 // ----------------------------------------------------------------------------
207 // POSIX stdio support.
208 //
209 
210 FILE* OS::FOpen(const char* path, const char* mode) {
211  FILE* file = fopen(path, mode);
212  if (file == NULL) return NULL;
213  struct stat file_stat;
214  if (fstat(fileno(file), &file_stat) != 0) return NULL;
215  bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0);
216  if (is_regular_file) return file;
217  fclose(file);
218  return NULL;
219 }
220 
221 
222 bool OS::Remove(const char* path) {
223  return (remove(path) == 0);
224 }
225 
226 
228  return tmpfile();
229 }
230 
231 
232 const char* const OS::LogFileOpenMode = "w";
233 
234 
235 void OS::Print(const char* format, ...) {
236  va_list args;
237  va_start(args, format);
238  VPrint(format, args);
239  va_end(args);
240 }
241 
242 
243 void OS::VPrint(const char* format, va_list args) {
244 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
245  __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
246 #else
247  vprintf(format, args);
248 #endif
249 }
250 
251 
252 void OS::FPrint(FILE* out, const char* format, ...) {
253  va_list args;
254  va_start(args, format);
255  VFPrint(out, format, args);
256  va_end(args);
257 }
258 
259 
260 void OS::VFPrint(FILE* out, const char* format, va_list args) {
261 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
262  __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
263 #else
264  vfprintf(out, format, args);
265 #endif
266 }
267 
268 
269 void OS::PrintError(const char* format, ...) {
270  va_list args;
271  va_start(args, format);
272  VPrintError(format, args);
273  va_end(args);
274 }
275 
276 
277 void OS::VPrintError(const char* format, va_list args) {
278 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
279  __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args);
280 #else
281  vfprintf(stderr, format, args);
282 #endif
283 }
284 
285 
286 int OS::SNPrintF(Vector<char> str, const char* format, ...) {
287  va_list args;
288  va_start(args, format);
289  int result = VSNPrintF(str, format, args);
290  va_end(args);
291  return result;
292 }
293 
294 
295 int OS::VSNPrintF(Vector<char> str,
296  const char* format,
297  va_list args) {
298  int n = vsnprintf(str.start(), str.length(), format, args);
299  if (n < 0 || n >= str.length()) {
300  // If the length is zero, the assignment fails.
301  if (str.length() > 0)
302  str[str.length() - 1] = '\0';
303  return -1;
304  } else {
305  return n;
306  }
307 }
308 
309 
310 #if defined(V8_TARGET_ARCH_IA32)
311 static OS::MemCopyFunction memcopy_function = NULL;
312 // Defined in codegen-ia32.cc.
313 OS::MemCopyFunction CreateMemCopyFunction();
314 
315 // Copy memory area to disjoint memory area.
316 void OS::MemCopy(void* dest, const void* src, size_t size) {
317  // Note: here we rely on dependent reads being ordered. This is true
318  // on all architectures we currently support.
319  (*memcopy_function)(dest, src, size);
320 #ifdef DEBUG
321  CHECK_EQ(0, memcmp(dest, src, size));
322 #endif
323 }
324 #endif // V8_TARGET_ARCH_IA32
325 
326 
328 #if defined(V8_TARGET_ARCH_IA32)
329  memcopy_function = CreateMemCopyFunction();
330 #endif
331  init_fast_sin_function();
332  init_fast_cos_function();
333  init_fast_tan_function();
334  init_fast_log_function();
335  init_fast_sqrt_function();
336 }
337 
338 // ----------------------------------------------------------------------------
339 // POSIX string support.
340 //
341 
342 char* OS::StrChr(char* str, int c) {
343  return strchr(str, c);
344 }
345 
346 
347 void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
348  strncpy(dest.start(), src, n);
349 }
350 
351 
352 // ----------------------------------------------------------------------------
353 // POSIX socket support.
354 //
355 
356 class POSIXSocket : public Socket {
357  public:
358  explicit POSIXSocket() {
359  // Create the socket.
360  socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
361  if (IsValid()) {
362  // Allow rapid reuse.
363  static const int kOn = 1;
364  int ret = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
365  &kOn, sizeof(kOn));
366  ASSERT(ret == 0);
367  USE(ret);
368  }
369  }
370  explicit POSIXSocket(int socket): socket_(socket) { }
371  virtual ~POSIXSocket() { Shutdown(); }
372 
373  // Server initialization.
374  bool Bind(const int port);
375  bool Listen(int backlog) const;
376  Socket* Accept() const;
377 
378  // Client initialization.
379  bool Connect(const char* host, const char* port);
380 
381  // Shutdown socket for both read and write.
382  bool Shutdown();
383 
384  // Data Transimission
385  int Send(const char* data, int len) const;
386  int Receive(char* data, int len) const;
387 
388  bool SetReuseAddress(bool reuse_address);
389 
390  bool IsValid() const { return socket_ != -1; }
391 
392  private:
393  int socket_;
394 };
395 
396 
397 bool POSIXSocket::Bind(const int port) {
398  if (!IsValid()) {
399  return false;
400  }
401 
402  sockaddr_in addr;
403  memset(&addr, 0, sizeof(addr));
404  addr.sin_family = AF_INET;
405  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
406  addr.sin_port = htons(port);
407  int status = bind(socket_,
408  BitCast<struct sockaddr *>(&addr),
409  sizeof(addr));
410  return status == 0;
411 }
412 
413 
414 bool POSIXSocket::Listen(int backlog) const {
415  if (!IsValid()) {
416  return false;
417  }
418 
419  int status = listen(socket_, backlog);
420  return status == 0;
421 }
422 
423 
425  if (!IsValid()) {
426  return NULL;
427  }
428 
429  int socket;
430  do {
431  socket = accept(socket_, NULL, NULL);
432  } while (socket == -1 && errno == EINTR);
433 
434  if (socket == -1) {
435  return NULL;
436  } else {
437  return new POSIXSocket(socket);
438  }
439 }
440 
441 
442 bool POSIXSocket::Connect(const char* host, const char* port) {
443  if (!IsValid()) {
444  return false;
445  }
446 
447  // Lookup host and port.
448  struct addrinfo *result = NULL;
449  struct addrinfo hints;
450  memset(&hints, 0, sizeof(addrinfo));
451  hints.ai_family = AF_INET;
452  hints.ai_socktype = SOCK_STREAM;
453  hints.ai_protocol = IPPROTO_TCP;
454  int status = getaddrinfo(host, port, &hints, &result);
455  if (status != 0) {
456  return false;
457  }
458 
459  // Connect.
460  do {
461  status = connect(socket_, result->ai_addr, result->ai_addrlen);
462  } while (status == -1 && errno == EINTR);
463  freeaddrinfo(result);
464  return status == 0;
465 }
466 
467 
469  if (IsValid()) {
470  // Shutdown socket for both read and write.
471  int status = shutdown(socket_, SHUT_RDWR);
472  close(socket_);
473  socket_ = -1;
474  return status == 0;
475  }
476  return true;
477 }
478 
479 
480 int POSIXSocket::Send(const char* data, int len) const {
481  if (len <= 0) return 0;
482  int written = 0;
483  while (written < len) {
484  int status = send(socket_, data + written, len - written, 0);
485  if (status == 0) {
486  break;
487  } else if (status > 0) {
488  written += status;
489  } else if (errno != EINTR) {
490  return 0;
491  }
492  }
493  return written;
494 }
495 
496 
497 int POSIXSocket::Receive(char* data, int len) const {
498  if (len <= 0) return 0;
499  int status;
500  do {
501  status = recv(socket_, data, len, 0);
502  } while (status == -1 && errno == EINTR);
503  return (status < 0) ? 0 : status;
504 }
505 
506 
507 bool POSIXSocket::SetReuseAddress(bool reuse_address) {
508  int on = reuse_address ? 1 : 0;
509  int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
510  return status == 0;
511 }
512 
513 
515  // Nothing to do on POSIX.
516  return true;
517 }
518 
519 
521  return errno;
522 }
523 
524 
526  return htons(value);
527 }
528 
529 
531  return ntohs(value);
532 }
533 
534 
535 uint32_t Socket::HToN(uint32_t value) {
536  return htonl(value);
537 }
538 
539 
540 uint32_t Socket::NToH(uint32_t value) {
541  return ntohl(value);
542 }
543 
544 
546  return new POSIXSocket();
547 }
548 
549 
550 } } // namespace v8::internal
#define CHECK_EQ(expected, value)
Definition: checks.h:219
static int VSNPrintF(Vector< char > str, const char *format, va_list args)
static int64_t Ticks()
#define LOG(isolate, Call)
Definition: log.h:81
static FILE * OpenTemporaryFile()
int Send(const char *data, int len) const
static void * GetRandomMmapAddr()
static int GetUserTime(uint32_t *secs, uint32_t *usecs)
#define UNARY_MATH_FUNCTION(name, generator)
#define ASSERT(condition)
Definition: checks.h:270
static void VFPrint(FILE *out, const char *format, va_list args)
unsigned short uint16_t
Definition: unicode.cc:46
int isnan(double x)
bool Listen(int backlog) const
Socket * Accept() const
T * start() const
Definition: utils.h:390
static void MemCopy(void *dest, const void *src, size_t size)
Definition: platform.h:339
static void ProtectCode(void *address, const size_t size)
void POSIXPostSetUp()
static FILE * FOpen(const char *path, const char *mode)
static void VPrint(const char *format, va_list args)
UnaryMathFunction CreateSqrtFunction()
static void Guard(void *address, const size_t size)
static void VPrintError(const char *format, va_list args)
double modulo(double x, double y)
static int GetCurrentProcessId()
static uint16_t NToH(uint16_t value)
static double TimeCurrentMillis()
static uint16_t HToN(uint16_t value)
static void Print(const char *format,...)
static int SNPrintF(Vector< char > str, const char *format,...)
static double nan_value()
static uint32_t RandomPrivate(Isolate *isolate)
Definition: v8.cc:181
static void PrintError(const char *format,...)
void USE(T)
Definition: globals.h:289
static void StrNCpy(Vector< char > dest, const char *src, size_t n)
bool SetReuseAddress(bool reuse_address)
static double DaylightSavingsOffset(double time)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
bool Bind(const int port)
static bool Remove(const char *path)
static int GetLastError()
static intptr_t MaxVirtualMemory()
static void FPrint(FILE *out, const char *format,...)
int Receive(char *data, int len) const
static intptr_t CommitPageSize()
static const char *const LogFileOpenMode
Definition: platform.h:186
UnaryMathFunction CreateTranscendentalFunction(TranscendentalCache::Type type)
static char * StrChr(char *str, int c)
static Socket * CreateSocket()
bool Connect(const char *host, const char *port)