Improve V8 support for Cygwin
Should re-enable crankshaft; can build w/ snapshot again.
This commit is contained in:
parent
77ae87d367
commit
a293f90db4
7
deps/v8/SConstruct
vendored
7
deps/v8/SConstruct
vendored
@ -188,9 +188,6 @@ LIBRARY_FLAGS = {
|
||||
'LIBPATH' : ['/usr/local/lib'],
|
||||
'CCFLAGS': ['-ansi'],
|
||||
},
|
||||
'os:cygwin': {
|
||||
'WARNINGFLAGS': ['-Werror'],
|
||||
},
|
||||
'os:win32': {
|
||||
'CCFLAGS': ['-DWIN32'],
|
||||
'CXXFLAGS': ['-DWIN32'],
|
||||
@ -672,8 +669,8 @@ def GuessToolchain(os):
|
||||
|
||||
|
||||
def GuessVisibility(os, toolchain):
|
||||
if os == 'win32' and toolchain == 'gcc':
|
||||
# MinGW can't do it.
|
||||
if (os == 'win32' or os == 'cygwin') and toolchain == 'gcc':
|
||||
# MinGW / Cygwin can't do it.
|
||||
return 'default'
|
||||
elif os == 'solaris':
|
||||
return 'default'
|
||||
|
3
deps/v8/src/SConscript
vendored
3
deps/v8/src/SConscript
vendored
@ -266,6 +266,9 @@ D8_FILES = {
|
||||
'os:solaris': [
|
||||
'd8-posix.cc'
|
||||
],
|
||||
'os:cygwin': [
|
||||
'd8-posix.cc'
|
||||
],
|
||||
'os:win32': [
|
||||
'd8-windows.cc'
|
||||
],
|
||||
|
287
deps/v8/src/platform-cygwin.cc
vendored
287
deps/v8/src/platform-cygwin.cc
vendored
@ -31,22 +31,17 @@
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <signal.h>
|
||||
#include <cygwin/signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Ubuntu Dapper requires memory pages to be marked as
|
||||
// executable. Otherwise, OS raises an exception when executing code
|
||||
// in that page.
|
||||
#include <sys/types.h> // mmap & munmap
|
||||
#include <sys/mman.h> // mmap & munmap
|
||||
#include <sys/stat.h> // open
|
||||
#include <fcntl.h> // open
|
||||
#include <unistd.h> // sysconf
|
||||
#ifdef __GLIBC__
|
||||
#include <execinfo.h> // backtrace, backtrace_symbols
|
||||
#endif // def __GLIBC__
|
||||
#include <strings.h> // index
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
@ -60,12 +55,10 @@
|
||||
#include "v8threads.h"
|
||||
#include "vm-state-inl.h"
|
||||
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// 0 is never a valid thread id on Linux since tids and pids share a
|
||||
// name space and pid 0 is reserved (see man 2 kill).
|
||||
// 0 is never a valid thread id
|
||||
static const pthread_t kNoThread = (pthread_t) 0;
|
||||
|
||||
|
||||
@ -86,98 +79,11 @@ void OS::Setup() {
|
||||
|
||||
|
||||
uint64_t OS::CpuFeaturesImpliedByPlatform() {
|
||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
||||
// Here gcc is telling us that we are on an ARM and gcc is assuming that we
|
||||
// have VFP3 instructions. If gcc can assume it then so can we.
|
||||
return 1u << VFP3;
|
||||
#elif CAN_USE_ARMV7_INSTRUCTIONS
|
||||
return 1u << ARMv7;
|
||||
#else
|
||||
return 0; // Linux runs on anything.
|
||||
#endif
|
||||
return 0; // Nothing special about cygwin
|
||||
}
|
||||
|
||||
|
||||
#ifdef __arm__
|
||||
static bool CPUInfoContainsString(const char * search_string) {
|
||||
const char* file_name = "/proc/cpuinfo";
|
||||
// This is written as a straight shot one pass parser
|
||||
// and not using STL string and ifstream because,
|
||||
// on Linux, it's reading from a (non-mmap-able)
|
||||
// character special device.
|
||||
FILE* f = NULL;
|
||||
const char* what = search_string;
|
||||
|
||||
if (NULL == (f = fopen(file_name, "r")))
|
||||
return false;
|
||||
|
||||
int k;
|
||||
while (EOF != (k = fgetc(f))) {
|
||||
if (k == *what) {
|
||||
++what;
|
||||
while ((*what != '\0') && (*what == fgetc(f))) {
|
||||
++what;
|
||||
}
|
||||
if (*what == '\0') {
|
||||
fclose(f);
|
||||
return true;
|
||||
} else {
|
||||
what = search_string;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
// Did not find string in the proc file.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OS::ArmCpuHasFeature(CpuFeature feature) {
|
||||
const char* search_string = NULL;
|
||||
// Simple detection of VFP at runtime for Linux.
|
||||
// It is based on /proc/cpuinfo, which reveals hardware configuration
|
||||
// to user-space applications. According to ARM (mid 2009), no similar
|
||||
// facility is universally available on the ARM architectures,
|
||||
// so it's up to individual OSes to provide such.
|
||||
switch (feature) {
|
||||
case VFP3:
|
||||
search_string = "vfpv3";
|
||||
break;
|
||||
case ARMv7:
|
||||
search_string = "ARMv7";
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
if (CPUInfoContainsString(search_string)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (feature == VFP3) {
|
||||
// Some old kernels will report vfp not vfpv3. Here we make a last attempt
|
||||
// to detect vfpv3 by checking for vfp *and* neon, since neon is only
|
||||
// available on architectures with vfpv3.
|
||||
// Checking neon on its own is not enough as it is possible to have neon
|
||||
// without vfp.
|
||||
if (CPUInfoContainsString("vfp") && CPUInfoContainsString("neon")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif // def __arm__
|
||||
|
||||
|
||||
int OS::ActivationFrameAlignment() {
|
||||
#ifdef V8_TARGET_ARCH_ARM
|
||||
// On EABI ARM targets this is required for fp correctness in the
|
||||
// runtime system.
|
||||
return 8;
|
||||
#elif V8_TARGET_ARCH_MIPS
|
||||
return 8;
|
||||
#endif
|
||||
// With gcc 4.4 the tree vectorization optimizer can generate code
|
||||
// that requires 16 byte alignment such as movdqa on x86.
|
||||
return 16;
|
||||
@ -195,7 +101,7 @@ const char* OS::LocalTimezone(double time) {
|
||||
time_t tv = static_cast<time_t>(floor(time/msPerSecond));
|
||||
struct tm* t = localtime(&tv);
|
||||
if (NULL == t) return "";
|
||||
return tzname[0]; // The location of the timezone string on Cywin.
|
||||
return tzname[0]; // The location of the timezone string on Cygwin.
|
||||
}
|
||||
|
||||
|
||||
@ -205,7 +111,9 @@ double OS::LocalTimeOffset() {
|
||||
ASSERT(utc != -1);
|
||||
struct tm* loc = localtime(&utc);
|
||||
ASSERT(loc != NULL);
|
||||
return static_cast<double>((mktime(loc) - utc) * msPerSecond);
|
||||
// time - localtime includes any daylight savings offset, so subtract it.
|
||||
return static_cast<double>((mktime(loc) - utc) * msPerSecond -
|
||||
(loc->tm_isdst > 0 ? 3600 * msPerSecond : 0));
|
||||
}
|
||||
|
||||
|
||||
@ -290,16 +198,7 @@ void OS::Abort() {
|
||||
|
||||
|
||||
void OS::DebugBreak() {
|
||||
// TODO(lrn): Introduce processor define for runtime system (!= V8_ARCH_x,
|
||||
// which is the architecture of generated code).
|
||||
#if (defined(__arm__) || defined(__thumb__)) && \
|
||||
defined(CAN_USE_ARMV5_INSTRUCTIONS)
|
||||
asm("bkpt 0");
|
||||
#elif defined(__mips__)
|
||||
asm("break");
|
||||
#else
|
||||
asm("int $3");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -413,39 +312,13 @@ void OS::LogSharedLibraryAddresses() {
|
||||
|
||||
|
||||
void OS::SignalCodeMovingGC() {
|
||||
// Nothing to do on Cygwin
|
||||
}
|
||||
|
||||
|
||||
int OS::StackWalk(Vector<OS::StackFrame> frames) {
|
||||
// backtrace is a glibc extension.
|
||||
#ifdef __GLIBC__
|
||||
int frames_size = frames.length();
|
||||
ScopedVector<void*> addresses(frames_size);
|
||||
|
||||
int frames_count = backtrace(addresses.start(), frames_size);
|
||||
|
||||
char** symbols = backtrace_symbols(addresses.start(), frames_count);
|
||||
if (symbols == NULL) {
|
||||
return kStackWalkError;
|
||||
}
|
||||
|
||||
for (int i = 0; i < frames_count; i++) {
|
||||
frames[i].address = addresses[i];
|
||||
// Format a text representation of the frame based on the information
|
||||
// available.
|
||||
SNPrintF(MutableCStrVector(frames[i].text, kStackWalkMaxTextLen),
|
||||
"%s",
|
||||
symbols[i]);
|
||||
// Make sure line termination is in place.
|
||||
frames[i].text[kStackWalkMaxTextLen - 1] = '\0';
|
||||
}
|
||||
|
||||
free(symbols);
|
||||
|
||||
return frames_count;
|
||||
#else // ndef __GLIBC__
|
||||
// Not supported on Cygwin
|
||||
return 0;
|
||||
#endif // ndef __GLIBC__
|
||||
}
|
||||
|
||||
|
||||
@ -488,7 +361,7 @@ bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
|
||||
|
||||
bool VirtualMemory::Uncommit(void* address, size_t size) {
|
||||
return mmap(address, size, PROT_NONE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, // | MAP_FIXED, - Cygwin doesn't have MAP_FIXED
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
|
||||
kMmapFd, kMmapFdOffset) != MAP_FAILED;
|
||||
}
|
||||
|
||||
@ -713,11 +586,6 @@ bool CygwinSemaphore::Wait(int timeout) {
|
||||
while (true) {
|
||||
int result = sem_timedwait(&sem_, &ts);
|
||||
if (result == 0) return true; // Successfully got semaphore.
|
||||
if (result > 0) {
|
||||
// For glibc prior to 2.3.4 sem_timedwait returns the error instead of -1.
|
||||
errno = result;
|
||||
result = -1;
|
||||
}
|
||||
if (result == -1 && errno == ETIMEDOUT) return false; // Timeout.
|
||||
CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup.
|
||||
}
|
||||
@ -731,25 +599,112 @@ Semaphore* OS::CreateSemaphore(int count) {
|
||||
|
||||
#ifdef ENABLE_LOGGING_AND_PROFILING
|
||||
|
||||
typedef struct ucontext ucontext_t;
|
||||
|
||||
static Sampler* active_sampler_ = NULL;
|
||||
static pthread_t vm_tid_ = 0;
|
||||
|
||||
|
||||
static pthread_t GetThreadID() {
|
||||
return pthread_self();
|
||||
}
|
||||
|
||||
|
||||
static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
|
||||
USE(info);
|
||||
if (signal != SIGPROF) return;
|
||||
if (active_sampler_ == NULL || !active_sampler_->IsActive()) return;
|
||||
if (vm_tid_ != GetThreadID()) return;
|
||||
|
||||
TickSample sample_obj;
|
||||
TickSample* sample = CpuProfiler::TickSampleEvent();
|
||||
if (sample == NULL) sample = &sample_obj;
|
||||
|
||||
// Extracting the sample from the context is extremely machine dependent.
|
||||
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
|
||||
sample->state = Top::current_vm_state();
|
||||
#if V8_HOST_ARCH_IA32
|
||||
sample->pc = reinterpret_cast<Address>(ucontext->eip);
|
||||
sample->sp = reinterpret_cast<Address>(ucontext->esp);
|
||||
sample->fp = reinterpret_cast<Address>(ucontext->ebp);
|
||||
#else
|
||||
UNIMPLEMENTED();
|
||||
#endif
|
||||
active_sampler_->SampleStack(sample);
|
||||
active_sampler_->Tick(sample);
|
||||
}
|
||||
|
||||
|
||||
class Sampler::PlatformData : public Malloced {
|
||||
public:
|
||||
enum SleepInterval {
|
||||
FULL_INTERVAL,
|
||||
HALF_INTERVAL
|
||||
};
|
||||
|
||||
explicit PlatformData(Sampler* sampler)
|
||||
: sampler_(sampler),
|
||||
signal_handler_installed_(false) {
|
||||
signal_handler_installed_(false),
|
||||
vm_tgid_(getpid()),
|
||||
signal_sender_launched_(false) {
|
||||
}
|
||||
|
||||
void SignalSender() {
|
||||
while (sampler_->IsActive()) {
|
||||
if (rate_limiter_.SuspendIfNecessary()) continue;
|
||||
if (sampler_->IsProfiling() && RuntimeProfiler::IsEnabled()) {
|
||||
SendProfilingSignal();
|
||||
Sleep(HALF_INTERVAL);
|
||||
RuntimeProfiler::NotifyTick();
|
||||
Sleep(HALF_INTERVAL);
|
||||
} else {
|
||||
if (sampler_->IsProfiling()) SendProfilingSignal();
|
||||
if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
|
||||
Sleep(FULL_INTERVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendProfilingSignal() {
|
||||
pthread_kill(vm_tid_, SIGPROF);
|
||||
}
|
||||
|
||||
void Sleep(SleepInterval full_or_half) {
|
||||
// Convert ms to us and subtract 100 us to compensate delays
|
||||
// occuring during signal delivery.
|
||||
useconds_t interval = sampler_->interval_ * 1000 - 100;
|
||||
if (full_or_half == HALF_INTERVAL) interval /= 2;
|
||||
int result = usleep(interval);
|
||||
#ifdef DEBUG
|
||||
if (result != 0 && errno != EINTR) {
|
||||
fprintf(stderr,
|
||||
"SignalSender usleep error; interval = %u, errno = %d\n",
|
||||
static_cast<int>(interval),
|
||||
errno);
|
||||
ASSERT(result == 0 || errno == EINTR);
|
||||
}
|
||||
#endif
|
||||
USE(result);
|
||||
}
|
||||
|
||||
Sampler* sampler_;
|
||||
bool signal_handler_installed_;
|
||||
struct sigaction old_signal_handler_;
|
||||
int vm_tgid_;
|
||||
bool signal_sender_launched_;
|
||||
pthread_t signal_sender_thread_;
|
||||
RuntimeProfilerRateLimiter rate_limiter_;
|
||||
};
|
||||
|
||||
|
||||
static void* SenderEntry(void* arg) {
|
||||
Sampler::PlatformData* data =
|
||||
reinterpret_cast<Sampler::PlatformData*>(arg);
|
||||
data->SignalSender();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Sampler::Sampler(int interval)
|
||||
: interval_(interval),
|
||||
profiling_(false),
|
||||
@ -760,19 +715,61 @@ Sampler::Sampler(int interval)
|
||||
|
||||
|
||||
Sampler::~Sampler() {
|
||||
ASSERT(!data_->signal_sender_launched_);
|
||||
delete data_;
|
||||
}
|
||||
|
||||
|
||||
void Sampler::Start() {
|
||||
active_ = true;
|
||||
// There can only be one active sampler at the time on POSIX
|
||||
// platforms.
|
||||
ASSERT(!IsActive());
|
||||
vm_tid_ = pthread_self();
|
||||
|
||||
// Request profiling signals.
|
||||
struct sigaction sa;
|
||||
sa.sa_sigaction = ProfilerSignalHandler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||
if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return;
|
||||
data_->signal_handler_installed_ = true;
|
||||
|
||||
// Start a thread that sends SIGPROF signal to VM thread.
|
||||
// Sending the signal ourselves instead of relying on itimer provides
|
||||
// much better accuracy.
|
||||
SetActive(true);
|
||||
if (pthread_create(
|
||||
&data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
|
||||
data_->signal_sender_launched_ = true;
|
||||
}
|
||||
|
||||
// Set this sampler as the active sampler.
|
||||
active_sampler_ = this;
|
||||
}
|
||||
|
||||
|
||||
void Sampler::Stop() {
|
||||
active_ = false;
|
||||
SetActive(false);
|
||||
|
||||
// Wait for signal sender termination (it will exit after setting
|
||||
// active_ to false).
|
||||
if (data_->signal_sender_launched_) {
|
||||
Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
|
||||
pthread_join(data_->signal_sender_thread_, NULL);
|
||||
data_->signal_sender_launched_ = false;
|
||||
}
|
||||
|
||||
// Restore old signal handler
|
||||
if (data_->signal_handler_installed_) {
|
||||
sigaction(SIGPROF, &data_->old_signal_handler_, 0);
|
||||
data_->signal_handler_installed_ = false;
|
||||
}
|
||||
|
||||
// This sampler is no longer the active sampler.
|
||||
active_sampler_ = NULL;
|
||||
}
|
||||
|
||||
|
||||
#endif // ENABLE_LOGGING_AND_PROFILING
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
2
wscript
2
wscript
@ -196,7 +196,7 @@ def configure(conf):
|
||||
|
||||
conf.env["USE_DEBUG"] = o.debug
|
||||
# Snapshot building does noet seem to work on cygwin and mingw32
|
||||
conf.env["SNAPSHOT_V8"] = not o.without_snapshot and not sys.platform.startswith("cygwin") and not sys.platform.startswith("win32")
|
||||
conf.env["SNAPSHOT_V8"] = not o.without_snapshot and not sys.platform.startswith("win32")
|
||||
if sys.platform.startswith("sunos"):
|
||||
conf.env["SNAPSHOT_V8"] = False
|
||||
conf.env["USE_PROFILING"] = o.profile
|
||||
|
Loading…
x
Reference in New Issue
Block a user