33 #include <semaphore.h>
54 static const pthread_t kNoThread = (pthread_t) 0;
62 static Mutex* limit_mutex =
NULL;
82 __asm__ __volatile__(
"" : : :
"memory");
88 if (
isnan(time))
return "";
89 time_t tv =
static_cast<time_t
>(floor(time/msPerSecond));
90 struct tm* t = localtime(&tv);
91 if (
NULL == t)
return "";
98 time_t utc = time(
NULL);
100 struct tm* loc = localtime(&utc);
103 return static_cast<double>((mktime(loc) - utc) * msPerSecond -
104 (loc->tm_isdst > 0 ? 3600 * msPerSecond : 0));
113 static void* lowest_ever_allocated =
reinterpret_cast<void*
>(-1);
114 static void* highest_ever_allocated =
reinterpret_cast<void*
>(0);
117 static void UpdateAllocatedSpaceLimits(
void* address,
int size) {
121 lowest_ever_allocated =
Min(lowest_ever_allocated, address);
122 highest_ever_allocated =
123 Max(highest_ever_allocated,
124 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
129 return address < lowest_ever_allocated || address >= highest_ever_allocated;
134 return sysconf(_SC_PAGESIZE);
140 bool is_executable) {
141 const size_t msize =
RoundUp(requested, sysconf(_SC_PAGESIZE));
142 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
143 void* mbase = mmap(
NULL, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
144 if (mbase == MAP_FAILED) {
145 LOG(
ISOLATE, StringEvent(
"OS::Allocate",
"mmap failed"));
149 UpdateAllocatedSpaceLimits(mbase, msize);
156 int result = munmap(address, size);
164 VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect);
170 VirtualProtect(address, size, PAGE_READONLY | PAGE_GUARD, &oldprotect);
175 unsigned int ms =
static_cast<unsigned int>(milliseconds);
194 : file_(file), memory_(memory), size_(size) { }
196 virtual void*
memory() {
return memory_; }
197 virtual int size() {
return size_; }
206 FILE* file = fopen(name,
"r+");
209 fseek(file, 0, SEEK_END);
210 int size = ftell(file);
213 mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
220 FILE* file = fopen(name,
"w+");
222 int result = fwrite(initial, size, 1, file);
228 mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
234 if (memory_) munmap(memory_, size_);
243 FILE*
fp = fopen(
"/proc/self/maps",
"r");
244 if (fp ==
NULL)
return;
247 const int kLibNameLen = FILENAME_MAX + 1;
248 char* lib_name =
reinterpret_cast<char*
>(malloc(kLibNameLen));
253 uintptr_t start, end;
254 char attr_r, attr_w, attr_x, attr_p;
257 if (fscanf(fp,
" %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4)
break;
260 if (attr_r ==
'r' && attr_w !=
'w' && attr_x ==
'x') {
265 }
while ((c != EOF) && (c !=
'\n') && (c !=
'/'));
273 if (fgets(lib_name, kLibNameLen, fp) ==
NULL)
break;
278 lib_name[strlen(lib_name) - 1] =
'\0';
281 snprintf(lib_name, kLibNameLen,
282 "%08" V8PRIxPTR
"-%08" V8PRIxPTR, start, end);
284 LOG(isolate, SharedLibraryEvent(lib_name, start, end));
290 }
while ((c != EOF) && (c !=
'\n'));
317 return address_ !=
NULL;
322 address_ = VirtualAlloc(
NULL, size, MEM_RESERVE, PAGE_NOACCESS);
329 if (0 == VirtualFree(address(), 0, MEM_RELEASE)) address_ =
NULL;
335 int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
336 if (
NULL == VirtualAlloc(address, size, MEM_COMMIT, prot)) {
340 UpdateAllocatedSpaceLimits(address, static_cast<int>(size));
347 return VirtualFree(address, size, MEM_DECOMMIT) !=
false;
352 if (
NULL == VirtualAlloc(address,
355 PAGE_READONLY | PAGE_GUARD)) {
373 stack_size_(options.stack_size()) {
374 set_name(options.
name());
383 static void* ThreadEntry(
void* arg) {
395 void Thread::set_name(
const char* name) {
396 strncpy(name_, name,
sizeof(name_));
397 name_[
sizeof(name_) - 1] =
'\0';
402 pthread_attr_t* attr_ptr =
NULL;
404 if (stack_size_ > 0) {
405 pthread_attr_init(&attr);
406 pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
409 pthread_create(&data_->
thread_, attr_ptr, ThreadEntry,
this);
420 pthread_key_t pthread_key) {
425 intptr_t ptr_key =
reinterpret_cast<intptr_t
>(pthread_key);
430 static inline pthread_key_t LocalKeyToPthreadKey(
433 intptr_t ptr_key =
static_cast<intptr_t
>(local_key);
434 return reinterpret_cast<pthread_key_t
>(ptr_key);
440 int result = pthread_key_create(&key,
NULL);
443 return PthreadKeyToLocalKey(key);
448 pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
449 int result = pthread_key_delete(pthread_key);
456 pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
457 return pthread_getspecific(pthread_key);
462 pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
463 pthread_setspecific(pthread_key, value);
475 pthread_mutexattr_t attrs;
476 memset(&attrs, 0,
sizeof(attrs));
478 int result = pthread_mutexattr_init(&attrs);
480 result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE);
482 result = pthread_mutex_init(&mutex_, &attrs);
489 int result = pthread_mutex_lock(&mutex_);
494 int result = pthread_mutex_unlock(&mutex_);
499 int result = pthread_mutex_trylock(&mutex_);
501 if (result == EBUSY) {
509 pthread_mutex_t mutex_;
524 virtual bool Wait(
int timeout);
525 virtual void Signal() { sem_post(&sem_); }
533 int result = sem_wait(&sem_);
534 if (result == 0)
return;
535 CHECK(result == -1 && errno == EINTR);
540 #ifndef TIMEVAL_TO_TIMESPEC
541 #define TIMEVAL_TO_TIMESPEC(tv, ts) do { \
542 (ts)->tv_sec = (tv)->tv_sec; \
543 (ts)->tv_nsec = (tv)->tv_usec * 1000; \
549 const long kOneSecondMicros = 1000000;
552 struct timeval delta;
553 delta.tv_usec = timeout % kOneSecondMicros;
554 delta.tv_sec = timeout / kOneSecondMicros;
556 struct timeval current_time;
558 if (gettimeofday(¤t_time,
NULL) == -1) {
563 struct timeval end_time;
564 timeradd(¤t_time, &delta, &end_time);
570 int result = sem_timedwait(&sem_, &ts);
571 if (result == 0)
return true;
572 if (result == -1 && errno == ETIMEDOUT)
return false;
573 CHECK(result == -1 && errno == EINTR);
596 THREAD_SUSPEND_RESUME |
597 THREAD_QUERY_INFORMATION,
599 GetCurrentThreadId())) {}
602 if (profiled_thread_ !=
NULL) {
603 CloseHandle(profiled_thread_);
604 profiled_thread_ =
NULL;
652 bool cpu_profiling_enabled =
657 if (!cpu_profiling_enabled) {
660 if (cpu_profiling_enabled) {
665 if (runtime_profiler_enabled) {
689 if (profiled_thread ==
NULL)
return;
693 memset(&context, 0,
sizeof(context));
697 if (sample ==
NULL) sample = &sample_obj;
699 static const DWORD kSuspendFailed =
static_cast<DWORD>(-1);
700 if (SuspendThread(profiled_thread) == kSuspendFailed)
return;
703 context.ContextFlags = CONTEXT_FULL;
704 if (GetThreadContext(profiled_thread, &context) != 0) {
706 sample->
pc =
reinterpret_cast<Address>(context.Rip);
707 sample->
sp =
reinterpret_cast<Address>(context.Rsp);
708 sample->
fp =
reinterpret_cast<Address>(context.Rbp);
710 sample->
pc =
reinterpret_cast<Address>(context.Eip);
711 sample->
sp =
reinterpret_cast<Address>(context.Esp);
712 sample->
fp =
reinterpret_cast<Address>(context.Ebp);
715 sampler->
Tick(sample);
717 ResumeThread(profiled_thread);
743 srandom(static_cast<unsigned int>(seed));
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 expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable memory(in Mbytes)") DEFINE_bool(gc_global
static void * GetThreadLocal(LocalStorageKey key)
static void RemoveActiveSampler(Sampler *sampler)
static void Free(void *address, const size_t size)
Thread(const Options &options)
PlatformData * platform_data()
StateTag current_vm_state()
#define LOG(isolate, Call)
static void SignalCodeMovingGC()
SamplerThread(int interval)
static bool IsOutsideAllocatedSpace(void *pointer)
static const char * LocalTimezone(double time)
static SamplerThread * instance_
PosixMemoryMappedFile(FILE *file, void *memory, int size)
static void AddActiveSampler(Sampler *sampler)
static const int kSamplerThreadStackSize
#define ASSERT(condition)
typedef HANDLE(__stdcall *DLL_FUNC_TYPE(CreateToolhelp32Snapshot))(DWORD dwFlags
static MemoryMappedFile * open(const char *name)
static void RemoveActiveSampler(Sampler *sampler)
typedef DWORD(__stdcall *DLL_FUNC_TYPE(SymGetOptions))(VOID)
virtual void * memory()=0
bool Guard(void *address)
static void StopRuntimeProfilerThreadBeforeShutdown(Thread *thread)
STATIC_ASSERT((FixedDoubleArray::kHeaderSize &kDoubleAlignmentMask)==0)
static void ReleaseStore(volatile AtomicWord *ptr, AtomicWord value)
CygwinSemaphore(int count)
RuntimeProfiler * runtime_profiler()
static TickSample * TickSampleEvent(Isolate *isolate)
static void ProtectCode(void *address, const size_t size)
static LocalStorageKey CreateThreadLocalKey()
static MemoryMappedFile * create(const char *name, int size, void *initial)
bool Commit(void *address, size_t size, bool is_executable)
static void Guard(void *address, const size_t size)
virtual ~CygwinSemaphore()
T RoundUp(T x, intptr_t m)
static Mutex * CreateMutex()
static double TimeCurrentMillis()
static void DoCpuProfile(Sampler *sampler, void *raw_sampler_thread)
activate correct semantics for inheriting readonliness false
static void DeleteThreadLocalKey(LocalStorageKey key)
static void Sleep(const int milliseconds)
static Semaphore * CreateSemaphore(int count)
void SampleContext(Sampler *sampler)
RuntimeProfilerRateLimiter rate_limiter_
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)
void SampleStack(TickSample *sample)
static void LogSharedLibraryAddresses()
virtual ~PosixMemoryMappedFile()
static int ActivationFrameAlignment()
const char * name() const
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)
Sampler(Isolate *isolate, int interval)
static uint64_t CpuFeaturesImpliedByPlatform()
virtual void Tick(TickSample *sample)=0
static bool IterateActiveSamplers(VisitSampler func, void *param)
static double LocalTimeOffset()
static intptr_t CommitPageSize()
bool Uncommit(void *address, size_t size)
static void DoRuntimeProfile(Sampler *sampler, void *ignored)