blob: 6c724bd016a2a6841cfb8a8065c25c89688f311e [file] [log] [blame]
ulan@chromium.org2efb9002012-01-19 15:36:35 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000028// Platform specific code for Linux goes here. For the POSIX comaptible parts
29// the implementation is in platform-posix.cc.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000030
31#include <pthread.h>
32#include <semaphore.h>
33#include <signal.h>
lrn@chromium.org5d00b602011-01-05 09:51:43 +000034#include <sys/prctl.h>
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000035#include <sys/time.h>
36#include <sys/resource.h>
lrn@chromium.org303ada72010-10-27 09:33:13 +000037#include <sys/syscall.h>
ager@chromium.org381abbb2009-02-25 13:23:22 +000038#include <sys/types.h>
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039#include <stdlib.h>
40
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000041#if defined(__GLIBC__)
42#include <execinfo.h>
43#include <cxxabi.h>
44#endif
45
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046// Ubuntu Dapper requires memory pages to be marked as
47// executable. Otherwise, OS raises an exception when executing code
48// in that page.
49#include <sys/types.h> // mmap & munmap
ager@chromium.org236ad962008-09-25 09:45:57 +000050#include <sys/mman.h> // mmap & munmap
51#include <sys/stat.h> // open
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000052#include <fcntl.h> // open
53#include <unistd.h> // sysconf
fschneider@chromium.org7d10be52012-04-10 12:30:14 +000054#if defined(__GLIBC__) && !defined(__UCLIBC__)
ager@chromium.org236ad962008-09-25 09:45:57 +000055#include <execinfo.h> // backtrace, backtrace_symbols
fschneider@chromium.org7d10be52012-04-10 12:30:14 +000056#endif // defined(__GLIBC__) && !defined(__UCLIBC__)
ager@chromium.org236ad962008-09-25 09:45:57 +000057#include <strings.h> // index
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000058#include <errno.h>
59#include <stdarg.h>
60
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +000061// GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'.
62// Old versions of the C library <signal.h> didn't define the type.
63#if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) && \
64 defined(__arm__) && !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
65#include <asm/sigcontext.h>
66#endif
67
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000068#undef MAP_TYPE
69
70#include "v8.h"
71
danno@chromium.org8c0a43f2012-04-03 08:37:53 +000072#include "platform-posix.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000073#include "platform.h"
ager@chromium.orga1645e22009-09-09 19:27:10 +000074#include "v8threads.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000075#include "vm-state-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000076
77
kasperl@chromium.org71affb52009-05-26 05:44:31 +000078namespace v8 {
79namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000080
81// 0 is never a valid thread id on Linux since tids and pids share a
82// name space and pid 0 is reserved (see man 2 kill).
83static const pthread_t kNoThread = (pthread_t) 0;
84
85
86double ceiling(double x) {
87 return ceil(x);
88}
89
90
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000091static Mutex* limit_mutex = NULL;
92
93
danno@chromium.org8c0a43f2012-04-03 08:37:53 +000094void OS::PostSetUp() {
fschneider@chromium.org7d10be52012-04-10 12:30:14 +000095 POSIXPostSetUp();
danno@chromium.org8c0a43f2012-04-03 08:37:53 +000096}
97
98
ager@chromium.orgc4c92722009-11-18 14:12:51 +000099uint64_t OS::CpuFeaturesImpliedByPlatform() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000100 return 0; // Linux runs on anything.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000101}
102
103
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000104#ifdef __arm__
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000105static bool CPUInfoContainsString(const char * search_string) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000106 const char* file_name = "/proc/cpuinfo";
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000107 // This is written as a straight shot one pass parser
108 // and not using STL string and ifstream because,
109 // on Linux, it's reading from a (non-mmap-able)
110 // character special device.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000111 FILE* f = NULL;
112 const char* what = search_string;
113
114 if (NULL == (f = fopen(file_name, "r")))
115 return false;
116
117 int k;
118 while (EOF != (k = fgetc(f))) {
119 if (k == *what) {
120 ++what;
121 while ((*what != '\0') && (*what == fgetc(f))) {
122 ++what;
123 }
124 if (*what == '\0') {
125 fclose(f);
126 return true;
127 } else {
128 what = search_string;
129 }
130 }
131 }
132 fclose(f);
133
134 // Did not find string in the proc file.
135 return false;
136}
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000137
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000138
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000139bool OS::ArmCpuHasFeature(CpuFeature feature) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000140 const char* search_string = NULL;
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000141 // Simple detection of VFP at runtime for Linux.
142 // It is based on /proc/cpuinfo, which reveals hardware configuration
143 // to user-space applications. According to ARM (mid 2009), no similar
144 // facility is universally available on the ARM architectures,
145 // so it's up to individual OSes to provide such.
146 switch (feature) {
verwaest@chromium.orgb6d052d2012-07-27 08:03:27 +0000147 case VFP2:
148 search_string = "vfp";
149 break;
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000150 case VFP3:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000151 search_string = "vfpv3";
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000152 break;
153 case ARMv7:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000154 search_string = "ARMv7";
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000155 break;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000156 case SUDIV:
157 search_string = "idiva";
158 break;
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000159 case VFP32DREGS:
160 // This case is handled specially below.
161 break;
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000162 default:
163 UNREACHABLE();
164 }
165
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000166 if (feature == VFP32DREGS) {
167 return ArmCpuHasFeature(VFP3) && !CPUInfoContainsString("d16");
168 }
169
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000170 if (CPUInfoContainsString(search_string)) {
171 return true;
172 }
173
174 if (feature == VFP3) {
175 // Some old kernels will report vfp not vfpv3. Here we make a last attempt
176 // to detect vfpv3 by checking for vfp *and* neon, since neon is only
177 // available on architectures with vfpv3.
178 // Checking neon on its own is not enough as it is possible to have neon
179 // without vfp.
180 if (CPUInfoContainsString("vfp") && CPUInfoContainsString("neon")) {
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000181 return true;
182 }
183 }
184
185 return false;
186}
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000187
188
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000189CpuImplementer OS::GetCpuImplementer() {
190 static bool use_cached_value = false;
191 static CpuImplementer cached_value = UNKNOWN_IMPLEMENTER;
192 if (use_cached_value) {
193 return cached_value;
194 }
195 if (CPUInfoContainsString("CPU implementer\t: 0x41")) {
196 cached_value = ARM_IMPLEMENTER;
197 } else if (CPUInfoContainsString("CPU implementer\t: 0x51")) {
198 cached_value = QUALCOMM_IMPLEMENTER;
199 } else {
200 cached_value = UNKNOWN_IMPLEMENTER;
201 }
202 use_cached_value = true;
203 return cached_value;
204}
205
206
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000207bool OS::ArmUsingHardFloat() {
yangguo@chromium.orgc74d6742012-06-29 15:15:45 +0000208 // GCC versions 4.6 and above define __ARM_PCS or __ARM_PCS_VFP to specify
209 // the Floating Point ABI used (PCS stands for Procedure Call Standard).
210 // We use these as well as a couple of other defines to statically determine
211 // what FP ABI used.
212 // GCC versions 4.4 and below don't support hard-fp.
213 // GCC versions 4.5 may support hard-fp without defining __ARM_PCS or
214 // __ARM_PCS_VFP.
215
216#define GCC_VERSION (__GNUC__ * 10000 \
217 + __GNUC_MINOR__ * 100 \
218 + __GNUC_PATCHLEVEL__)
219#if GCC_VERSION >= 40600
220#if defined(__ARM_PCS_VFP)
221 return true;
222#else
223 return false;
224#endif
225
226#elif GCC_VERSION < 40500
227 return false;
228
229#else
230#if defined(__ARM_PCS_VFP)
231 return true;
232#elif defined(__ARM_PCS) || defined(__SOFTFP) || !defined(__VFP_FP__)
233 return false;
234#else
235#error "Your version of GCC does not report the FP ABI compiled for." \
236 "Please report it on this issue" \
237 "http://code.google.com/p/v8/issues/detail?id=2140"
238
239#endif
240#endif
241#undef GCC_VERSION
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000242}
yangguo@chromium.orgc74d6742012-06-29 15:15:45 +0000243
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000244#endif // def __arm__
245
246
lrn@chromium.org7516f052011-03-30 08:52:27 +0000247#ifdef __mips__
248bool OS::MipsCpuHasFeature(CpuFeature feature) {
249 const char* search_string = NULL;
250 const char* file_name = "/proc/cpuinfo";
251 // Simple detection of FPU at runtime for Linux.
252 // It is based on /proc/cpuinfo, which reveals hardware configuration
253 // to user-space applications. According to MIPS (early 2010), no similar
254 // facility is universally available on the MIPS architectures,
255 // so it's up to individual OSes to provide such.
256 //
257 // This is written as a straight shot one pass parser
258 // and not using STL string and ifstream because,
259 // on Linux, it's reading from a (non-mmap-able)
260 // character special device.
261
262 switch (feature) {
263 case FPU:
264 search_string = "FPU";
265 break;
266 default:
267 UNREACHABLE();
268 }
269
270 FILE* f = NULL;
271 const char* what = search_string;
272
273 if (NULL == (f = fopen(file_name, "r")))
274 return false;
275
276 int k;
277 while (EOF != (k = fgetc(f))) {
278 if (k == *what) {
279 ++what;
280 while ((*what != '\0') && (*what == fgetc(f))) {
281 ++what;
282 }
283 if (*what == '\0') {
284 fclose(f);
285 return true;
286 } else {
287 what = search_string;
288 }
289 }
290 }
291 fclose(f);
292
293 // Did not find string in the proc file.
294 return false;
295}
296#endif // def __mips__
297
298
ager@chromium.org236ad962008-09-25 09:45:57 +0000299int OS::ActivationFrameAlignment() {
ager@chromium.orge2902be2009-06-08 12:21:35 +0000300#ifdef V8_TARGET_ARCH_ARM
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +0000301 // On EABI ARM targets this is required for fp correctness in the
302 // runtime system.
ager@chromium.org3a6061e2009-03-12 14:24:36 +0000303 return 8;
ager@chromium.org5c838252010-02-19 08:53:10 +0000304#elif V8_TARGET_ARCH_MIPS
305 return 8;
306#endif
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000307 // With gcc 4.4 the tree vectorization optimizer can generate code
ager@chromium.orge2902be2009-06-08 12:21:35 +0000308 // that requires 16 byte alignment such as movdqa on x86.
309 return 16;
ager@chromium.org236ad962008-09-25 09:45:57 +0000310}
311
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000312
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000313void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000314#if (defined(V8_TARGET_ARCH_ARM) && defined(__arm__)) || \
315 (defined(V8_TARGET_ARCH_MIPS) && defined(__mips__))
316 // Only use on ARM or MIPS hardware.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000317 MemoryBarrier();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000318#else
319 __asm__ __volatile__("" : : : "memory");
320 // An x86 store acts as a release barrier.
321#endif
322 *ptr = value;
323}
324
325
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000326const char* OS::LocalTimezone(double time) {
327 if (isnan(time)) return "";
328 time_t tv = static_cast<time_t>(floor(time/msPerSecond));
329 struct tm* t = localtime(&tv);
330 if (NULL == t) return "";
331 return t->tm_zone;
332}
333
334
335double OS::LocalTimeOffset() {
336 time_t tv = time(NULL);
337 struct tm* t = localtime(&tv);
338 // tm_gmtoff includes any daylight savings offset, so subtract it.
339 return static_cast<double>(t->tm_gmtoff * msPerSecond -
340 (t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
341}
342
343
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000344// We keep the lowest and highest addresses mapped as a quick way of
345// determining that pointers are outside the heap (used mostly in assertions
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000346// and verification). The estimate is conservative, i.e., not all addresses in
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000347// 'allocated' space are actually allocated to our heap. The range is
348// [lowest, highest), inclusive on the low and and exclusive on the high end.
349static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
350static void* highest_ever_allocated = reinterpret_cast<void*>(0);
351
352
353static void UpdateAllocatedSpaceLimits(void* address, int size) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000354 ASSERT(limit_mutex != NULL);
355 ScopedLock lock(limit_mutex);
356
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000357 lowest_ever_allocated = Min(lowest_ever_allocated, address);
358 highest_ever_allocated =
359 Max(highest_ever_allocated,
360 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
361}
362
363
364bool OS::IsOutsideAllocatedSpace(void* address) {
365 return address < lowest_ever_allocated || address >= highest_ever_allocated;
366}
367
368
369size_t OS::AllocateAlignment() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000370 return sysconf(_SC_PAGESIZE);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000371}
372
373
kasper.lund7276f142008-07-30 08:49:36 +0000374void* OS::Allocate(const size_t requested,
375 size_t* allocated,
kasperl@chromium.orgf5aa8372009-03-24 14:47:14 +0000376 bool is_executable) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000377 const size_t msize = RoundUp(requested, AllocateAlignment());
kasperl@chromium.orgf5aa8372009-03-24 14:47:14 +0000378 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +0000379 void* addr = OS::GetRandomMmapAddr();
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000380 void* mbase = mmap(addr, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000381 if (mbase == MAP_FAILED) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000382 LOG(i::Isolate::Current(),
383 StringEvent("OS::Allocate", "mmap failed"));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000384 return NULL;
385 }
386 *allocated = msize;
387 UpdateAllocatedSpaceLimits(mbase, msize);
388 return mbase;
389}
390
391
kasperl@chromium.orgf5aa8372009-03-24 14:47:14 +0000392void OS::Free(void* address, const size_t size) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000393 // TODO(1240712): munmap has a return value which is ignored here.
ager@chromium.orga1645e22009-09-09 19:27:10 +0000394 int result = munmap(address, size);
395 USE(result);
396 ASSERT(result == 0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000397}
398
399
400void OS::Sleep(int milliseconds) {
401 unsigned int ms = static_cast<unsigned int>(milliseconds);
402 usleep(1000 * ms);
403}
404
405
406void OS::Abort() {
407 // Redirect to std abort to signal abnormal program termination.
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000408 if (FLAG_break_on_abort) {
409 DebugBreak();
410 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000411 abort();
412}
413
414
kasper.lund7276f142008-07-30 08:49:36 +0000415void OS::DebugBreak() {
ager@chromium.org5ec48922009-05-05 07:25:34 +0000416// TODO(lrn): Introduce processor define for runtime system (!= V8_ARCH_x,
417// which is the architecture of generated code).
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000418#if (defined(__arm__) || defined(__thumb__))
419# if defined(CAN_USE_ARMV5_INSTRUCTIONS)
kasper.lund7276f142008-07-30 08:49:36 +0000420 asm("bkpt 0");
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000421# endif
ager@chromium.org5c838252010-02-19 08:53:10 +0000422#elif defined(__mips__)
423 asm("break");
kasper.lund7276f142008-07-30 08:49:36 +0000424#else
425 asm("int $3");
426#endif
427}
428
429
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000430void OS::DumpBacktrace() {
431#if defined(__GLIBC__)
432 void* trace[100];
433 int size = backtrace(trace, ARRAY_SIZE(trace));
434 char** symbols = backtrace_symbols(trace, size);
435 fprintf(stderr, "\n==== C stack trace ===============================\n\n");
436 if (size == 0) {
437 fprintf(stderr, "(empty)\n");
438 } else if (symbols == NULL) {
439 fprintf(stderr, "(no symbols)\n");
440 } else {
441 for (int i = 1; i < size; ++i) {
442 fprintf(stderr, "%2d: ", i);
443 char mangled[201];
444 if (sscanf(symbols[i], "%*[^(]%*[(]%200[^)+]", mangled) == 1) { // NOLINT
445 int status;
446 size_t length;
447 char* demangled = abi::__cxa_demangle(mangled, NULL, &length, &status);
448 fprintf(stderr, "%s\n", demangled ? demangled : mangled);
449 free(demangled);
450 } else {
451 fprintf(stderr, "??\n");
452 }
453 }
454 }
455 fflush(stderr);
456 free(symbols);
457#endif
458}
459
460
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000461class PosixMemoryMappedFile : public OS::MemoryMappedFile {
462 public:
463 PosixMemoryMappedFile(FILE* file, void* memory, int size)
464 : file_(file), memory_(memory), size_(size) { }
465 virtual ~PosixMemoryMappedFile();
466 virtual void* memory() { return memory_; }
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000467 virtual int size() { return size_; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000468 private:
469 FILE* file_;
470 void* memory_;
471 int size_;
472};
473
474
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000475OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000476 FILE* file = fopen(name, "r+");
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000477 if (file == NULL) return NULL;
478
479 fseek(file, 0, SEEK_END);
480 int size = ftell(file);
481
482 void* memory =
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +0000483 mmap(OS::GetRandomMmapAddr(),
484 size,
485 PROT_READ | PROT_WRITE,
486 MAP_SHARED,
487 fileno(file),
488 0);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000489 return new PosixMemoryMappedFile(file, memory, size);
490}
491
492
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000493OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
494 void* initial) {
495 FILE* file = fopen(name, "w+");
496 if (file == NULL) return NULL;
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000497 int result = fwrite(initial, size, 1, file);
498 if (result < 1) {
499 fclose(file);
500 return NULL;
501 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000502 void* memory =
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +0000503 mmap(OS::GetRandomMmapAddr(),
504 size,
505 PROT_READ | PROT_WRITE,
506 MAP_SHARED,
507 fileno(file),
508 0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000509 return new PosixMemoryMappedFile(file, memory, size);
510}
511
512
513PosixMemoryMappedFile::~PosixMemoryMappedFile() {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000514 if (memory_) OS::Free(memory_, size_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000515 fclose(file_);
516}
517
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000518
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000519void OS::LogSharedLibraryAddresses() {
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000520 // This function assumes that the layout of the file is as follows:
521 // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
522 // If we encounter an unexpected situation we abort scanning further entries.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000523 FILE* fp = fopen("/proc/self/maps", "r");
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000524 if (fp == NULL) return;
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000525
526 // Allocate enough room to be able to store a full file name.
527 const int kLibNameLen = FILENAME_MAX + 1;
528 char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
529
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000530 i::Isolate* isolate = ISOLATE;
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000531 // This loop will terminate once the scanning hits an EOF.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000532 while (true) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000533 uintptr_t start, end;
534 char attr_r, attr_w, attr_x, attr_p;
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000535 // Parse the addresses and permission bits at the beginning of the line.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000536 if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break;
537 if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break;
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000538
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000539 int c;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000540 if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') {
541 // Found a read-only executable entry. Skip characters until we reach
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000542 // the beginning of the filename or the end of the line.
543 do {
544 c = getc(fp);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000545 } while ((c != EOF) && (c != '\n') && (c != '/') && (c != '['));
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000546 if (c == EOF) break; // EOF: Was unexpected, just exit.
547
548 // Process the filename if found.
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000549 if ((c == '/') || (c == '[')) {
550 // Push the '/' or '[' back into the stream to be read below.
551 ungetc(c, fp);
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000552
553 // Read to the end of the line. Exit if the read fails.
554 if (fgets(lib_name, kLibNameLen, fp) == NULL) break;
555
556 // Drop the newline character read by fgets. We do not need to check
557 // for a zero-length string because we know that we at least read the
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000558 // '/' or '[' character.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000559 lib_name[strlen(lib_name) - 1] = '\0';
560 } else {
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000561 // No library name found, just record the raw address range.
562 snprintf(lib_name, kLibNameLen,
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000563 "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end);
564 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000565 LOG(isolate, SharedLibraryEvent(lib_name, start, end));
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000566 } else {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000567 // Entry not describing executable data. Skip to end of line to set up
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000568 // reading the next entry.
569 do {
570 c = getc(fp);
571 } while ((c != EOF) && (c != '\n'));
572 if (c == EOF) break;
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000573 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000574 }
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000575 free(lib_name);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000576 fclose(fp);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000577}
578
579
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000580void OS::SignalCodeMovingGC() {
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000581 // Support for ll_prof.py.
582 //
583 // The Linux profiler built into the kernel logs all mmap's with
584 // PROT_EXEC so that analysis tools can properly attribute ticks. We
585 // do a mmap with a name known by ll_prof.py and immediately munmap
586 // it. This injects a GC marker into the stream of events generated
587 // by the kernel and allows us to synchronize V8 code log and the
588 // kernel log.
589 int size = sysconf(_SC_PAGESIZE);
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +0000590 FILE* f = fopen(FLAG_gc_fake_mmap, "w+");
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +0000591 void* addr = mmap(OS::GetRandomMmapAddr(),
592 size,
593 PROT_READ | PROT_EXEC,
594 MAP_PRIVATE,
595 fileno(f),
596 0);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000597 ASSERT(addr != MAP_FAILED);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000598 OS::Free(addr, size);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000599 fclose(f);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000600}
601
602
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000603int OS::StackWalk(Vector<OS::StackFrame> frames) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000604 // backtrace is a glibc extension.
fschneider@chromium.org7d10be52012-04-10 12:30:14 +0000605#if defined(__GLIBC__) && !defined(__UCLIBC__)
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000606 int frames_size = frames.length();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000607 ScopedVector<void*> addresses(frames_size);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000608
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000609 int frames_count = backtrace(addresses.start(), frames_size);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000610
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000611 char** symbols = backtrace_symbols(addresses.start(), frames_count);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000612 if (symbols == NULL) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000613 return kStackWalkError;
614 }
615
616 for (int i = 0; i < frames_count; i++) {
617 frames[i].address = addresses[i];
618 // Format a text representation of the frame based on the information
619 // available.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000620 SNPrintF(MutableCStrVector(frames[i].text, kStackWalkMaxTextLen),
621 "%s",
622 symbols[i]);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000623 // Make sure line termination is in place.
624 frames[i].text[kStackWalkMaxTextLen - 1] = '\0';
625 }
626
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000627 free(symbols);
628
629 return frames_count;
fschneider@chromium.org7d10be52012-04-10 12:30:14 +0000630#else // defined(__GLIBC__) && !defined(__UCLIBC__)
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000631 return 0;
fschneider@chromium.org7d10be52012-04-10 12:30:14 +0000632#endif // defined(__GLIBC__) && !defined(__UCLIBC__)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000633}
634
635
636// Constants used for mmap.
637static const int kMmapFd = -1;
638static const int kMmapFdOffset = 0;
639
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000640VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000641
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000642VirtualMemory::VirtualMemory(size_t size) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000643 address_ = ReserveRegion(size);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000644 size_ = size;
645}
646
647
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000648VirtualMemory::VirtualMemory(size_t size, size_t alignment)
649 : address_(NULL), size_(0) {
650 ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment())));
651 size_t request_size = RoundUp(size + alignment,
652 static_cast<intptr_t>(OS::AllocateAlignment()));
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +0000653 void* reservation = mmap(OS::GetRandomMmapAddr(),
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000654 request_size,
655 PROT_NONE,
656 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
657 kMmapFd,
658 kMmapFdOffset);
659 if (reservation == MAP_FAILED) return;
660
661 Address base = static_cast<Address>(reservation);
662 Address aligned_base = RoundUp(base, alignment);
663 ASSERT_LE(base, aligned_base);
664
665 // Unmap extra memory reserved before and after the desired block.
666 if (aligned_base != base) {
667 size_t prefix_size = static_cast<size_t>(aligned_base - base);
668 OS::Free(base, prefix_size);
669 request_size -= prefix_size;
670 }
671
672 size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
673 ASSERT_LE(aligned_size, request_size);
674
675 if (aligned_size != request_size) {
676 size_t suffix_size = request_size - aligned_size;
677 OS::Free(aligned_base + aligned_size, suffix_size);
678 request_size -= suffix_size;
679 }
680
681 ASSERT(aligned_size == request_size);
682
683 address_ = static_cast<void*>(aligned_base);
684 size_ = aligned_size;
685}
686
687
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000688VirtualMemory::~VirtualMemory() {
689 if (IsReserved()) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000690 bool result = ReleaseRegion(address(), size());
691 ASSERT(result);
692 USE(result);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000693 }
694}
695
696
697bool VirtualMemory::IsReserved() {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000698 return address_ != NULL;
699}
700
701
702void VirtualMemory::Reset() {
703 address_ = NULL;
704 size_ = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000705}
706
707
kasperl@chromium.orgf5aa8372009-03-24 14:47:14 +0000708bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000709 return CommitRegion(address, size, is_executable);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000710}
711
712
713bool VirtualMemory::Uncommit(void* address, size_t size) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000714 return UncommitRegion(address, size);
715}
716
717
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000718bool VirtualMemory::Guard(void* address) {
719 OS::Guard(address, OS::CommitPageSize());
720 return true;
721}
722
723
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000724void* VirtualMemory::ReserveRegion(size_t size) {
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +0000725 void* result = mmap(OS::GetRandomMmapAddr(),
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000726 size,
727 PROT_NONE,
728 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
729 kMmapFd,
730 kMmapFdOffset);
731
732 if (result == MAP_FAILED) return NULL;
733
734 return result;
735}
736
737
738bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
739 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
740 if (MAP_FAILED == mmap(base,
741 size,
742 prot,
743 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
744 kMmapFd,
745 kMmapFdOffset)) {
746 return false;
747 }
748
749 UpdateAllocatedSpaceLimits(base, size);
750 return true;
751}
752
753
754bool VirtualMemory::UncommitRegion(void* base, size_t size) {
755 return mmap(base,
756 size,
757 PROT_NONE,
ager@chromium.orga1645e22009-09-09 19:27:10 +0000758 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000759 kMmapFd,
760 kMmapFdOffset) != MAP_FAILED;
761}
762
763
764bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
765 return munmap(base, size) == 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000766}
767
768
danno@chromium.org72204d52012-10-31 10:02:10 +0000769bool VirtualMemory::HasLazyCommits() {
770 return true;
771}
772
773
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000774class Thread::PlatformData : public Malloced {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000775 public:
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000776 PlatformData() : thread_(kNoThread) {}
ager@chromium.org41826e72009-03-30 13:30:57 +0000777
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000778 pthread_t thread_; // Thread handle for pthread.
779};
780
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000781Thread::Thread(const Options& options)
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000782 : data_(new PlatformData()),
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000783 stack_size_(options.stack_size()) {
784 set_name(options.name());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000785}
786
787
788Thread::~Thread() {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000789 delete data_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000790}
791
792
793static void* ThreadEntry(void* arg) {
794 Thread* thread = reinterpret_cast<Thread*>(arg);
795 // This is also initialized by the first argument to pthread_create() but we
796 // don't know which thread will run first (the original thread or the new
797 // one) so we initialize it here too.
danno@chromium.orgb6451162011-08-17 14:33:23 +0000798#ifdef PR_SET_NAME
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000799 prctl(PR_SET_NAME,
800 reinterpret_cast<unsigned long>(thread->name()), // NOLINT
801 0, 0, 0);
danno@chromium.orgb6451162011-08-17 14:33:23 +0000802#endif
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000803 thread->data()->thread_ = pthread_self();
804 ASSERT(thread->data()->thread_ != kNoThread);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000805 thread->Run();
806 return NULL;
807}
808
809
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000810void Thread::set_name(const char* name) {
811 strncpy(name_, name, sizeof(name_));
812 name_[sizeof(name_) - 1] = '\0';
813}
814
815
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000816void Thread::Start() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000817 pthread_attr_t* attr_ptr = NULL;
818 pthread_attr_t attr;
819 if (stack_size_ > 0) {
820 pthread_attr_init(&attr);
821 pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
822 attr_ptr = &attr;
823 }
danno@chromium.orgc612e022011-11-10 11:38:15 +0000824 int result = pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this);
825 CHECK_EQ(0, result);
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000826 ASSERT(data_->thread_ != kNoThread);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000827}
828
829
830void Thread::Join() {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000831 pthread_join(data_->thread_, NULL);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000832}
833
834
835Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
836 pthread_key_t key;
837 int result = pthread_key_create(&key, NULL);
838 USE(result);
839 ASSERT(result == 0);
840 return static_cast<LocalStorageKey>(key);
841}
842
843
844void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
845 pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
846 int result = pthread_key_delete(pthread_key);
847 USE(result);
848 ASSERT(result == 0);
849}
850
851
852void* Thread::GetThreadLocal(LocalStorageKey key) {
853 pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
854 return pthread_getspecific(pthread_key);
855}
856
857
858void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
859 pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
860 pthread_setspecific(pthread_key, value);
861}
862
863
864void Thread::YieldCPU() {
865 sched_yield();
866}
867
868
869class LinuxMutex : public Mutex {
870 public:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000871 LinuxMutex() {
872 pthread_mutexattr_t attrs;
873 int result = pthread_mutexattr_init(&attrs);
874 ASSERT(result == 0);
875 result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE);
876 ASSERT(result == 0);
877 result = pthread_mutex_init(&mutex_, &attrs);
878 ASSERT(result == 0);
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000879 USE(result);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000880 }
881
882 virtual ~LinuxMutex() { pthread_mutex_destroy(&mutex_); }
883
884 virtual int Lock() {
885 int result = pthread_mutex_lock(&mutex_);
886 return result;
887 }
888
889 virtual int Unlock() {
890 int result = pthread_mutex_unlock(&mutex_);
891 return result;
892 }
893
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000894 virtual bool TryLock() {
895 int result = pthread_mutex_trylock(&mutex_);
896 // Return false if the lock is busy and locking failed.
897 if (result == EBUSY) {
898 return false;
899 }
900 ASSERT(result == 0); // Verify no other errors.
901 return true;
902 }
903
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000904 private:
905 pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms.
906};
907
908
909Mutex* OS::CreateMutex() {
910 return new LinuxMutex();
911}
912
913
914class LinuxSemaphore : public Semaphore {
915 public:
916 explicit LinuxSemaphore(int count) { sem_init(&sem_, 0, count); }
917 virtual ~LinuxSemaphore() { sem_destroy(&sem_); }
918
kasper.lund7276f142008-07-30 08:49:36 +0000919 virtual void Wait();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000920 virtual bool Wait(int timeout);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000921 virtual void Signal() { sem_post(&sem_); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000922 private:
923 sem_t sem_;
924};
925
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000926
kasper.lund7276f142008-07-30 08:49:36 +0000927void LinuxSemaphore::Wait() {
928 while (true) {
929 int result = sem_wait(&sem_);
930 if (result == 0) return; // Successfully got semaphore.
931 CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup.
932 }
933}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000934
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000935
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000936#ifndef TIMEVAL_TO_TIMESPEC
937#define TIMEVAL_TO_TIMESPEC(tv, ts) do { \
938 (ts)->tv_sec = (tv)->tv_sec; \
939 (ts)->tv_nsec = (tv)->tv_usec * 1000; \
940} while (false)
941#endif
942
943
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000944bool LinuxSemaphore::Wait(int timeout) {
945 const long kOneSecondMicros = 1000000; // NOLINT
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000946
947 // Split timeout into second and nanosecond parts.
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000948 struct timeval delta;
949 delta.tv_usec = timeout % kOneSecondMicros;
950 delta.tv_sec = timeout / kOneSecondMicros;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000951
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000952 struct timeval current_time;
953 // Get the current time.
954 if (gettimeofday(&current_time, NULL) == -1) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000955 return false;
956 }
957
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000958 // Calculate time for end of timeout.
959 struct timeval end_time;
960 timeradd(&current_time, &delta, &end_time);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000961
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000962 struct timespec ts;
963 TIMEVAL_TO_TIMESPEC(&end_time, &ts);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000964 // Wait for semaphore signalled or timeout.
965 while (true) {
966 int result = sem_timedwait(&sem_, &ts);
967 if (result == 0) return true; // Successfully got semaphore.
968 if (result > 0) {
969 // For glibc prior to 2.3.4 sem_timedwait returns the error instead of -1.
970 errno = result;
971 result = -1;
972 }
973 if (result == -1 && errno == ETIMEDOUT) return false; // Timeout.
974 CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup.
975 }
976}
977
978
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000979Semaphore* OS::CreateSemaphore(int count) {
980 return new LinuxSemaphore(count);
981}
982
ager@chromium.org381abbb2009-02-25 13:23:22 +0000983
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000984#if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T)
kasperl@chromium.orgacae3782009-04-11 09:17:08 +0000985
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000986// Not all versions of Android's C library provide ucontext_t.
987// Detect this and provide custom but compatible definitions. Note that these
988// follow the GLibc naming convention to access register values from
989// mcontext_t.
990//
991// See http://code.google.com/p/android/issues/detail?id=34784
992
993#if defined(__arm__)
994
kasperl@chromium.orgacae3782009-04-11 09:17:08 +0000995typedef struct sigcontext mcontext_t;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000996
kasperl@chromium.orgacae3782009-04-11 09:17:08 +0000997typedef struct ucontext {
998 uint32_t uc_flags;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000999 struct ucontext* uc_link;
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00001000 stack_t uc_stack;
1001 mcontext_t uc_mcontext;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001002 // Other fields are not used by V8, don't define them here.
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00001003} ucontext_t;
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00001004
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001005#elif defined(__mips__)
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001006// MIPS version of sigcontext, for Android bionic.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001007typedef struct {
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001008 uint32_t regmask;
1009 uint32_t status;
1010 uint64_t pc;
1011 uint64_t gregs[32];
1012 uint64_t fpregs[32];
1013 uint32_t acx;
1014 uint32_t fpc_csr;
1015 uint32_t fpc_eir;
1016 uint32_t used_math;
1017 uint32_t dsp;
1018 uint64_t mdhi;
1019 uint64_t mdlo;
1020 uint32_t hi1;
1021 uint32_t lo1;
1022 uint32_t hi2;
1023 uint32_t lo2;
1024 uint32_t hi3;
1025 uint32_t lo3;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001026} mcontext_t;
1027
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001028typedef struct ucontext {
1029 uint32_t uc_flags;
1030 struct ucontext* uc_link;
1031 stack_t uc_stack;
1032 mcontext_t uc_mcontext;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001033 // Other fields are not used by V8, don't define them here.
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001034} ucontext_t;
1035
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001036#elif defined(__i386__)
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001037// x86 version for Android.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001038typedef struct {
yangguo@chromium.orgcb9affa2012-05-15 12:16:38 +00001039 uint32_t gregs[19];
1040 void* fpregs;
1041 uint32_t oldmask;
1042 uint32_t cr2;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001043} mcontext_t;
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001044
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001045typedef uint32_t kernel_sigset_t[2]; // x86 kernel uses 64-bit signal masks
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001046typedef struct ucontext {
yangguo@chromium.orgcb9affa2012-05-15 12:16:38 +00001047 uint32_t uc_flags;
1048 struct ucontext* uc_link;
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001049 stack_t uc_stack;
1050 mcontext_t uc_mcontext;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001051 // Other fields are not used by V8, don't define them here.
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001052} ucontext_t;
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001053enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00001054#endif
1055
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001056#endif // __ANDROID__ && !defined(__BIONIC_HAVE_UCONTEXT_T)
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00001057
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001058static int GetThreadID() {
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001059#if defined(__ANDROID__)
1060 // Android's C library provides gettid(2).
1061 return gettid();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001062#else
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001063 // Glibc doesn't provide a wrapper for gettid(2).
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001064 return syscall(SYS_gettid);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001065#endif
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001066}
1067
1068
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001069static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
1070 USE(info);
1071 if (signal != SIGPROF) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001072 Isolate* isolate = Isolate::UncheckedCurrent();
1073 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
1074 // We require a fully initialized and entered isolate.
1075 return;
1076 }
vitalyr@chromium.org0ec56d62011-04-15 22:22:08 +00001077 if (v8::Locker::IsActive() &&
1078 !isolate->thread_manager()->IsLockedByCurrentThread()) {
1079 return;
1080 }
1081
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001082 Sampler* sampler = isolate->logger()->sampler();
1083 if (sampler == NULL || !sampler->IsActive()) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001084
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001085 TickSample sample_obj;
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001086 TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001087 if (sample == NULL) sample = &sample_obj;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001088
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001089 // Extracting the sample from the context is extremely machine dependent.
1090 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
1091 mcontext_t& mcontext = ucontext->uc_mcontext;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001092 sample->state = isolate->current_vm_state();
ager@chromium.org9085a012009-05-11 19:22:57 +00001093#if V8_HOST_ARCH_IA32
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001094 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
1095 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
1096 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
ager@chromium.org9085a012009-05-11 19:22:57 +00001097#elif V8_HOST_ARCH_X64
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001098 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
1099 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
1100 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
ager@chromium.org9085a012009-05-11 19:22:57 +00001101#elif V8_HOST_ARCH_ARM
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001102#if defined(__GLIBC__) && !defined(__UCLIBC__) && \
1103 (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1104 // Old GLibc ARM versions used a gregs[] array to access the register
1105 // values from mcontext_t.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001106 sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
1107 sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
1108 sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001109#else
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001110 sample->pc = reinterpret_cast<Address>(mcontext.arm_pc);
1111 sample->sp = reinterpret_cast<Address>(mcontext.arm_sp);
1112 sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001113#endif // defined(__GLIBC__) && !defined(__UCLIBC__) &&
1114 // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
ager@chromium.org5c838252010-02-19 08:53:10 +00001115#elif V8_HOST_ARCH_MIPS
danno@chromium.orgc612e022011-11-10 11:38:15 +00001116 sample->pc = reinterpret_cast<Address>(mcontext.pc);
1117 sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]);
1118 sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]);
1119#endif // V8_HOST_ARCH_*
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001120 sampler->SampleStack(sample);
1121 sampler->Tick(sample);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001122}
1123
1124
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001125class Sampler::PlatformData : public Malloced {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001126 public:
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001127 PlatformData() : vm_tid_(GetThreadID()) {}
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001128
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001129 int vm_tid() const { return vm_tid_; }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001130
1131 private:
1132 const int vm_tid_;
1133};
1134
1135
1136class SignalSender : public Thread {
1137 public:
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +00001138 static const int kSignalSenderStackSize = 64 * KB;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001139
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001140 explicit SignalSender(int interval)
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001141 : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001142 vm_tgid_(getpid()),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001143 interval_(interval) {}
1144
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001145 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
1146 static void TearDown() { delete mutex_; }
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001147
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001148 static void InstallSignalHandler() {
1149 struct sigaction sa;
1150 sa.sa_sigaction = ProfilerSignalHandler;
1151 sigemptyset(&sa.sa_mask);
1152 sa.sa_flags = SA_RESTART | SA_SIGINFO;
1153 signal_handler_installed_ =
1154 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
1155 }
1156
1157 static void RestoreSignalHandler() {
1158 if (signal_handler_installed_) {
1159 sigaction(SIGPROF, &old_signal_handler_, 0);
1160 signal_handler_installed_ = false;
1161 }
1162 }
1163
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001164 static void AddActiveSampler(Sampler* sampler) {
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001165 ScopedLock lock(mutex_);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001166 SamplerRegistry::AddActiveSampler(sampler);
1167 if (instance_ == NULL) {
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00001168 // Start a thread that will send SIGPROF signal to VM threads,
1169 // when CPU profiling will be enabled.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001170 instance_ = new SignalSender(sampler->interval());
1171 instance_->Start();
1172 } else {
1173 ASSERT(instance_->interval_ == sampler->interval());
1174 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001175 }
1176
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001177 static void RemoveActiveSampler(Sampler* sampler) {
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001178 ScopedLock lock(mutex_);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001179 SamplerRegistry::RemoveActiveSampler(sampler);
1180 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001181 RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001182 delete instance_;
1183 instance_ = NULL;
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001184 RestoreSignalHandler();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001185 }
1186 }
1187
1188 // Implement Thread::Run().
1189 virtual void Run() {
1190 SamplerRegistry::State state;
1191 while ((state = SamplerRegistry::GetState()) !=
1192 SamplerRegistry::HAS_NO_SAMPLERS) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001193 // When CPU profiling is enabled both JavaScript and C++ code is
1194 // profiled. We must not suspend.
rossberg@chromium.orgcddc71f2012-12-07 12:40:13 +00001195 if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) {
1196 if (!signal_handler_installed_) InstallSignalHandler();
1197 SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
1198 } else {
1199 if (signal_handler_installed_) RestoreSignalHandler();
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001200 if (RuntimeProfiler::WaitForSomeIsolateToEnterJS()) continue;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001201 }
rossberg@chromium.orgcddc71f2012-12-07 12:40:13 +00001202 Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001203 }
1204 }
1205
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001206 static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001207 if (!sampler->IsProfiling()) return;
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001208 SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
1209 sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001210 }
1211
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001212 void SendProfilingSignal(int tid) {
1213 if (!signal_handler_installed_) return;
1214 // Glibc doesn't provide a wrapper for tgkill(2).
1215#if defined(ANDROID)
1216 syscall(__NR_tgkill, vm_tgid_, tid, SIGPROF);
1217#else
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00001218 int result = syscall(SYS_tgkill, vm_tgid_, tid, SIGPROF);
1219 USE(result);
1220 ASSERT(result == 0);
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001221#endif
1222 }
1223
rossberg@chromium.orgcddc71f2012-12-07 12:40:13 +00001224 void Sleep() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001225 // Convert ms to us and subtract 100 us to compensate delays
1226 // occuring during signal delivery.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001227 useconds_t interval = interval_ * 1000 - 100;
ulan@chromium.org2efb9002012-01-19 15:36:35 +00001228#if defined(ANDROID)
1229 usleep(interval);
1230#else
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001231 int result = usleep(interval);
1232#ifdef DEBUG
1233 if (result != 0 && errno != EINTR) {
1234 fprintf(stderr,
1235 "SignalSender usleep error; interval = %u, errno = %d\n",
1236 interval,
1237 errno);
1238 ASSERT(result == 0 || errno == EINTR);
1239 }
ulan@chromium.org2efb9002012-01-19 15:36:35 +00001240#endif // DEBUG
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001241 USE(result);
ulan@chromium.org2efb9002012-01-19 15:36:35 +00001242#endif // ANDROID
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001243 }
1244
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001245 const int vm_tgid_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001246 const int interval_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001247
1248 // Protects the process wide state below.
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001249 static Mutex* mutex_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001250 static SignalSender* instance_;
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001251 static bool signal_handler_installed_;
1252 static struct sigaction old_signal_handler_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001253
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001254 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001255 DISALLOW_COPY_AND_ASSIGN(SignalSender);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001256};
1257
1258
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001259Mutex* SignalSender::mutex_ = NULL;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001260SignalSender* SignalSender::instance_ = NULL;
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001261struct sigaction SignalSender::old_signal_handler_;
1262bool SignalSender::signal_handler_installed_ = false;
lrn@chromium.org303ada72010-10-27 09:33:13 +00001263
1264
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001265void OS::SetUp() {
1266 // Seed the random number generator. We preserve microsecond resolution.
1267 uint64_t seed = Ticks() ^ (getpid() << 16);
1268 srandom(static_cast<unsigned int>(seed));
1269 limit_mutex = CreateMutex();
1270
1271#ifdef __arm__
1272 // When running on ARM hardware check that the EABI used by V8 and
1273 // by the C code is the same.
1274 bool hard_float = OS::ArmUsingHardFloat();
1275 if (hard_float) {
1276#if !USE_EABI_HARDFLOAT
1277 PrintF("ERROR: Binary compiled with -mfloat-abi=hard but without "
1278 "-DUSE_EABI_HARDFLOAT\n");
1279 exit(1);
1280#endif
1281 } else {
1282#if USE_EABI_HARDFLOAT
1283 PrintF("ERROR: Binary not compiled with -mfloat-abi=hard but with "
1284 "-DUSE_EABI_HARDFLOAT\n");
1285 exit(1);
1286#endif
1287 }
1288#endif
1289 SignalSender::SetUp();
1290}
1291
1292
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001293void OS::TearDown() {
1294 SignalSender::TearDown();
1295 delete limit_mutex;
1296}
1297
1298
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001299Sampler::Sampler(Isolate* isolate, int interval)
1300 : isolate_(isolate),
1301 interval_(interval),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001302 profiling_(false),
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001303 active_(false),
1304 samples_taken_(0) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001305 data_ = new PlatformData;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001306}
1307
1308
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001309Sampler::~Sampler() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001310 ASSERT(!IsActive());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001311 delete data_;
1312}
1313
1314
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001315void Sampler::Start() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001316 ASSERT(!IsActive());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001317 SetActive(true);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001318 SignalSender::AddActiveSampler(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001319}
1320
1321
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001322void Sampler::Stop() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001323 ASSERT(IsActive());
1324 SignalSender::RemoveActiveSampler(this);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001325 SetActive(false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001326}
1327
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001328
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001329} } // namespace v8::internal