From 0c1255453eb36144c2a895397ebcd3aec984e87f Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Tue, 19 Jan 2010 23:38:20 +0000 Subject: [PATCH] Initial Solaris support --- deps/evcom/evcom.c | 2 +- deps/udns/Makefile.in | 2 +- deps/udns/configure | 1 + deps/v8/SConstruct | 22 +- deps/v8/src/SConscript | 4 + deps/v8/src/dtoa-config.c | 7 +- deps/v8/src/platform-freebsd.cc | 24 + deps/v8/src/platform-linux.cc | 24 + deps/v8/src/platform-macos.cc | 24 + deps/v8/src/platform-openbsd.cc | 24 + deps/v8/src/platform-posix.cc | 25 - deps/v8/src/platform-solaris.cc | 686 ++++++++++++++++++ deps/v8/src/platform.h | 14 + deps/v8/test/cctest/test-compiler.cc | 3 +- deps/v8/tools/utils.py | 4 + .../scons-local-1.2.0/SCons/Platform/posix.py | 2 +- wscript | 29 +- 17 files changed, 857 insertions(+), 40 deletions(-) create mode 100644 deps/v8/src/platform-solaris.cc diff --git a/deps/evcom/evcom.c b/deps/evcom/evcom.c index 9490168921..0f48ab0812 100644 --- a/deps/evcom/evcom.c +++ b/deps/evcom/evcom.c @@ -1317,7 +1317,7 @@ int evcom_stream_pair (evcom_stream *a, evcom_stream *b) int sv[2]; int old_errno; - int r = socketpair(PF_LOCAL, SOCK_STREAM, 0, sv); + int r = socketpair(PF_UNIX, SOCK_STREAM, 0, sv); if (r < 0) return -1; r = set_nonblock(sv[0]); diff --git a/deps/udns/Makefile.in b/deps/udns/Makefile.in index fe83c7cd2d..4e0e56ec59 100644 --- a/deps/udns/Makefile.in +++ b/deps/udns/Makefile.in @@ -57,7 +57,7 @@ CDEFS = @CDEFS@ PICFLAGS = -fPIC AWK = awk -all: static +all: staticlib .SUFFIXES: .c .o .lo diff --git a/deps/udns/configure b/deps/udns/configure index 1cbac6b308..14e1b7078c 100755 --- a/deps/udns/configure +++ b/deps/udns/configure @@ -83,6 +83,7 @@ ac_ign \ #include #include #include +#include int main() { char buf[64]; long x = 0; diff --git a/deps/v8/SConstruct b/deps/v8/SConstruct index 97189073b1..cd214646da 100644 --- a/deps/v8/SConstruct +++ b/deps/v8/SConstruct @@ -35,7 +35,6 @@ root_dir = dirname(File('SConstruct').rfile().abspath) sys.path.append(join(root_dir, 'tools')) import js2c, utils - # ANDROID_TOP is the top of the Android checkout, fetched from the environment # variable 'TOP'. You will also need to set the CXX, CC, AR and RANLIB # environment variables to the cross-compiling tools. @@ -157,6 +156,11 @@ LIBRARY_FLAGS = { 'LIBPATH' : ['/usr/local/lib'], 'CCFLAGS': ['-ansi'], }, + 'os:solaris': { + 'CPPPATH' : ['/usr/local/include'], + 'LIBPATH' : ['/usr/local/lib'], + 'CCFLAGS': ['-ansi'], + }, 'os:win32': { 'CCFLAGS': ['-DWIN32'], 'CXXFLAGS': ['-DWIN32'], @@ -313,6 +317,9 @@ MKSNAPSHOT_EXTRA_FLAGS = { 'os:freebsd': { 'LIBS': ['execinfo', 'pthread'] }, + 'os:solaris': { + 'LIBS': ['pthread', 'socket', 'nsl', 'rt'] + }, 'os:openbsd': { 'LIBS': ['execinfo', 'pthread'] }, @@ -362,6 +369,9 @@ CCTEST_EXTRA_FLAGS = { 'os:freebsd': { 'LIBS': ['execinfo', 'pthread'] }, + 'os:solaris': { + 'LIBS': ['pthread', 'socket', 'nsl', 'rt'] + }, 'os:openbsd': { 'LIBS': ['execinfo', 'pthread'] }, @@ -420,6 +430,10 @@ SAMPLE_FLAGS = { 'LIBPATH' : ['/usr/local/lib'], 'LIBS': ['execinfo', 'pthread'] }, + 'os:solaris': { + 'LIBPATH' : ['/usr/local/lib'], + 'LIBS': ['pthread', 'socket', 'nsl', 'rt'] + }, 'os:openbsd': { 'LIBPATH' : ['/usr/local/lib'], 'LIBS': ['execinfo', 'pthread'] @@ -529,6 +543,9 @@ D8_FLAGS = { 'os:freebsd': { 'LIBS': ['pthread'], }, + 'os:solaris': { + 'LIBS': ['pthread', 'socket', 'nsl', 'rt'] + }, 'os:openbsd': { 'LIBS': ['pthread'], }, @@ -582,7 +599,7 @@ SIMPLE_OPTIONS = { 'help': 'the toolchain to use (' + TOOLCHAIN_GUESS + ')' }, 'os': { - 'values': ['freebsd', 'linux', 'macos', 'win32', 'android', 'openbsd'], + 'values': ['freebsd', 'linux', 'macos', 'win32', 'android', 'openbsd', 'solaris'], 'default': OS_GUESS, 'help': 'the os to build for (' + OS_GUESS + ')' }, @@ -936,6 +953,7 @@ def BuildSpecific(env, mode, env_overrides): # Link the object files into a library. env.Replace(**context.flags['v8']) + context.ApplyEnvOverrides(env) if context.options['library'] == 'static': library = env.StaticLibrary(library_name, object_files) diff --git a/deps/v8/src/SConscript b/deps/v8/src/SConscript index 28996b05ee..9f8e4190bf 100755 --- a/deps/v8/src/SConscript +++ b/deps/v8/src/SConscript @@ -168,6 +168,7 @@ SOURCES = { 'os:linux': ['platform-linux.cc', 'platform-posix.cc'], 'os:android': ['platform-linux.cc', 'platform-posix.cc'], 'os:macos': ['platform-macos.cc', 'platform-posix.cc'], + 'os:solaris': ['platform-solaris.cc', 'platform-posix.cc'], 'os:nullos': ['platform-nullos.cc'], 'os:win32': ['platform-win32.cc'], 'mode:release': [], @@ -196,6 +197,9 @@ D8_FILES = { 'os:openbsd': [ 'd8-posix.cc' ], + 'os:solaris': [ + 'd8-posix.cc' + ], 'os:win32': [ 'd8-windows.cc' ], diff --git a/deps/v8/src/dtoa-config.c b/deps/v8/src/dtoa-config.c index a1acd2dd44..9c5ee33194 100644 --- a/deps/v8/src/dtoa-config.c +++ b/deps/v8/src/dtoa-config.c @@ -38,7 +38,8 @@ */ #if !(defined(__APPLE__) && defined(__MACH__)) && \ - !defined(WIN32) && !defined(__FreeBSD__) && !defined(__OpenBSD__) + !defined(WIN32) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && \ + !defined(__sun) #include #endif #include @@ -47,7 +48,7 @@ /* The floating point word order on ARM is big endian when floating point * emulation is used, even if the byte order is little endian */ #if !(defined(__APPLE__) && defined(__MACH__)) && !defined(WIN32) && \ - !defined(__FreeBSD__) && !defined(__OpenBSD__) && \ + !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__sun) && \ __FLOAT_WORD_ORDER == __BIG_ENDIAN #define IEEE_MC68k #else @@ -56,7 +57,7 @@ #define __MATH_H__ #if defined(__APPLE__) && defined(__MACH__) || defined(__FreeBSD__) || \ - defined(__OpenBSD__) + defined(__OpenBSD__) || defined(__sun) /* stdlib.h on FreeBSD and Apple's 10.5 and later SDKs will mangle the * name of strtod. If it's included after strtod is redefined as * gay_strtod, it will mangle the name of gay_strtod, which is diff --git a/deps/v8/src/platform-freebsd.cc b/deps/v8/src/platform-freebsd.cc index 353d165403..ee0d7b8c2f 100644 --- a/deps/v8/src/platform-freebsd.cc +++ b/deps/v8/src/platform-freebsd.cc @@ -73,6 +73,12 @@ double ceiling(double x) { } +double OS::nan_value() { + // NAN from math.h is defined in C99 and not in POSIX. + return NAN; +} + + void OS::Setup() { // Seed the random number generator. // Convert the current time to a 64-bit integer first, before converting it @@ -95,6 +101,24 @@ int OS::ActivationFrameAlignment() { } +const char* OS::LocalTimezone(double time) { + if (isnan(time)) return ""; + time_t tv = static_cast(floor(time/msPerSecond)); + struct tm* t = localtime(&tv); + if (NULL == t) return ""; + return t->tm_zone; +} + + +double OS::LocalTimeOffset() { + time_t tv = time(NULL); + struct tm* t = localtime(&tv); + // tm_gmtoff includes any daylight savings offset, so subtract it. + return static_cast(t->tm_gmtoff * msPerSecond - + (t->tm_isdst > 0 ? 3600 * msPerSecond : 0)); +} + + // We keep the lowest and highest addresses mapped as a quick way of // determining that pointers are outside the heap (used mostly in assertions // and verification). The estimate is conservative, ie, not all addresses in diff --git a/deps/v8/src/platform-linux.cc b/deps/v8/src/platform-linux.cc index bfcd8fba72..403bf42b75 100644 --- a/deps/v8/src/platform-linux.cc +++ b/deps/v8/src/platform-linux.cc @@ -73,6 +73,12 @@ double ceiling(double x) { } +double OS::nan_value() { + // NAN from math.h is defined in C99 and not in POSIX. + return NAN; +} + + void OS::Setup() { // Seed the random number generator. // Convert the current time to a 64-bit integer first, before converting it @@ -159,6 +165,24 @@ int OS::ActivationFrameAlignment() { } +const char* OS::LocalTimezone(double time) { + if (isnan(time)) return ""; + time_t tv = static_cast(floor(time/msPerSecond)); + struct tm* t = localtime(&tv); + if (NULL == t) return ""; + return t->tm_zone; +} + + +double OS::LocalTimeOffset() { + time_t tv = time(NULL); + struct tm* t = localtime(&tv); + // tm_gmtoff includes any daylight savings offset, so subtract it. + return static_cast(t->tm_gmtoff * msPerSecond - + (t->tm_isdst > 0 ? 3600 * msPerSecond : 0)); +} + + // We keep the lowest and highest addresses mapped as a quick way of // determining that pointers are outside the heap (used mostly in assertions // and verification). The estimate is conservative, ie, not all addresses in diff --git a/deps/v8/src/platform-macos.cc b/deps/v8/src/platform-macos.cc index 0d5be45eec..0c7a8b816b 100644 --- a/deps/v8/src/platform-macos.cc +++ b/deps/v8/src/platform-macos.cc @@ -86,6 +86,12 @@ double ceiling(double x) { } +double OS::nan_value() { + // NAN from math.h is defined in C99 and not in POSIX. + return NAN; +} + + void OS::Setup() { // Seed the random number generator. // Convert the current time to a 64-bit integer first, before converting it @@ -259,6 +265,24 @@ int OS::ActivationFrameAlignment() { } +const char* OS::LocalTimezone(double time) { + if (isnan(time)) return ""; + time_t tv = static_cast(floor(time/msPerSecond)); + struct tm* t = localtime(&tv); + if (NULL == t) return ""; + return t->tm_zone; +} + + +double OS::LocalTimeOffset() { + time_t tv = time(NULL); + struct tm* t = localtime(&tv); + // tm_gmtoff includes any daylight savings offset, so subtract it. + return static_cast(t->tm_gmtoff * msPerSecond - + (t->tm_isdst > 0 ? 3600 * msPerSecond : 0)); +} + + int OS::StackWalk(Vector frames) { // If weak link to execinfo lib has failed, ie because we are on 10.4, abort. if (backtrace == NULL) diff --git a/deps/v8/src/platform-openbsd.cc b/deps/v8/src/platform-openbsd.cc index 6d273047da..c85861c43e 100644 --- a/deps/v8/src/platform-openbsd.cc +++ b/deps/v8/src/platform-openbsd.cc @@ -72,6 +72,12 @@ double ceiling(double x) { } +double OS::nan_value() { + // NAN from math.h is defined in C99 and not in POSIX. + return NAN; +} + + void OS::Setup() { // Seed the random number generator. // Convert the current time to a 64-bit integer first, before converting it @@ -94,6 +100,24 @@ int OS::ActivationFrameAlignment() { } +const char* OS::LocalTimezone(double time) { + if (isnan(time)) return ""; + time_t tv = static_cast(floor(time/msPerSecond)); + struct tm* t = localtime(&tv); + if (NULL == t) return ""; + return t->tm_zone; +} + + +double OS::LocalTimeOffset() { + time_t tv = time(NULL); + struct tm* t = localtime(&tv); + // tm_gmtoff includes any daylight savings offset, so subtract it. + return static_cast(t->tm_gmtoff * msPerSecond - + (t->tm_isdst > 0 ? 3600 * msPerSecond : 0)); +} + + // We keep the lowest and highest addresses mapped as a quick way of // determining that pointers are outside the heap (used mostly in assertions // and verification). The estimate is conservative, ie, not all addresses in diff --git a/deps/v8/src/platform-posix.cc b/deps/v8/src/platform-posix.cc index 41e0e64f3b..d42e34e66d 100644 --- a/deps/v8/src/platform-posix.cc +++ b/deps/v8/src/platform-posix.cc @@ -61,13 +61,6 @@ double modulo(double x, double y) { return fmod(x, y); } - -double OS::nan_value() { - // NAN from math.h is defined in C99 and not in POSIX. - return NAN; -} - - // ---------------------------------------------------------------------------- // POSIX date/time support. // @@ -99,15 +92,6 @@ int64_t OS::Ticks() { } -const char* OS::LocalTimezone(double time) { - if (isnan(time)) return ""; - time_t tv = static_cast(floor(time/msPerSecond)); - struct tm* t = localtime(&tv); - if (NULL == t) return ""; - return t->tm_zone; -} - - double OS::DaylightSavingsOffset(double time) { if (isnan(time)) return nan_value(); time_t tv = static_cast(floor(time/msPerSecond)); @@ -117,15 +101,6 @@ double OS::DaylightSavingsOffset(double time) { } -double OS::LocalTimeOffset() { - time_t tv = time(NULL); - struct tm* t = localtime(&tv); - // tm_gmtoff includes any daylight savings offset, so subtract it. - return static_cast(t->tm_gmtoff * msPerSecond - - (t->tm_isdst > 0 ? 3600 * msPerSecond : 0)); -} - - // ---------------------------------------------------------------------------- // POSIX stdio support. // diff --git a/deps/v8/src/platform-solaris.cc b/deps/v8/src/platform-solaris.cc new file mode 100644 index 0000000000..d58ce58764 --- /dev/null +++ b/deps/v8/src/platform-solaris.cc @@ -0,0 +1,686 @@ +// Copyright 2006-2009 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Platform specific code for Solaris 10 goes here. For the POSIX comaptible +// parts the implementation is in platform-posix.cc. + +#include // for stack alignment +#include // getpagesize() +#include // mmap() +#include // usleep() +#include // backtrace(), backtrace_symbols() +#include +#include // for sched_yield +#include +#include +#include // gettimeofday(), timeradd() +#include +#include // finite() +#include // sigemptyset(), etc + +#undef MAP_TYPE + +#include "v8.h" + +#include "platform.h" + + +namespace v8 { +namespace internal { + +int isfinite(double x) { + return finite(x) && !isnand(x); +} + +} } // namespace v8::internal + + +// Test for infinity - usually defined in math.h +int isinf(double x) { + fpclass_t fpc = fpclass(x); + return (fpc == FP_NINF || fpc == FP_PINF); +} + + +// Test if x is less than y and both nominal - usually defined in math.h +int isless(double x, double y) { + return isnan(x) || isnan(y) ? 0 : x < y; +} + + +// Test if x is greater than y and both nominal - usually defined in math.h +int isgreater(double x, double y) { + return isnan(x) || isnan(y) ? 0 : x > y; +} + + +// Classify floating point number - usually defined in math.h#ifndef fpclassify +int fpclassify(double x) { + // Use the Solaris-specific fpclass() for classification. + fpclass_t fpc = fpclass(x); + + switch (fpc) { + case FP_PNORM: + case FP_NNORM: + return FP_NORMAL; + case FP_PZERO: + case FP_NZERO: + return FP_ZERO; + case FP_PDENORM: + case FP_NDENORM: + return FP_SUBNORMAL; + case FP_PINF: + case FP_NINF: + return FP_INFINITE; + default: + // All cases should be covered by the code above. + ASSERT(fpc == FP_QNAN || fpc == FP_SNAN); + return FP_NAN; + } +} + + +int signbit(double x) { + // We need to take care of the special case of both positive + // and negative versions of zero. + if (x == 0) + return fpclass(x) == FP_NZERO; + else + return x < 0; +} + + +namespace v8 { +namespace internal { + +// 0 is never a valid thread id on Solaris since the main thread is 1 and +// subsequent have their ids incremented from there +static const pthread_t kNoThread = (pthread_t) 0; + + +// TODO: Test to see if ceil() is correct on Solaris. +double ceiling(double x) { + return ceil(x); +} + + +void OS::Setup() { + // Seed the random number generator. + // Convert the current time to a 64-bit integer first, before converting it + // to an unsigned. Going directly will cause an overflow and the seed to be + // set to all ones. The seed will be identical for different instances that + // call this setup code within the same millisecond. + uint64_t seed = static_cast(TimeCurrentMillis()); + srandom(static_cast(seed)); +} + + +uint64_t OS::CpuFeaturesImpliedByPlatform() { + return 0; // Solaris runs on a lot of things. +} + + +double OS::nan_value() { + static double NAN = __builtin_nan("0x0"); + return NAN; +} + + +int OS::ActivationFrameAlignment() { + return STACK_ALIGN; +} + + +const char* OS::LocalTimezone(double time) { + if (isnan(time)) return ""; + time_t tv = static_cast(floor(time/msPerSecond)); + struct tm* t = localtime(&tv); + if (NULL == t) return ""; + return tzname[0]; // the location of the timezone string on Solaris +} + + +double OS::LocalTimeOffset() { + int days, hours, minutes; + time_t tv = time(NULL); + + // on Solaris, struct tm does not contain a tm_gmtoff field... + struct tm* loc = localtime(&tv); + struct tm* utc = gmtime(&tv); + + // calulate the utc offset + days = loc->tm_yday = utc->tm_yday; + hours = ((days < -1 ? 24 : 1 < days ? -24 : days * 24) + + loc->tm_hour - utc->tm_hour); + minutes = hours * 60 + loc->tm_min - utc->tm_min; + + // don't include any daylight savings offset in local time + if (loc->tm_isdst > 0) minutes -= 60; + + // the result is in milliseconds + return static_cast(minutes * 60 * msPerSecond); +} + + +// We keep the lowest and highest addresses mapped as a quick way of +// determining that pointers are outside the heap (used mostly in assertions +// and verification). The estimate is conservative, ie, not all addresses in +// 'allocated' space are actually allocated to our heap. The range is +// [lowest, highest), inclusive on the low and and exclusive on the high end. +static void* lowest_ever_allocated = reinterpret_cast(-1); +static void* highest_ever_allocated = reinterpret_cast(0); + + +static void UpdateAllocatedSpaceLimits(void* address, int size) { + lowest_ever_allocated = Min(lowest_ever_allocated, address); + highest_ever_allocated = + Max(highest_ever_allocated, + reinterpret_cast(reinterpret_cast(address) + size)); +} + + +bool OS::IsOutsideAllocatedSpace(void* address) { + return address < lowest_ever_allocated || address >= highest_ever_allocated; +} + + +size_t OS::AllocateAlignment() { + return (size_t)getpagesize(); +} + + +void* OS::Allocate(const size_t requested, + size_t* allocated, + bool is_executable) { + const size_t msize = RoundUp(requested, getpagesize()); + int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); + void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0); + + if (mbase == MAP_FAILED) { + LOG(StringEvent("OS::Allocate", "mmap failed")); + return NULL; + } + *allocated = msize; + UpdateAllocatedSpaceLimits(mbase, msize); + return mbase; +} + + +void OS::Free(void* address, const size_t size) { + // TODO(1240712): munmap has a return value which is ignored here. + int result = munmap(address, size); + USE(result); + ASSERT(result == 0); +} + + +#ifdef ENABLE_HEAP_PROTECTION + +void OS::Protect(void* address, size_t size) { + // TODO(1240712): mprotect has a return value which is ignored here. + mprotect(address, size, PROT_READ); +} + + +void OS::Unprotect(void* address, size_t size, bool is_executable) { + // TODO(1240712): mprotect has a return value which is ignored here. + int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); + mprotect(address, size, prot); +} + +#endif + + +void OS::Sleep(int milliseconds) { + useconds_t ms = static_cast(milliseconds); + usleep(1000 * ms); +} + + +void OS::Abort() { + // Redirect to std abort to signal abnormal program termination + abort(); +} + + +void OS::DebugBreak() { + asm("int $3"); +} + + +class PosixMemoryMappedFile : public OS::MemoryMappedFile { + public: + PosixMemoryMappedFile(FILE* file, void* memory, int size) + : file_(file), memory_(memory), size_(size) { } + virtual ~PosixMemoryMappedFile(); + virtual void* memory() { return memory_; } + private: + FILE* file_; + void* memory_; + int size_; +}; + + +OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, + void* initial) { + FILE* file = fopen(name, "w+"); + if (file == NULL) return NULL; + int result = fwrite(initial, size, 1, file); + if (result < 1) { + fclose(file); + return NULL; + } + void* memory = + mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); + return new PosixMemoryMappedFile(file, memory, size); +} + + +PosixMemoryMappedFile::~PosixMemoryMappedFile() { + if (memory_) munmap(memory_, size_); + fclose(file_); +} + + +void OS::LogSharedLibraryAddresses() { +#ifdef ENABLE_LOGGING_AND_PROFILING + UNIMPLEMENTED(); +#endif +} + + +int OS::StackWalk(Vector frames) { + int frames_size = frames.length(); + void** addresses = NewArray(frames_size); + + int frames_count = backtrace(addresses, frames_size); + + char** symbols; + symbols = backtrace_symbols(addresses, frames_count); + if (symbols == NULL) { + DeleteArray(addresses); + 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'; + } + + DeleteArray(addresses); + free(symbols); + + return frames_count; +} + + +// Constants used for mmap. +static const int kMmapFd = -1; +static const int kMmapFdOffset = 0; + + +VirtualMemory::VirtualMemory(size_t size) { + address_ = mmap(NULL, size, PROT_NONE, + MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, + kMmapFd, kMmapFdOffset); + size_ = size; +} + + +VirtualMemory::~VirtualMemory() { + if (IsReserved()) { + if (0 == munmap(address(), size())) address_ = MAP_FAILED; + } +} + + +bool VirtualMemory::IsReserved() { + return address_ != MAP_FAILED; +} + + +bool VirtualMemory::Commit(void* address, size_t size, bool executable) { + int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0); + if (MAP_FAILED == mmap(address, size, prot, + MAP_PRIVATE | MAP_ANON | MAP_FIXED, + kMmapFd, kMmapFdOffset)) { + return false; + } + + UpdateAllocatedSpaceLimits(address, size); + return true; +} + + +bool VirtualMemory::Uncommit(void* address, size_t size) { + return mmap(address, size, PROT_NONE, + MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED, + kMmapFd, kMmapFdOffset) != MAP_FAILED; +} + + +class ThreadHandle::PlatformData : public Malloced { + public: + explicit PlatformData(ThreadHandle::Kind kind) { + Initialize(kind); + } + + void Initialize(ThreadHandle::Kind kind) { + switch (kind) { + case ThreadHandle::SELF: thread_ = pthread_self(); break; + case ThreadHandle::INVALID: thread_ = kNoThread; break; + } + } + + pthread_t thread_; // Thread handle for pthread. +}; + + +ThreadHandle::ThreadHandle(Kind kind) { + data_ = new PlatformData(kind); +} + + +void ThreadHandle::Initialize(ThreadHandle::Kind kind) { + data_->Initialize(kind); +} + + +ThreadHandle::~ThreadHandle() { + delete data_; +} + + +bool ThreadHandle::IsSelf() const { + return pthread_equal(data_->thread_, pthread_self()); +} + + +bool ThreadHandle::IsValid() const { + return data_->thread_ != kNoThread; +} + + +Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) { +} + + +Thread::~Thread() { +} + + +static void* ThreadEntry(void* arg) { + Thread* thread = reinterpret_cast(arg); + // This is also initialized by the first argument to pthread_create() but we + // don't know which thread will run first (the original thread or the new + // one) so we initialize it here too. + thread->thread_handle_data()->thread_ = pthread_self(); + ASSERT(thread->IsValid()); + thread->Run(); + return NULL; +} + + +void Thread::Start() { + pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this); + ASSERT(IsValid()); +} + + +void Thread::Join() { + pthread_join(thread_handle_data()->thread_, NULL); +} + + +Thread::LocalStorageKey Thread::CreateThreadLocalKey() { + pthread_key_t key; + int result = pthread_key_create(&key, NULL); + USE(result); + ASSERT(result == 0); + return static_cast(key); +} + + +void Thread::DeleteThreadLocalKey(LocalStorageKey key) { + pthread_key_t pthread_key = static_cast(key); + int result = pthread_key_delete(pthread_key); + USE(result); + ASSERT(result == 0); +} + + +void* Thread::GetThreadLocal(LocalStorageKey key) { + pthread_key_t pthread_key = static_cast(key); + return pthread_getspecific(pthread_key); +} + + +void Thread::SetThreadLocal(LocalStorageKey key, void* value) { + pthread_key_t pthread_key = static_cast(key); + pthread_setspecific(pthread_key, value); +} + + +void Thread::YieldCPU() { + sched_yield(); +} + + +class SolarisMutex : public Mutex { + public: + + SolarisMutex() { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mutex_, &attr); + } + + ~SolarisMutex() { pthread_mutex_destroy(&mutex_); } + + int Lock() { return pthread_mutex_lock(&mutex_); } + + int Unlock() { return pthread_mutex_unlock(&mutex_); } + + private: + pthread_mutex_t mutex_; +}; + + +Mutex* OS::CreateMutex() { + return new SolarisMutex(); +} + + +class SolarisSemaphore : public Semaphore { + public: + explicit SolarisSemaphore(int count) { sem_init(&sem_, 0, count); } + virtual ~SolarisSemaphore() { sem_destroy(&sem_); } + + virtual void Wait(); + virtual bool Wait(int timeout); + virtual void Signal() { sem_post(&sem_); } + private: + sem_t sem_; +}; + + +void SolarisSemaphore::Wait() { + while (true) { + int result = sem_wait(&sem_); + if (result == 0) return; // Successfully got semaphore. + CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. + } +} + + +#ifndef TIMEVAL_TO_TIMESPEC +#define TIMEVAL_TO_TIMESPEC(tv, ts) do { \ + (ts)->tv_sec = (tv)->tv_sec; \ + (ts)->tv_nsec = (tv)->tv_usec * 1000; \ +} while (false) +#endif + + +#ifndef timeradd +#define timeradd(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ + if ((result)->tv_usec >= 1000000) { \ + ++(result)->tv_sec; \ + (result)->tv_usec -= 1000000; \ + } \ + } while (0) +#endif + + +bool SolarisSemaphore::Wait(int timeout) { + const long kOneSecondMicros = 1000000; // NOLINT + + // Split timeout into second and nanosecond parts. + struct timeval delta; + delta.tv_usec = timeout % kOneSecondMicros; + delta.tv_sec = timeout / kOneSecondMicros; + + struct timeval current_time; + // Get the current time. + if (gettimeofday(¤t_time, NULL) == -1) { + return false; + } + + // Calculate time for end of timeout. + struct timeval end_time; + timeradd(¤t_time, &delta, &end_time); + + struct timespec ts; + TIMEVAL_TO_TIMESPEC(&end_time, &ts); + // Wait for semaphore signalled or timeout. + while (true) { + int result = sem_timedwait(&sem_, &ts); + if (result == 0) return true; // Successfully got semaphore. + if (result == -1 && errno == ETIMEDOUT) return false; // Timeout. + CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. + } +} + + +Semaphore* OS::CreateSemaphore(int count) { + return new SolarisSemaphore(count); +} + + +#ifdef ENABLE_LOGGING_AND_PROFILING + +static Sampler* active_sampler_ = NULL; + +static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { + USE(info); + if (signal != SIGPROF) return; + if (active_sampler_ == NULL) return; + + TickSample sample; + + // We always sample the VM state. + sample.state = Logger::state(); + + active_sampler_->Tick(&sample); +} + + +class Sampler::PlatformData : public Malloced { + public: + PlatformData() { + signal_handler_installed_ = false; + } + + bool signal_handler_installed_; + struct sigaction old_signal_handler_; + struct itimerval old_timer_value_; +}; + + +Sampler::Sampler(int interval, bool profiling) + : interval_(interval), profiling_(profiling), active_(false) { + data_ = new PlatformData(); +} + + +Sampler::~Sampler() { + delete data_; +} + + +void Sampler::Start() { + // There can only be one active sampler at the time on POSIX + // platforms. + if (active_sampler_ != NULL) return; + + // Request profiling signals. + struct sigaction sa; + sa.sa_sigaction = ProfilerSignalHandler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return; + data_->signal_handler_installed_ = true; + + // Set the itimer to generate a tick for each interval. + itimerval itimer; + itimer.it_interval.tv_sec = interval_ / 1000; + itimer.it_interval.tv_usec = (interval_ % 1000) * 1000; + itimer.it_value.tv_sec = itimer.it_interval.tv_sec; + itimer.it_value.tv_usec = itimer.it_interval.tv_usec; + setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_); + + // Set this sampler as the active sampler. + active_sampler_ = this; + active_ = true; +} + + +void Sampler::Stop() { + // Restore old signal handler + if (data_->signal_handler_installed_) { + setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL); + sigaction(SIGPROF, &data_->old_signal_handler_, 0); + data_->signal_handler_installed_ = false; + } + + // This sampler is no longer the active sampler. + active_sampler_ = NULL; + active_ = false; +} + +#endif // ENABLE_LOGGING_AND_PROFILING + +} } // namespace v8::internal diff --git a/deps/v8/src/platform.h b/deps/v8/src/platform.h index 75e557cb44..861a48a94c 100644 --- a/deps/v8/src/platform.h +++ b/deps/v8/src/platform.h @@ -46,6 +46,20 @@ #define V8_INFINITY INFINITY +#ifdef __sun + +namespace v8 { +namespace internal { +int isfinite(double x); +} } +int isinf(double x); +int isless(double x, double y); +int isgreater(double x, double y); +int fpclassify(double x); +int signbit(double x); + +#endif // __sun + // Windows specific stuff. #ifdef WIN32 diff --git a/deps/v8/test/cctest/test-compiler.cc b/deps/v8/test/cctest/test-compiler.cc index 08037b3779..8c9e4ee574 100644 --- a/deps/v8/test/cctest/test-compiler.cc +++ b/deps/v8/test/cctest/test-compiler.cc @@ -26,6 +26,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include // wint_t #include "v8.h" @@ -73,7 +74,7 @@ v8::Handle PrintExtension::Print(const v8::Arguments& args) { uint16_t* string = NewArray(length + 1); string_obj->Write(string); for (int j = 0; j < length; j++) - printf("%lc", string[j]); + printf("%lc", (wint_t)string[j]); DeleteArray(string); } printf("\n"); diff --git a/deps/v8/tools/utils.py b/deps/v8/tools/utils.py index 196bb05555..435c12dee6 100644 --- a/deps/v8/tools/utils.py +++ b/deps/v8/tools/utils.py @@ -57,6 +57,8 @@ def GuessOS(): return 'freebsd' elif id == 'OpenBSD': return 'openbsd' + elif id == 'SunOS': + return 'solaris' else: return None @@ -67,6 +69,8 @@ def GuessArchitecture(): return 'arm' elif (not id) or (not re.match('(x|i[3-6])86', id) is None): return 'ia32' + elif id == 'i86pc': + return 'ia32' else: return None diff --git a/tools/scons/scons-local-1.2.0/SCons/Platform/posix.py b/tools/scons/scons-local-1.2.0/SCons/Platform/posix.py index 6d0b0747e2..2a7c544207 100644 --- a/tools/scons/scons-local-1.2.0/SCons/Platform/posix.py +++ b/tools/scons/scons-local-1.2.0/SCons/Platform/posix.py @@ -231,7 +231,7 @@ def generate(env): if not env.has_key('ENV'): env['ENV'] = {} - env['ENV']['PATH'] = '/usr/local/bin:/opt/bin:/bin:/usr/bin' + env['ENV']['PATH'] = os.environ.get("PATH") env['OBJPREFIX'] = '' env['OBJSUFFIX'] = '.o' env['SHOBJPREFIX'] = '$OBJPREFIX' diff --git a/wscript b/wscript index e6275e58a5..89be9aa2b2 100644 --- a/wscript +++ b/wscript @@ -108,8 +108,9 @@ def configure(conf): conf.env["USE_DEBUG"] = Options.options.debug conf.check(lib='dl', uselib_store='DL') - conf.env.append_value("CCFLAGS", "-rdynamic") - conf.env.append_value("LINKFLAGS_DL", "-rdynamic") + if not sys.platform.startswith("sunos"): + conf.env.append_value("CCFLAGS", "-rdynamic") + conf.env.append_value("LINKFLAGS_DL", "-rdynamic") if sys.platform.startswith("freebsd"): conf.check(lib='kvm', uselib_store='KVM') @@ -137,10 +138,19 @@ def configure(conf): conf.env.append_value("CCFLAGS", "-DEVCOM_HAVE_GNUTLS=1") conf.env.append_value("CXXFLAGS", "-DEVCOM_HAVE_GNUTLS=1") + if sys.platform.startswith("sunos"): + if not conf.check(lib='socket', uselib_store="SOCKET"): + conf.fatal("Cannot find socket library") + if not conf.check(lib='nsl', uselib_store="NSL"): + conf.fatal("Cannot find nsl library") + conf.sub_config('deps/libeio') conf.sub_config('deps/libev') - conf_subproject(conf, 'deps/udns', './configure') + if sys.platform.startswith("sunos"): + conf_subproject(conf, 'deps/udns', 'LIBS="-lsocket -lnsl" ./configure') + else: + conf_subproject(conf, 'deps/udns', './configure') conf.define("HAVE_CONFIG_H", 1) @@ -201,6 +211,7 @@ def build_udns(bld): debug.rule = rule % debug_dir t = join(bld.srcnode.abspath(bld.env_of_name("debug")), debug.target) bld.env_of_name('debug')["LINKFLAGS_UDNS"] = [t] + bld.install_files('${PREFIX}/include/node/', 'deps/udns/udns.h') def v8_cmd(bld, variant): @@ -247,7 +258,10 @@ def build_v8(bld): v8.uselib = "EXECINFO" bld.env["CPPPATH_V8"] = "deps/v8/include" t = join(bld.srcnode.abspath(bld.env_of_name("default")), v8.target) - bld.env_of_name('default')["LINKFLAGS_V8"] = ["-pthread", t] + if sys.platform.startswith("sunos"): + bld.env_of_name('default')["LINKFLAGS_V8"] = ["-mt", t] + else: + bld.env_of_name('default')["LINKFLAGS_V8"] = ["-pthread", t] ### v8 debug if bld.env["USE_DEBUG"]: @@ -256,7 +270,10 @@ def build_v8(bld): v8_debug.target = bld.env["staticlib_PATTERN"] % "v8_g" v8_debug.uselib = "EXECINFO" t = join(bld.srcnode.abspath(bld.env_of_name("debug")), v8_debug.target) - bld.env_of_name('debug')["LINKFLAGS_V8"] = ["-pthread", t] + if sys.platform.startswith("sunos"): + bld.env_of_name('debug')["LINKFLAGS_V8"] = ["-mt", t] + else: + bld.env_of_name('debug')["LINKFLAGS_V8"] = ["-pthread", t] bld.install_files('${PREFIX}/include/node/', 'deps/v8/include/*.h') @@ -352,7 +369,7 @@ def build(bld): """ node.add_objects = 'ev eio evcom http_parser coupling' node.uselib_local = '' - node.uselib = 'GNUTLS GPGERROR UDNS V8 EXECINFO DL KVM' + node.uselib = 'GNUTLS GPGERROR UDNS V8 EXECINFO DL KVM SOCKET NSL' node.install_path = '${PREFIX}/lib' node.install_path = '${PREFIX}/bin'