Commit 5378d727 authored by vegorov@chromium.org's avatar vegorov@chromium.org

Fix the Cygwin build after isolates merge.

Patch by Bert Belder.

Review URL: http://codereview.chromium.org/6776011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7447 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1358772e
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
#include "v8.h" #include "v8.h"
#include "platform.h" #include "platform.h"
#include "top.h"
#include "v8threads.h" #include "v8threads.h"
#include "vm-state-inl.h" #include "vm-state-inl.h"
#include "win32-headers.h" #include "win32-headers.h"
...@@ -59,6 +58,9 @@ double ceiling(double x) { ...@@ -59,6 +58,9 @@ double ceiling(double x) {
} }
static Mutex* limit_mutex = NULL;
void OS::Setup() { void OS::Setup() {
// Seed the random number generator. // Seed the random number generator.
// Convert the current time to a 64-bit integer first, before converting it // Convert the current time to a 64-bit integer first, before converting it
...@@ -67,6 +69,7 @@ void OS::Setup() { ...@@ -67,6 +69,7 @@ void OS::Setup() {
// call this setup code within the same millisecond. // call this setup code within the same millisecond.
uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
srandom(static_cast<unsigned int>(seed)); srandom(static_cast<unsigned int>(seed));
limit_mutex = CreateMutex();
} }
...@@ -119,6 +122,9 @@ static void* highest_ever_allocated = reinterpret_cast<void*>(0); ...@@ -119,6 +122,9 @@ static void* highest_ever_allocated = reinterpret_cast<void*>(0);
static void UpdateAllocatedSpaceLimits(void* address, int size) { static void UpdateAllocatedSpaceLimits(void* address, int size) {
ASSERT(limit_mutex != NULL);
ScopedLock lock(limit_mutex);
lowest_ever_allocated = Min(lowest_ever_allocated, address); lowest_ever_allocated = Min(lowest_ever_allocated, address);
highest_ever_allocated = highest_ever_allocated =
Max(highest_ever_allocated, Max(highest_ever_allocated,
...@@ -254,6 +260,7 @@ void OS::LogSharedLibraryAddresses() { ...@@ -254,6 +260,7 @@ void OS::LogSharedLibraryAddresses() {
const int kLibNameLen = FILENAME_MAX + 1; const int kLibNameLen = FILENAME_MAX + 1;
char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen)); char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
i::Isolate* isolate = ISOLATE;
// This loop will terminate once the scanning hits an EOF. // This loop will terminate once the scanning hits an EOF.
while (true) { while (true) {
uintptr_t start, end; uintptr_t start, end;
...@@ -287,7 +294,7 @@ void OS::LogSharedLibraryAddresses() { ...@@ -287,7 +294,7 @@ void OS::LogSharedLibraryAddresses() {
snprintf(lib_name, kLibNameLen, snprintf(lib_name, kLibNameLen,
"%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end); "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end);
} }
LOG(SharedLibraryEvent(lib_name, start, end)); LOG(isolate, SharedLibraryEvent(lib_name, start, end));
} else { } else {
// Entry not describing executable data. Skip to end of line to setup // Entry not describing executable data. Skip to end of line to setup
// reading the next entry. // reading the next entry.
...@@ -314,47 +321,44 @@ int OS::StackWalk(Vector<OS::StackFrame> frames) { ...@@ -314,47 +321,44 @@ int OS::StackWalk(Vector<OS::StackFrame> frames) {
} }
// Constants used for mmap. // The VirtualMemory implementation is taken from platform-win32.cc.
static const int kMmapFd = -1; // The mmap-based virtual memory implementation as it is used on most posix
static const int kMmapFdOffset = 0; // platforms does not work well because Cygwin does not support MAP_FIXED.
// This causes VirtualMemory::Commit to not always commit the memory region
// specified.
bool VirtualMemory::IsReserved() {
return address_ != NULL;
}
VirtualMemory::VirtualMemory(size_t size) { VirtualMemory::VirtualMemory(size_t size) {
address_ = mmap(NULL, size, PROT_NONE, address_ = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS);
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
kMmapFd, kMmapFdOffset);
size_ = size; size_ = size;
} }
VirtualMemory::~VirtualMemory() { VirtualMemory::~VirtualMemory() {
if (IsReserved()) { if (IsReserved()) {
if (0 == munmap(address(), size())) address_ = MAP_FAILED; if (0 == VirtualFree(address(), 0, MEM_RELEASE)) address_ = NULL;
} }
} }
bool VirtualMemory::IsReserved() {
return address_ != MAP_FAILED;
}
bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
if (NULL == VirtualAlloc(address, size, MEM_COMMIT, prot)) {
if (mprotect(address, size, prot) != 0) {
return false; return false;
} }
UpdateAllocatedSpaceLimits(address, size); UpdateAllocatedSpaceLimits(address, static_cast<int>(size));
return true; return true;
} }
bool VirtualMemory::Uncommit(void* address, size_t size) { bool VirtualMemory::Uncommit(void* address, size_t size) {
return mmap(address, size, PROT_NONE, ASSERT(IsReserved());
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, return VirtualFree(address, size, MEM_DECOMMIT) != false;
kMmapFd, kMmapFdOffset) != MAP_FAILED;
} }
...@@ -427,6 +431,7 @@ static void* ThreadEntry(void* arg) { ...@@ -427,6 +431,7 @@ static void* ThreadEntry(void* arg) {
// one) so we initialize it here too. // one) so we initialize it here too.
thread->thread_handle_data()->thread_ = pthread_self(); thread->thread_handle_data()->thread_ = pthread_self();
ASSERT(thread->IsValid()); ASSERT(thread->IsValid());
Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
thread->Run(); thread->Run();
return NULL; return NULL;
} }
...@@ -439,7 +444,14 @@ void Thread::set_name(const char* name) { ...@@ -439,7 +444,14 @@ void Thread::set_name(const char* name) {
void Thread::Start() { void Thread::Start() {
pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this); pthread_attr_t* attr_ptr = NULL;
pthread_attr_t attr;
if (stack_size_ > 0) {
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
attr_ptr = &attr;
}
pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry, this);
ASSERT(IsValid()); ASSERT(IsValid());
} }
...@@ -623,128 +635,176 @@ Semaphore* OS::CreateSemaphore(int count) { ...@@ -623,128 +635,176 @@ Semaphore* OS::CreateSemaphore(int count) {
class Sampler::PlatformData : public Malloced { class Sampler::PlatformData : public Malloced {
public: public:
explicit PlatformData(Sampler* sampler) { // Get a handle to the calling thread. This is the thread that we are
sampler_ = sampler; // going to profile. We need to make a copy of the handle because we are
sampler_thread_ = INVALID_HANDLE_VALUE; // going to use it in the sampler thread. Using GetThreadHandle() will
profiled_thread_ = INVALID_HANDLE_VALUE; // not work in this case. We're using OpenThread because DuplicateHandle
// for some reason doesn't work in Chrome's sandbox.
PlatformData() : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
THREAD_SUSPEND_RESUME |
THREAD_QUERY_INFORMATION,
false,
GetCurrentThreadId())) {}
~PlatformData() {
if (profiled_thread_ != NULL) {
CloseHandle(profiled_thread_);
profiled_thread_ = NULL;
}
} }
Sampler* sampler_; HANDLE profiled_thread() { return profiled_thread_; }
HANDLE sampler_thread_;
private:
HANDLE profiled_thread_; HANDLE profiled_thread_;
RuntimeProfilerRateLimiter rate_limiter_; };
// Sampler thread handler. class SamplerThread : public Thread {
void Runner() { public:
while (sampler_->IsActive()) { explicit SamplerThread(int interval)
if (rate_limiter_.SuspendIfNecessary()) continue; : Thread(NULL, "SamplerThread"),
Sample(); interval_(interval) {}
Sleep(sampler_->interval_);
static void AddActiveSampler(Sampler* sampler) {
ScopedLock lock(mutex_);
SamplerRegistry::AddActiveSampler(sampler);
if (instance_ == NULL) {
instance_ = new SamplerThread(sampler->interval());
instance_->Start();
} else {
ASSERT(instance_->interval_ == sampler->interval());
} }
} }
void Sample() { static void RemoveActiveSampler(Sampler* sampler) {
if (sampler_->IsProfiling()) { ScopedLock lock(mutex_);
// Context used for sampling the register state of the profiled thread. SamplerRegistry::RemoveActiveSampler(sampler);
CONTEXT context; if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
memset(&context, 0, sizeof(context)); RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
instance_->Join();
delete instance_;
instance_ = NULL;
}
}
TickSample sample_obj; // Implement Thread::Run().
TickSample* sample = CpuProfiler::TickSampleEvent(); virtual void Run() {
if (sample == NULL) sample = &sample_obj; SamplerRegistry::State state;
while ((state = SamplerRegistry::GetState()) !=
SamplerRegistry::HAS_NO_SAMPLERS) {
bool cpu_profiling_enabled =
(state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
// When CPU profiling is enabled both JavaScript and C++ code is
// profiled. We must not suspend.
if (!cpu_profiling_enabled) {
if (rate_limiter_.SuspendIfNecessary()) continue;
}
if (cpu_profiling_enabled) {
if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
return;
}
}
if (runtime_profiler_enabled) {
if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
return;
}
}
OS::Sleep(interval_);
}
}
static void DoCpuProfile(Sampler* sampler, void* raw_sampler_thread) {
if (!sampler->isolate()->IsInitialized()) return;
if (!sampler->IsProfiling()) return;
SamplerThread* sampler_thread =
reinterpret_cast<SamplerThread*>(raw_sampler_thread);
sampler_thread->SampleContext(sampler);
}
static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
if (!sampler->isolate()->IsInitialized()) return;
sampler->isolate()->runtime_profiler()->NotifyTick();
}
void SampleContext(Sampler* sampler) {
HANDLE profiled_thread = sampler->platform_data()->profiled_thread();
if (profiled_thread == NULL) return;
// Context used for sampling the register state of the profiled thread.
CONTEXT context;
memset(&context, 0, sizeof(context));
TickSample sample_obj;
TickSample* sample = CpuProfiler::TickSampleEvent(sampler->isolate());
if (sample == NULL) sample = &sample_obj;
static const DWORD kSuspendFailed = static_cast<DWORD>(-1); static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
if (SuspendThread(profiled_thread_) == kSuspendFailed) return; if (SuspendThread(profiled_thread) == kSuspendFailed) return;
sample->state = Top::current_vm_state(); sample->state = sampler->isolate()->current_vm_state();
context.ContextFlags = CONTEXT_FULL; context.ContextFlags = CONTEXT_FULL;
if (GetThreadContext(profiled_thread_, &context) != 0) { if (GetThreadContext(profiled_thread, &context) != 0) {
#if V8_HOST_ARCH_X64 #if V8_HOST_ARCH_X64
sample->pc = reinterpret_cast<Address>(context.Rip); sample->pc = reinterpret_cast<Address>(context.Rip);
sample->sp = reinterpret_cast<Address>(context.Rsp); sample->sp = reinterpret_cast<Address>(context.Rsp);
sample->fp = reinterpret_cast<Address>(context.Rbp); sample->fp = reinterpret_cast<Address>(context.Rbp);
#else #else
sample->pc = reinterpret_cast<Address>(context.Eip); sample->pc = reinterpret_cast<Address>(context.Eip);
sample->sp = reinterpret_cast<Address>(context.Esp); sample->sp = reinterpret_cast<Address>(context.Esp);
sample->fp = reinterpret_cast<Address>(context.Ebp); sample->fp = reinterpret_cast<Address>(context.Ebp);
#endif #endif
sampler_->SampleStack(sample); sampler->SampleStack(sample);
sampler_->Tick(sample); sampler->Tick(sample);
}
ResumeThread(profiled_thread_);
} }
if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick(); ResumeThread(profiled_thread);
} }
const int interval_;
RuntimeProfilerRateLimiter rate_limiter_;
// Protects the process wide state below.
static Mutex* mutex_;
static SamplerThread* instance_;
DISALLOW_COPY_AND_ASSIGN(SamplerThread);
}; };
// Entry point for sampler thread. Mutex* SamplerThread::mutex_ = OS::CreateMutex();
static DWORD __stdcall SamplerEntry(void* arg) { SamplerThread* SamplerThread::instance_ = NULL;
Sampler::PlatformData* data =
reinterpret_cast<Sampler::PlatformData*>(arg);
data->Runner();
return 0;
}
// Initialize a profile sampler. Sampler::Sampler(Isolate* isolate, int interval)
Sampler::Sampler(int interval) : isolate_(isolate),
: interval_(interval), interval_(interval),
profiling_(false), profiling_(false),
active_(false), active_(false),
samples_taken_(0) { samples_taken_(0) {
data_ = new PlatformData(this); data_ = new PlatformData;
} }
Sampler::~Sampler() { Sampler::~Sampler() {
ASSERT(!IsActive());
delete data_; delete data_;
} }
// Start profiling.
void Sampler::Start() { void Sampler::Start() {
// Do not start multiple threads for the same sampler.
ASSERT(!IsActive()); ASSERT(!IsActive());
// Get a handle to the calling thread. This is the thread that we are
// going to profile. We need to make a copy of the handle because we are
// going to use it in the sampler thread. Using GetThreadHandle() will
// not work in this case. We're using OpenThread because DuplicateHandle
// for some reason doesn't work in Chrome's sandbox.
data_->profiled_thread_ = OpenThread(THREAD_GET_CONTEXT |
THREAD_SUSPEND_RESUME |
THREAD_QUERY_INFORMATION,
false,
GetCurrentThreadId());
BOOL ok = data_->profiled_thread_ != NULL;
if (!ok) return;
// Start sampler thread.
DWORD tid;
SetActive(true); SetActive(true);
data_->sampler_thread_ = CreateThread(NULL, 0, SamplerEntry, data_, 0, &tid); SamplerThread::AddActiveSampler(this);
// Set thread to high priority to increase sampling accuracy.
SetThreadPriority(data_->sampler_thread_, THREAD_PRIORITY_TIME_CRITICAL);
} }
// Stop profiling.
void Sampler::Stop() { void Sampler::Stop() {
// Seting active to false triggers termination of the sampler ASSERT(IsActive());
// thread. SamplerThread::RemoveActiveSampler(this);
SetActive(false); SetActive(false);
// Wait for sampler thread to terminate.
Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
WaitForSingleObject(data_->sampler_thread_, INFINITE);
// Release the thread handles
CloseHandle(data_->sampler_thread_);
CloseHandle(data_->profiled_thread_);
} }
#endif // ENABLE_LOGGING_AND_PROFILING #endif // ENABLE_LOGGING_AND_PROFILING
} } // namespace v8::internal } } // namespace v8::internal
......
...@@ -200,6 +200,7 @@ TEST(CodeRange) { ...@@ -200,6 +200,7 @@ TEST(CodeRange) {
size_t allocated = 0; size_t allocated = 0;
void* base = Isolate::Current()->code_range()-> void* base = Isolate::Current()->code_range()->
AllocateRawMemory(requested, &allocated); AllocateRawMemory(requested, &allocated);
CHECK(base != NULL);
blocks.Add(Block(base, static_cast<int>(allocated))); blocks.Add(Block(base, static_cast<int>(allocated)));
current_allocated += static_cast<int>(allocated); current_allocated += static_cast<int>(allocated);
total_allocated += static_cast<int>(allocated); total_allocated += static_cast<int>(allocated);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment