v8  3.11.10(node0.8.26)
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 
156 // ----------------------------------------------------------------------------
157 // POSIX date/time support.
158 //
159 
160 int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) {
161  struct rusage usage;
162 
163  if (getrusage(RUSAGE_SELF, &usage) < 0) return -1;
164  *secs = usage.ru_utime.tv_sec;
165  *usecs = usage.ru_utime.tv_usec;
166  return 0;
167 }
168 
169 
170 double OS::TimeCurrentMillis() {
171  struct timeval tv;
172  if (gettimeofday(&tv, NULL) < 0) return 0.0;
173  return (static_cast<double>(tv.tv_sec) * 1000) +
174  (static_cast<double>(tv.tv_usec) / 1000);
175 }
176 
177 
178 int64_t OS::Ticks() {
179  // gettimeofday has microsecond resolution.
180  struct timeval tv;
181  if (gettimeofday(&tv, NULL) < 0)
182  return 0;
183  return (static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec;
184 }
185 
186 
187 double OS::DaylightSavingsOffset(double time) {
188  if (isnan(time)) return nan_value();
189  time_t tv = static_cast<time_t>(floor(time/msPerSecond));
190  struct tm* t = localtime(&tv);
191  if (NULL == t) return nan_value();
192  return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;
193 }
194 
195 
196 int OS::GetLastError() {
197  return errno;
198 }
199 
200 
201 // ----------------------------------------------------------------------------
202 // POSIX stdio support.
203 //
204 
205 FILE* OS::FOpen(const char* path, const char* mode) {
206  FILE* file = fopen(path, mode);
207  if (file == NULL) return NULL;
208  struct stat file_stat;
209  if (fstat(fileno(file), &file_stat) != 0) return NULL;
210  bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0);
211  if (is_regular_file) return file;
212  fclose(file);
213  return NULL;
214 }
215 
216 
217 bool OS::Remove(const char* path) {
218  return (remove(path) == 0);
219 }
220 
221 
223  return tmpfile();
224 }
225 
226 
227 const char* const OS::LogFileOpenMode = "w";
228 
229 
230 void OS::Print(const char* format, ...) {
231  va_list args;
232  va_start(args, format);
233  VPrint(format, args);
234  va_end(args);
235 }
236 
237 
238 void OS::VPrint(const char* format, va_list args) {
239 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
240  __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
241 #else
242  vprintf(format, args);
243 #endif
244 }
245 
246 
247 void OS::FPrint(FILE* out, const char* format, ...) {
248  va_list args;
249  va_start(args, format);
250  VFPrint(out, format, args);
251  va_end(args);
252 }
253 
254 
255 void OS::VFPrint(FILE* out, const char* format, va_list args) {
256 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
257  __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
258 #else
259  vfprintf(out, format, args);
260 #endif
261 }
262 
263 
264 void OS::PrintError(const char* format, ...) {
265  va_list args;
266  va_start(args, format);
267  VPrintError(format, args);
268  va_end(args);
269 }
270 
271 
272 void OS::VPrintError(const char* format, va_list args) {
273 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
274  __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args);
275 #else
276  vfprintf(stderr, format, args);
277 #endif
278 }
279 
280 
281 int OS::SNPrintF(Vector<char> str, const char* format, ...) {
282  va_list args;
283  va_start(args, format);
284  int result = VSNPrintF(str, format, args);
285  va_end(args);
286  return result;
287 }
288 
289 
290 int OS::VSNPrintF(Vector<char> str,
291  const char* format,
292  va_list args) {
293  int n = vsnprintf(str.start(), str.length(), format, args);
294  if (n < 0 || n >= str.length()) {
295  // If the length is zero, the assignment fails.
296  if (str.length() > 0)
297  str[str.length() - 1] = '\0';
298  return -1;
299  } else {
300  return n;
301  }
302 }
303 
304 
305 #if defined(V8_TARGET_ARCH_IA32)
306 static OS::MemCopyFunction memcopy_function = NULL;
307 // Defined in codegen-ia32.cc.
308 OS::MemCopyFunction CreateMemCopyFunction();
309 
310 // Copy memory area to disjoint memory area.
311 void OS::MemCopy(void* dest, const void* src, size_t size) {
312  // Note: here we rely on dependent reads being ordered. This is true
313  // on all architectures we currently support.
314  (*memcopy_function)(dest, src, size);
315 #ifdef DEBUG
316  CHECK_EQ(0, memcmp(dest, src, size));
317 #endif
318 }
319 #endif // V8_TARGET_ARCH_IA32
320 
321 
323 #if defined(V8_TARGET_ARCH_IA32)
324  memcopy_function = CreateMemCopyFunction();
325 #endif
326  init_fast_sin_function();
327  init_fast_cos_function();
328  init_fast_tan_function();
329  init_fast_log_function();
330  init_fast_sqrt_function();
331 }
332 
333 // ----------------------------------------------------------------------------
334 // POSIX string support.
335 //
336 
337 char* OS::StrChr(char* str, int c) {
338  return strchr(str, c);
339 }
340 
341 
342 void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
343  strncpy(dest.start(), src, n);
344 }
345 
346 
347 // ----------------------------------------------------------------------------
348 // POSIX socket support.
349 //
350 
351 class POSIXSocket : public Socket {
352  public:
353  explicit POSIXSocket() {
354  // Create the socket.
355  socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
356  if (IsValid()) {
357  // Allow rapid reuse.
358  static const int kOn = 1;
359  int ret = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
360  &kOn, sizeof(kOn));
361  ASSERT(ret == 0);
362  USE(ret);
363  }
364  }
365  explicit POSIXSocket(int socket): socket_(socket) { }
366  virtual ~POSIXSocket() { Shutdown(); }
367 
368  // Server initialization.
369  bool Bind(const int port);
370  bool Listen(int backlog) const;
371  Socket* Accept() const;
372 
373  // Client initialization.
374  bool Connect(const char* host, const char* port);
375 
376  // Shutdown socket for both read and write.
377  bool Shutdown();
378 
379  // Data Transimission
380  int Send(const char* data, int len) const;
381  int Receive(char* data, int len) const;
382 
383  bool SetReuseAddress(bool reuse_address);
384 
385  bool IsValid() const { return socket_ != -1; }
386 
387  private:
388  int socket_;
389 };
390 
391 
392 bool POSIXSocket::Bind(const int port) {
393  if (!IsValid()) {
394  return false;
395  }
396 
397  sockaddr_in addr;
398  memset(&addr, 0, sizeof(addr));
399  addr.sin_family = AF_INET;
400  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
401  addr.sin_port = htons(port);
402  int status = bind(socket_,
403  BitCast<struct sockaddr *>(&addr),
404  sizeof(addr));
405  return status == 0;
406 }
407 
408 
409 bool POSIXSocket::Listen(int backlog) const {
410  if (!IsValid()) {
411  return false;
412  }
413 
414  int status = listen(socket_, backlog);
415  return status == 0;
416 }
417 
418 
420  if (!IsValid()) {
421  return NULL;
422  }
423 
424  int socket;
425  do {
426  socket = accept(socket_, NULL, NULL);
427  } while (socket == -1 && errno == EINTR);
428 
429  if (socket == -1) {
430  return NULL;
431  } else {
432  return new POSIXSocket(socket);
433  }
434 }
435 
436 
437 bool POSIXSocket::Connect(const char* host, const char* port) {
438  if (!IsValid()) {
439  return false;
440  }
441 
442  // Lookup host and port.
443  struct addrinfo *result = NULL;
444  struct addrinfo hints;
445  memset(&hints, 0, sizeof(addrinfo));
446  hints.ai_family = AF_INET;
447  hints.ai_socktype = SOCK_STREAM;
448  hints.ai_protocol = IPPROTO_TCP;
449  int status = getaddrinfo(host, port, &hints, &result);
450  if (status != 0) {
451  return false;
452  }
453 
454  // Connect.
455  do {
456  status = connect(socket_, result->ai_addr, result->ai_addrlen);
457  } while (status == -1 && errno == EINTR);
458  freeaddrinfo(result);
459  return status == 0;
460 }
461 
462 
464  if (IsValid()) {
465  // Shutdown socket for both read and write.
466  int status = shutdown(socket_, SHUT_RDWR);
467  close(socket_);
468  socket_ = -1;
469  return status == 0;
470  }
471  return true;
472 }
473 
474 
475 int POSIXSocket::Send(const char* data, int len) const {
476  if (len <= 0) return 0;
477  int written = 0;
478  while (written < len) {
479  int status = send(socket_, data + written, len - written, 0);
480  if (status == 0) {
481  break;
482  } else if (status > 0) {
483  written += status;
484  } else if (errno != EINTR) {
485  return 0;
486  }
487  }
488  return written;
489 }
490 
491 
492 int POSIXSocket::Receive(char* data, int len) const {
493  if (len <= 0) return 0;
494  int status;
495  do {
496  status = recv(socket_, data, len, 0);
497  } while (status == -1 && errno == EINTR);
498  return (status < 0) ? 0 : status;
499 }
500 
501 
502 bool POSIXSocket::SetReuseAddress(bool reuse_address) {
503  int on = reuse_address ? 1 : 0;
504  int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
505  return status == 0;
506 }
507 
508 
510  // Nothing to do on POSIX.
511  return true;
512 }
513 
514 
516  return errno;
517 }
518 
519 
521  return htons(value);
522 }
523 
524 
526  return ntohs(value);
527 }
528 
529 
530 uint32_t Socket::HToN(uint32_t value) {
531  return htonl(value);
532 }
533 
534 
535 uint32_t Socket::NToH(uint32_t value) {
536  return ntohl(value);
537 }
538 
539 
541  return new POSIXSocket();
542 }
543 
544 
545 } } // 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:389
static void MemCopy(void *dest, const void *src, size_t size)
Definition: platform.h:314
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 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:178
static void PrintError(const char *format,...)
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 trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt 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 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
void USE(T)
Definition: globals.h:303
static void StrNCpy(Vector< char > dest, const char *src, size_t n)
bool SetReuseAddress(bool reuse_address)
static double DaylightSavingsOffset(double time)
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:164
UnaryMathFunction CreateTranscendentalFunction(TranscendentalCache::Type type)
static char * StrChr(char *str, int c)
static Socket * CreateSocket()
bool Connect(const char *host, const char *port)