The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / platform-solaris.cc @ f230a1cf

History | View | Annotate | Download (9.68 KB)

1
// Copyright 2012 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
// Platform specific code for Solaris 10 goes here. For the POSIX comaptible
29
// parts the implementation is in platform-posix.cc.
30

    
31
#ifdef __sparc
32
# error "V8 does not support the SPARC CPU architecture."
33
#endif
34

    
35
#include <sys/stack.h>  // for stack alignment
36
#include <unistd.h>  // getpagesize(), usleep()
37
#include <sys/mman.h>  // mmap()
38
#include <ucontext.h>  // walkstack(), getcontext()
39
#include <dlfcn.h>     // dladdr
40
#include <pthread.h>
41
#include <semaphore.h>
42
#include <time.h>
43
#include <sys/time.h>  // gettimeofday(), timeradd()
44
#include <errno.h>
45
#include <ieeefp.h>  // finite()
46
#include <signal.h>  // sigemptyset(), etc
47
#include <sys/regset.h>
48

    
49

    
50
#undef MAP_TYPE
51

    
52
#include "v8.h"
53

    
54
#include "platform.h"
55
#include "v8threads.h"
56
#include "vm-state-inl.h"
57

    
58

    
59
// It seems there is a bug in some Solaris distributions (experienced in
60
// SunOS 5.10 Generic_141445-09) which make it difficult or impossible to
61
// access signbit() despite the availability of other C99 math functions.
62
#ifndef signbit
63
namespace std {
64
// Test sign - usually defined in math.h
65
int signbit(double x) {
66
  // We need to take care of the special case of both positive and negative
67
  // versions of zero.
68
  if (x == 0) {
69
    return fpclass(x) & FP_NZERO;
70
  } else {
71
    // This won't detect negative NaN but that should be okay since we don't
72
    // assume that behavior.
73
    return x < 0;
74
  }
75
}
76
}  // namespace std
77
#endif  // signbit
78

    
79
namespace v8 {
80
namespace internal {
81

    
82

    
83
const char* OS::LocalTimezone(double time) {
84
  if (std::isnan(time)) return "";
85
  time_t tv = static_cast<time_t>(floor(time/msPerSecond));
86
  struct tm* t = localtime(&tv);
87
  if (NULL == t) return "";
88
  return tzname[0];  // The location of the timezone string on Solaris.
89
}
90

    
91

    
92
double OS::LocalTimeOffset() {
93
  tzset();
94
  return -static_cast<double>(timezone * msPerSecond);
95
}
96

    
97

    
98
void* OS::Allocate(const size_t requested,
99
                   size_t* allocated,
100
                   bool is_executable) {
101
  const size_t msize = RoundUp(requested, getpagesize());
102
  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
103
  void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
104

    
105
  if (mbase == MAP_FAILED) {
106
    LOG(Isolate::Current(), StringEvent("OS::Allocate", "mmap failed"));
107
    return NULL;
108
  }
109
  *allocated = msize;
110
  return mbase;
111
}
112

    
113

    
114
class PosixMemoryMappedFile : public OS::MemoryMappedFile {
115
 public:
116
  PosixMemoryMappedFile(FILE* file, void* memory, int size)
117
    : file_(file), memory_(memory), size_(size) { }
118
  virtual ~PosixMemoryMappedFile();
119
  virtual void* memory() { return memory_; }
120
  virtual int size() { return size_; }
121
 private:
122
  FILE* file_;
123
  void* memory_;
124
  int size_;
125
};
126

    
127

    
128
OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
129
  FILE* file = fopen(name, "r+");
130
  if (file == NULL) return NULL;
131

    
132
  fseek(file, 0, SEEK_END);
133
  int size = ftell(file);
134

    
135
  void* memory =
136
      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
137
  return new PosixMemoryMappedFile(file, memory, size);
138
}
139

    
140

    
141
OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
142
    void* initial) {
143
  FILE* file = fopen(name, "w+");
144
  if (file == NULL) return NULL;
145
  int result = fwrite(initial, size, 1, file);
146
  if (result < 1) {
147
    fclose(file);
148
    return NULL;
149
  }
150
  void* memory =
151
      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
152
  return new PosixMemoryMappedFile(file, memory, size);
153
}
154

    
155

    
156
PosixMemoryMappedFile::~PosixMemoryMappedFile() {
157
  if (memory_) munmap(memory_, size_);
158
  fclose(file_);
159
}
160

    
161

    
162
void OS::LogSharedLibraryAddresses(Isolate* isolate) {
163
}
164

    
165

    
166
void OS::SignalCodeMovingGC() {
167
}
168

    
169

    
170
struct StackWalker {
171
  Vector<OS::StackFrame>& frames;
172
  int index;
173
};
174

    
175

    
176
static int StackWalkCallback(uintptr_t pc, int signo, void* data) {
177
  struct StackWalker* walker = static_cast<struct StackWalker*>(data);
178
  Dl_info info;
179

    
180
  int i = walker->index;
181

    
182
  walker->frames[i].address = reinterpret_cast<void*>(pc);
183

    
184
  // Make sure line termination is in place.
185
  walker->frames[i].text[OS::kStackWalkMaxTextLen - 1] = '\0';
186

    
187
  Vector<char> text = MutableCStrVector(walker->frames[i].text,
188
                                        OS::kStackWalkMaxTextLen);
189

    
190
  if (dladdr(reinterpret_cast<void*>(pc), &info) == 0) {
191
    OS::SNPrintF(text, "[0x%p]", pc);
192
  } else if ((info.dli_fname != NULL && info.dli_sname != NULL)) {
193
    // We have symbol info.
194
    OS::SNPrintF(text, "%s'%s+0x%x", info.dli_fname, info.dli_sname, pc);
195
  } else {
196
    // No local symbol info.
197
    OS::SNPrintF(text,
198
                 "%s'0x%p [0x%p]",
199
                 info.dli_fname,
200
                 pc - reinterpret_cast<uintptr_t>(info.dli_fbase),
201
                 pc);
202
  }
203
  walker->index++;
204
  return 0;
205
}
206

    
207

    
208
// Constants used for mmap.
209
static const int kMmapFd = -1;
210
static const int kMmapFdOffset = 0;
211

    
212

    
213
VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
214

    
215

    
216
VirtualMemory::VirtualMemory(size_t size)
217
    : address_(ReserveRegion(size)), size_(size) { }
218

    
219

    
220
VirtualMemory::VirtualMemory(size_t size, size_t alignment)
221
    : address_(NULL), size_(0) {
222
  ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment())));
223
  size_t request_size = RoundUp(size + alignment,
224
                                static_cast<intptr_t>(OS::AllocateAlignment()));
225
  void* reservation = mmap(OS::GetRandomMmapAddr(),
226
                           request_size,
227
                           PROT_NONE,
228
                           MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
229
                           kMmapFd,
230
                           kMmapFdOffset);
231
  if (reservation == MAP_FAILED) return;
232

    
233
  Address base = static_cast<Address>(reservation);
234
  Address aligned_base = RoundUp(base, alignment);
235
  ASSERT_LE(base, aligned_base);
236

    
237
  // Unmap extra memory reserved before and after the desired block.
238
  if (aligned_base != base) {
239
    size_t prefix_size = static_cast<size_t>(aligned_base - base);
240
    OS::Free(base, prefix_size);
241
    request_size -= prefix_size;
242
  }
243

    
244
  size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
245
  ASSERT_LE(aligned_size, request_size);
246

    
247
  if (aligned_size != request_size) {
248
    size_t suffix_size = request_size - aligned_size;
249
    OS::Free(aligned_base + aligned_size, suffix_size);
250
    request_size -= suffix_size;
251
  }
252

    
253
  ASSERT(aligned_size == request_size);
254

    
255
  address_ = static_cast<void*>(aligned_base);
256
  size_ = aligned_size;
257
}
258

    
259

    
260
VirtualMemory::~VirtualMemory() {
261
  if (IsReserved()) {
262
    bool result = ReleaseRegion(address(), size());
263
    ASSERT(result);
264
    USE(result);
265
  }
266
}
267

    
268

    
269
bool VirtualMemory::IsReserved() {
270
  return address_ != NULL;
271
}
272

    
273

    
274
void VirtualMemory::Reset() {
275
  address_ = NULL;
276
  size_ = 0;
277
}
278

    
279

    
280
bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
281
  return CommitRegion(address, size, is_executable);
282
}
283

    
284

    
285
bool VirtualMemory::Uncommit(void* address, size_t size) {
286
  return UncommitRegion(address, size);
287
}
288

    
289

    
290
bool VirtualMemory::Guard(void* address) {
291
  OS::Guard(address, OS::CommitPageSize());
292
  return true;
293
}
294

    
295

    
296
void* VirtualMemory::ReserveRegion(size_t size) {
297
  void* result = mmap(OS::GetRandomMmapAddr(),
298
                      size,
299
                      PROT_NONE,
300
                      MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
301
                      kMmapFd,
302
                      kMmapFdOffset);
303

    
304
  if (result == MAP_FAILED) return NULL;
305

    
306
  return result;
307
}
308

    
309

    
310
bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
311
  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
312
  if (MAP_FAILED == mmap(base,
313
                         size,
314
                         prot,
315
                         MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
316
                         kMmapFd,
317
                         kMmapFdOffset)) {
318
    return false;
319
  }
320
  return true;
321
}
322

    
323

    
324
bool VirtualMemory::UncommitRegion(void* base, size_t size) {
325
  return mmap(base,
326
              size,
327
              PROT_NONE,
328
              MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED,
329
              kMmapFd,
330
              kMmapFdOffset) != MAP_FAILED;
331
}
332

    
333

    
334
bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
335
  return munmap(base, size) == 0;
336
}
337

    
338

    
339
bool VirtualMemory::HasLazyCommits() {
340
  // TODO(alph): implement for the platform.
341
  return false;
342
}
343

    
344
} }  // namespace v8::internal