| OLD | NEW |
| (Empty) |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Platform-specific code for Solaris 10 goes here. For the POSIX-compatible | |
| 6 // parts, the implementation is in platform-posix.cc. | |
| 7 | |
| 8 #ifdef __sparc | |
| 9 # error "V8 does not support the SPARC CPU architecture." | |
| 10 #endif | |
| 11 | |
| 12 #include <dlfcn.h> // dladdr | |
| 13 #include <errno.h> | |
| 14 #include <ieeefp.h> // finite() | |
| 15 #include <pthread.h> | |
| 16 #include <semaphore.h> | |
| 17 #include <signal.h> // sigemptyset(), etc | |
| 18 #include <sys/mman.h> // mmap() | |
| 19 #include <sys/regset.h> | |
| 20 #include <sys/stack.h> // for stack alignment | |
| 21 #include <sys/time.h> // gettimeofday(), timeradd() | |
| 22 #include <time.h> | |
| 23 #include <ucontext.h> // walkstack(), getcontext() | |
| 24 #include <unistd.h> // getpagesize(), usleep() | |
| 25 | |
| 26 #include <cmath> | |
| 27 | |
| 28 #undef MAP_TYPE | |
| 29 | |
| 30 #include "src/platform.h" | |
| 31 #include "src/utils.h" | |
| 32 | |
| 33 | |
| 34 // It seems there is a bug in some Solaris distributions (experienced in | |
| 35 // SunOS 5.10 Generic_141445-09) which make it difficult or impossible to | |
| 36 // access signbit() despite the availability of other C99 math functions. | |
| 37 #ifndef signbit | |
| 38 namespace std { | |
| 39 // Test sign - usually defined in math.h | |
| 40 int signbit(double x) { | |
| 41 // We need to take care of the special case of both positive and negative | |
| 42 // versions of zero. | |
| 43 if (x == 0) { | |
| 44 return fpclass(x) & FP_NZERO; | |
| 45 } else { | |
| 46 // This won't detect negative NaN but that should be okay since we don't | |
| 47 // assume that behavior. | |
| 48 return x < 0; | |
| 49 } | |
| 50 } | |
| 51 } // namespace std | |
| 52 #endif // signbit | |
| 53 | |
| 54 namespace v8 { | |
| 55 namespace internal { | |
| 56 | |
| 57 | |
| 58 const char* OS::LocalTimezone(double time, TimezoneCache* cache) { | |
| 59 if (std::isnan(time)) return ""; | |
| 60 time_t tv = static_cast<time_t>(std::floor(time/msPerSecond)); | |
| 61 struct tm* t = localtime(&tv); | |
| 62 if (NULL == t) return ""; | |
| 63 return tzname[0]; // The location of the timezone string on Solaris. | |
| 64 } | |
| 65 | |
| 66 | |
| 67 double OS::LocalTimeOffset(TimezoneCache* cache) { | |
| 68 tzset(); | |
| 69 return -static_cast<double>(timezone * msPerSecond); | |
| 70 } | |
| 71 | |
| 72 | |
| 73 void* OS::Allocate(const size_t requested, | |
| 74 size_t* allocated, | |
| 75 bool is_executable) { | |
| 76 const size_t msize = RoundUp(requested, getpagesize()); | |
| 77 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); | |
| 78 void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0); | |
| 79 | |
| 80 if (mbase == MAP_FAILED) return NULL; | |
| 81 *allocated = msize; | |
| 82 return mbase; | |
| 83 } | |
| 84 | |
| 85 | |
| 86 class PosixMemoryMappedFile : public OS::MemoryMappedFile { | |
| 87 public: | |
| 88 PosixMemoryMappedFile(FILE* file, void* memory, int size) | |
| 89 : file_(file), memory_(memory), size_(size) { } | |
| 90 virtual ~PosixMemoryMappedFile(); | |
| 91 virtual void* memory() { return memory_; } | |
| 92 virtual int size() { return size_; } | |
| 93 private: | |
| 94 FILE* file_; | |
| 95 void* memory_; | |
| 96 int size_; | |
| 97 }; | |
| 98 | |
| 99 | |
| 100 OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { | |
| 101 FILE* file = fopen(name, "r+"); | |
| 102 if (file == NULL) return NULL; | |
| 103 | |
| 104 fseek(file, 0, SEEK_END); | |
| 105 int size = ftell(file); | |
| 106 | |
| 107 void* memory = | |
| 108 mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); | |
| 109 return new PosixMemoryMappedFile(file, memory, size); | |
| 110 } | |
| 111 | |
| 112 | |
| 113 OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, | |
| 114 void* initial) { | |
| 115 FILE* file = fopen(name, "w+"); | |
| 116 if (file == NULL) return NULL; | |
| 117 int result = fwrite(initial, size, 1, file); | |
| 118 if (result < 1) { | |
| 119 fclose(file); | |
| 120 return NULL; | |
| 121 } | |
| 122 void* memory = | |
| 123 mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); | |
| 124 return new PosixMemoryMappedFile(file, memory, size); | |
| 125 } | |
| 126 | |
| 127 | |
| 128 PosixMemoryMappedFile::~PosixMemoryMappedFile() { | |
| 129 if (memory_) munmap(memory_, size_); | |
| 130 fclose(file_); | |
| 131 } | |
| 132 | |
| 133 | |
| 134 std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() { | |
| 135 return std::vector<SharedLibraryAddress>(); | |
| 136 } | |
| 137 | |
| 138 | |
| 139 void OS::SignalCodeMovingGC() { | |
| 140 } | |
| 141 | |
| 142 | |
| 143 // Constants used for mmap. | |
| 144 static const int kMmapFd = -1; | |
| 145 static const int kMmapFdOffset = 0; | |
| 146 | |
| 147 | |
| 148 VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } | |
| 149 | |
| 150 | |
| 151 VirtualMemory::VirtualMemory(size_t size) | |
| 152 : address_(ReserveRegion(size)), size_(size) { } | |
| 153 | |
| 154 | |
| 155 VirtualMemory::VirtualMemory(size_t size, size_t alignment) | |
| 156 : address_(NULL), size_(0) { | |
| 157 ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment()))); | |
| 158 size_t request_size = RoundUp(size + alignment, | |
| 159 static_cast<intptr_t>(OS::AllocateAlignment())); | |
| 160 void* reservation = mmap(OS::GetRandomMmapAddr(), | |
| 161 request_size, | |
| 162 PROT_NONE, | |
| 163 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, | |
| 164 kMmapFd, | |
| 165 kMmapFdOffset); | |
| 166 if (reservation == MAP_FAILED) return; | |
| 167 | |
| 168 uint8_t* base = static_cast<uint8_t*>(reservation); | |
| 169 uint8_t* aligned_base = RoundUp(base, alignment); | |
| 170 ASSERT_LE(base, aligned_base); | |
| 171 | |
| 172 // Unmap extra memory reserved before and after the desired block. | |
| 173 if (aligned_base != base) { | |
| 174 size_t prefix_size = static_cast<size_t>(aligned_base - base); | |
| 175 OS::Free(base, prefix_size); | |
| 176 request_size -= prefix_size; | |
| 177 } | |
| 178 | |
| 179 size_t aligned_size = RoundUp(size, OS::AllocateAlignment()); | |
| 180 ASSERT_LE(aligned_size, request_size); | |
| 181 | |
| 182 if (aligned_size != request_size) { | |
| 183 size_t suffix_size = request_size - aligned_size; | |
| 184 OS::Free(aligned_base + aligned_size, suffix_size); | |
| 185 request_size -= suffix_size; | |
| 186 } | |
| 187 | |
| 188 ASSERT(aligned_size == request_size); | |
| 189 | |
| 190 address_ = static_cast<void*>(aligned_base); | |
| 191 size_ = aligned_size; | |
| 192 } | |
| 193 | |
| 194 | |
| 195 VirtualMemory::~VirtualMemory() { | |
| 196 if (IsReserved()) { | |
| 197 bool result = ReleaseRegion(address(), size()); | |
| 198 ASSERT(result); | |
| 199 USE(result); | |
| 200 } | |
| 201 } | |
| 202 | |
| 203 | |
| 204 bool VirtualMemory::IsReserved() { | |
| 205 return address_ != NULL; | |
| 206 } | |
| 207 | |
| 208 | |
| 209 void VirtualMemory::Reset() { | |
| 210 address_ = NULL; | |
| 211 size_ = 0; | |
| 212 } | |
| 213 | |
| 214 | |
| 215 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { | |
| 216 return CommitRegion(address, size, is_executable); | |
| 217 } | |
| 218 | |
| 219 | |
| 220 bool VirtualMemory::Uncommit(void* address, size_t size) { | |
| 221 return UncommitRegion(address, size); | |
| 222 } | |
| 223 | |
| 224 | |
| 225 bool VirtualMemory::Guard(void* address) { | |
| 226 OS::Guard(address, OS::CommitPageSize()); | |
| 227 return true; | |
| 228 } | |
| 229 | |
| 230 | |
| 231 void* VirtualMemory::ReserveRegion(size_t size) { | |
| 232 void* result = mmap(OS::GetRandomMmapAddr(), | |
| 233 size, | |
| 234 PROT_NONE, | |
| 235 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, | |
| 236 kMmapFd, | |
| 237 kMmapFdOffset); | |
| 238 | |
| 239 if (result == MAP_FAILED) return NULL; | |
| 240 | |
| 241 return result; | |
| 242 } | |
| 243 | |
| 244 | |
| 245 bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { | |
| 246 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); | |
| 247 if (MAP_FAILED == mmap(base, | |
| 248 size, | |
| 249 prot, | |
| 250 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, | |
| 251 kMmapFd, | |
| 252 kMmapFdOffset)) { | |
| 253 return false; | |
| 254 } | |
| 255 return true; | |
| 256 } | |
| 257 | |
| 258 | |
| 259 bool VirtualMemory::UncommitRegion(void* base, size_t size) { | |
| 260 return mmap(base, | |
| 261 size, | |
| 262 PROT_NONE, | |
| 263 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED, | |
| 264 kMmapFd, | |
| 265 kMmapFdOffset) != MAP_FAILED; | |
| 266 } | |
| 267 | |
| 268 | |
| 269 bool VirtualMemory::ReleaseRegion(void* base, size_t size) { | |
| 270 return munmap(base, size) == 0; | |
| 271 } | |
| 272 | |
| 273 | |
| 274 bool VirtualMemory::HasLazyCommits() { | |
| 275 // TODO(alph): implement for the platform. | |
| 276 return false; | |
| 277 } | |
| 278 | |
| 279 } } // namespace v8::internal | |
| OLD | NEW |