32 # error "V8 does not support the SPARC CPU architecture."
35 #include <sys/stack.h>
42 #include <semaphore.h>
48 #include <sys/regset.h>
70 return fpclass(x) & FP_NZERO;
85 static const pthread_t kNoThread = (pthread_t) 0;
93 static Mutex* limit_mutex =
NULL;
108 return Max(STACK_ALIGN, 16);
113 __asm__ __volatile__(
"" : : :
"memory");
119 if (
isnan(time))
return "";
120 time_t tv =
static_cast<time_t
>(floor(time/msPerSecond));
121 struct tm* t = localtime(&tv);
122 if (
NULL == t)
return "";
129 time_t utc = time(
NULL);
131 struct tm* loc = localtime(&utc);
133 return static_cast<double>((mktime(loc) - utc) * msPerSecond);
142 static void* lowest_ever_allocated =
reinterpret_cast<void*
>(-1);
143 static void* highest_ever_allocated =
reinterpret_cast<void*
>(0);
146 static void UpdateAllocatedSpaceLimits(
void* address,
int size) {
148 ScopedLock lock(limit_mutex);
150 lowest_ever_allocated =
Min(lowest_ever_allocated, address);
151 highest_ever_allocated =
152 Max(highest_ever_allocated,
153 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
158 return address < lowest_ever_allocated || address >= highest_ever_allocated;
163 return static_cast<size_t>(getpagesize());
169 bool is_executable) {
170 const size_t msize =
RoundUp(requested, getpagesize());
171 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
172 void* mbase = mmap(
NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
174 if (mbase == MAP_FAILED) {
175 LOG(
ISOLATE, StringEvent(
"OS::Allocate",
"mmap failed"));
179 UpdateAllocatedSpaceLimits(mbase, msize);
184 void OS::Free(
void* address,
const size_t size) {
186 int result = munmap(address, size);
193 useconds_t ms =
static_cast<useconds_t
>(milliseconds);
209 class PosixMemoryMappedFile :
public OS::MemoryMappedFile {
212 : file_(file), memory_(memory), size_(size) { }
214 virtual void*
memory() {
return memory_; }
215 virtual int size() {
return size_; }
224 FILE* file = fopen(name,
"r+");
227 fseek(file, 0, SEEK_END);
228 int size = ftell(file);
231 mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
232 return new PosixMemoryMappedFile(file, memory, size);
238 FILE* file = fopen(name,
"w+");
240 int result = fwrite(initial, size, 1, file);
246 mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
247 return new PosixMemoryMappedFile(file, memory, size);
252 if (memory_) munmap(memory_, size_);
271 static int StackWalkCallback(uintptr_t
pc,
int signo,
void* data) {
275 int i = walker->
index;
277 walker->
frames[i].address =
reinterpret_cast<void*
>(
pc);
285 if (dladdr(reinterpret_cast<void*>(pc), &info) == 0) {
287 }
else if ((info.dli_fname !=
NULL && info.dli_sname !=
NULL)) {
289 OS::SNPrintF(text,
"%s'%s+0x%x", info.dli_fname, info.dli_sname, pc);
295 pc - reinterpret_cast<uintptr_t>(info.dli_fbase),
305 struct StackWalker walker = { frames, 0 };
309 if (!walkcontext(&ctx, StackWalkCallback, &walker)) {
318 static const int kMmapFd = -1;
319 static const int kMmapFdOffset = 0;
331 : address_(
NULL), size_(0) {
333 size_t request_size =
RoundUp(size + alignment,
338 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
341 if (reservation == MAP_FAILED)
return;
348 if (aligned_base != base) {
349 size_t prefix_size =
static_cast<size_t>(aligned_base - base);
351 request_size -= prefix_size;
357 if (aligned_size != request_size) {
358 size_t suffix_size = request_size - aligned_size;
359 OS::Free(aligned_base + aligned_size, suffix_size);
360 request_size -= suffix_size;
363 ASSERT(aligned_size == request_size);
365 address_ =
static_cast<void*
>(aligned_base);
366 size_ = aligned_size;
380 return address_ !=
NULL;
410 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
414 if (result == MAP_FAILED)
return NULL;
421 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
422 if (MAP_FAILED == mmap(base,
425 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
431 UpdateAllocatedSpaceLimits(base, size);
440 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED,
442 kMmapFdOffset) != MAP_FAILED;
447 return munmap(base, size) == 0;
451 class Thread::PlatformData :
public Malloced {
460 : data_(new PlatformData()),
461 stack_size_(options.stack_size()) {
462 set_name(options.name());
471 static void* ThreadEntry(
void* arg) {
476 thread->data()->thread_ = pthread_self();
477 ASSERT(thread->data()->thread_ != kNoThread);
483 void Thread::set_name(
const char* name) {
484 strncpy(name_, name,
sizeof(name_));
485 name_[
sizeof(name_) - 1] =
'\0';
491 if (stack_size_ > 0) {
492 pthread_attr_init(&attr);
493 pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
495 pthread_create(&data_->
thread_,
NULL, ThreadEntry,
this);
507 int result = pthread_key_create(&key,
NULL);
515 pthread_key_t pthread_key =
static_cast<pthread_key_t
>(key);
516 int result = pthread_key_delete(pthread_key);
523 pthread_key_t pthread_key =
static_cast<pthread_key_t
>(key);
524 return pthread_getspecific(pthread_key);
529 pthread_key_t pthread_key =
static_cast<pthread_key_t
>(key);
530 pthread_setspecific(pthread_key, value);
542 pthread_mutexattr_t attr;
543 pthread_mutexattr_init(&attr);
544 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
545 pthread_mutex_init(&mutex_, &attr);
550 int Lock() {
return pthread_mutex_lock(&mutex_); }
552 int Unlock() {
return pthread_mutex_unlock(&mutex_); }
555 int result = pthread_mutex_trylock(&mutex_);
557 if (result == EBUSY) {
565 pthread_mutex_t mutex_;
570 return new SolarisMutex();
580 virtual bool Wait(
int timeout);
581 virtual void Signal() { sem_post(&sem_); }
589 int result = sem_wait(&sem_);
590 if (result == 0)
return;
591 CHECK(result == -1 && errno == EINTR);
596 #ifndef TIMEVAL_TO_TIMESPEC
597 #define TIMEVAL_TO_TIMESPEC(tv, ts) do { \
598 (ts)->tv_sec = (tv)->tv_sec; \
599 (ts)->tv_nsec = (tv)->tv_usec * 1000; \
605 #define timeradd(a, b, result) \
607 (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
608 (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
609 if ((result)->tv_usec >= 1000000) { \
610 ++(result)->tv_sec; \
611 (result)->tv_usec -= 1000000; \
618 const long kOneSecondMicros = 1000000;
621 struct timeval delta;
622 delta.tv_usec = timeout % kOneSecondMicros;
623 delta.tv_sec = timeout / kOneSecondMicros;
625 struct timeval current_time;
627 if (gettimeofday(¤t_time,
NULL) == -1) {
632 struct timeval end_time;
633 timeradd(¤t_time, &delta, &end_time);
639 int result = sem_timedwait(&sem_, &ts);
640 if (result == 0)
return true;
641 if (result == -1 && errno == ETIMEDOUT)
return false;
642 CHECK(result == -1 && errno == EINTR);
652 static pthread_t GetThreadID() {
653 return pthread_self();
656 static void ProfilerSignalHandler(
int signal, siginfo_t* info,
void* context) {
658 if (signal != SIGPROF)
return;
659 Isolate* isolate = Isolate::UncheckedCurrent();
660 if (isolate ==
NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
665 !isolate->thread_manager()->IsLockedByCurrentThread()) {
669 Sampler* sampler = isolate->logger()->sampler();
670 if (sampler ==
NULL || !sampler->IsActive())
return;
672 TickSample sample_obj;
674 if (sample ==
NULL) sample = &sample_obj;
677 ucontext_t* ucontext =
reinterpret_cast<ucontext_t*
>(context);
678 mcontext_t& mcontext = ucontext->uc_mcontext;
679 sample->state = isolate->current_vm_state();
681 sample->pc =
reinterpret_cast<Address>(mcontext.gregs[REG_PC]);
682 sample->sp =
reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
683 sample->fp =
reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
685 sampler->SampleStack(sample);
686 sampler->Tick(sample);
689 class Sampler::PlatformData :
public Malloced {
693 pthread_t
vm_tid()
const {
return vm_tid_; }
707 static const int kSignalSenderStackSize = 64 *
KB;
711 interval_(interval) {}
718 sa.sa_sigaction = ProfilerSignalHandler;
719 sigemptyset(&sa.sa_mask);
720 sa.sa_flags = SA_RESTART | SA_SIGINFO;
721 signal_handler_installed_ =
722 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
726 if (signal_handler_installed_) {
727 sigaction(SIGPROF, &old_signal_handler_, 0);
728 signal_handler_installed_ =
false;
735 if (instance_ ==
NULL) {
752 RestoreSignalHandler();
761 bool cpu_profiling_enabled =
764 if (cpu_profiling_enabled && !signal_handler_installed_) {
765 InstallSignalHandler();
766 }
else if (!cpu_profiling_enabled && signal_handler_installed_) {
767 RestoreSignalHandler();
772 if (!cpu_profiling_enabled) {
773 if (rate_limiter_.SuspendIfNecessary())
continue;
775 if (cpu_profiling_enabled && runtime_profiler_enabled) {
779 Sleep(HALF_INTERVAL);
783 Sleep(HALF_INTERVAL);
785 if (cpu_profiling_enabled) {
791 if (runtime_profiler_enabled) {
797 Sleep(FULL_INTERVAL);
814 if (!signal_handler_installed_)
return;
815 pthread_kill(tid, SIGPROF);
821 useconds_t interval = interval_ * 1000 - 100;
822 if (full_or_half == HALF_INTERVAL) interval /= 2;
823 int result = usleep(interval);
825 if (result != 0 && errno != EINTR) {
827 "SignalSender usleep error; interval = %u, errno = %d\n",
830 ASSERT(result == 0 || errno == EINTR);
837 RuntimeProfilerRateLimiter rate_limiter_;
840 static Mutex* mutex_;
842 static bool signal_handler_installed_;
843 static struct sigaction old_signal_handler_;
851 struct sigaction SignalSender::old_signal_handler_;
861 uint64_t
seed =
static_cast<uint64_t
>(TimeCurrentMillis());
862 srandom(static_cast<unsigned int>(
seed));
863 limit_mutex = CreateMutex();
880 data_ =
new PlatformData;
static void * GetThreadLocal(LocalStorageKey key)
static void Free(void *address, const size_t size)
Thread(const Options &options)
PlatformData * platform_data()
#define LOG(isolate, Call)
static void InstallSignalHandler()
void SendProfilingSignal(pthread_t tid)
static void SignalCodeMovingGC()
static void * GetRandomMmapAddr()
static void * ReserveRegion(size_t size)
static bool IsOutsideAllocatedSpace(void *pointer)
static const char * LocalTimezone(double time)
Vector< char > MutableCStrVector(char *data)
static const int kStackWalkError
void Sleep(SleepInterval full_or_half)
static const int kStackWalkMaxTextLen
static void DoRuntimeProfile(Sampler *sampler, void *ignored)
PosixMemoryMappedFile(FILE *file, void *memory, int size)
#define ASSERT(condition)
static void RestoreSignalHandler()
static MemoryMappedFile * open(const char *name)
static void RemoveActiveSampler(Sampler *sampler)
virtual void * memory()=0
bool Guard(void *address)
static void StopRuntimeProfilerThreadBeforeShutdown(Thread *thread)
static SignalSender * instance_
static void ReleaseStore(volatile AtomicWord *ptr, AtomicWord value)
RuntimeProfiler * runtime_profiler()
static TickSample * TickSampleEvent(Isolate *isolate)
static LocalStorageKey CreateThreadLocalKey()
SignalSender(int interval)
bool IsAligned(T value, U alignment)
static MemoryMappedFile * create(const char *name, int size, void *initial)
bool Commit(void *address, size_t size, bool is_executable)
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
static void Guard(void *address, const size_t size)
SolarisSemaphore(int count)
T RoundUp(T x, intptr_t m)
#define ASSERT_LE(v1, v2)
static Mutex * CreateMutex()
activate correct semantics for inheriting readonliness false
static void DeleteThreadLocalKey(LocalStorageKey key)
static void Sleep(const int milliseconds)
Vector< OS::StackFrame > & frames
static int SNPrintF(Vector< char > str, const char *format,...)
static Semaphore * CreateSemaphore(int count)
static bool ReleaseRegion(void *base, size_t size)
static bool CommitRegion(void *base, size_t size, bool is_executable)
static void SetThreadLocal(LocalStorageKey key, void *value)
static void * Allocate(const size_t requested, size_t *allocated, bool is_executable)
static int StackWalk(Vector< StackFrame > frames)
static bool UncommitRegion(void *base, size_t size)
static void LogSharedLibraryAddresses()
virtual ~PosixMemoryMappedFile()
static int ActivationFrameAlignment()
static size_t AllocateAlignment()
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
static void AddActiveSampler(Sampler *sampler)
static void AddActiveSampler(Sampler *sampler)
Sampler(Isolate *isolate, int interval)
static uint64_t CpuFeaturesImpliedByPlatform()
static bool IterateActiveSamplers(VisitSampler func, void *param)
static void RemoveActiveSampler(Sampler *sampler)
static double LocalTimeOffset()
static bool signal_handler_installed_
virtual ~SolarisSemaphore()
static intptr_t CommitPageSize()
bool Uncommit(void *address, size_t size)
static void DoCpuProfile(Sampler *sampler, void *raw_sender)