13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Platform specific code for MacOS goes here. For the POSIX comaptible parts 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the implementation is in platform-posix.cc. 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block#include <dlfcn.h> 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <unistd.h> 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <sys/mman.h> 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <mach/mach_init.h> 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <mach-o/dyld.h> 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <mach-o/getsect.h> 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <AvailabilityMacros.h> 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <pthread.h> 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <semaphore.h> 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <signal.h> 43f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#include <libkern/OSAtomic.h> 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <mach/mach.h> 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <mach/semaphore.h> 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <mach/task.h> 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <mach/vm_statistics.h> 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <sys/time.h> 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <sys/resource.h> 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <sys/types.h> 518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include <sys/sysctl.h> 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdarg.h> 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdlib.h> 548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include <string.h> 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <errno.h> 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef MAP_TYPE 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "platform-posix.h" 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h" 63b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "vm-state-inl.h" 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Manually define these here as weak imports, rather than including execinfo.h. 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This lets us launch on 10.4 which does not have these calls. 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockextern "C" { 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block extern int backtrace(void**, int) __attribute__((weak_import)); 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block extern char** backtrace_symbols(void* const*, int) 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __attribute__((weak_import)); 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block extern void backtrace_symbols_fd(void* const*, int, int) 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __attribute__((weak_import)); 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// 0 is never a valid thread id on MacOSX since a pthread_t is 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a pointer. 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const pthread_t kNoThread = (pthread_t) 0; 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockdouble ceiling(double x) { 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Correct Mac OS X Leopard 'ceil' behavior. 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (-1.0 < x && x < 0.0) { 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -0.0; 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ceil(x); 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic Mutex* limit_mutex = NULL; 9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::SetUp() { 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Seed the random number generator. We preserve microsecond resolution. 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint64_t seed = Ticks() ^ (getpid() << 16); 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block srandom(static_cast<unsigned int>(seed)); 10144f0eee88ff00398ff7f715fab053374d808c90dSteve Block limit_mutex = CreateMutex(); 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::PostSetUp() { 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Math functions depend on CPU features therefore they are initialized after 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // CPU. 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MathSetup(); 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We keep the lowest and highest addresses mapped as a quick way of 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// determining that pointers are outside the heap (used mostly in assertions 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// and verification). The estimate is conservative, i.e., not all addresses in 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 'allocated' space are actually allocated to our heap. The range is 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// [lowest, highest), inclusive on the low and and exclusive on the high end. 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void* highest_ever_allocated = reinterpret_cast<void*>(0); 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void UpdateAllocatedSpaceLimits(void* address, int size) { 12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(limit_mutex != NULL); 12344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ScopedLock lock(limit_mutex); 12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lowest_ever_allocated = Min(lowest_ever_allocated, address); 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block highest_ever_allocated = 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Max(highest_ever_allocated, 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool OS::IsOutsideAllocatedSpace(void* address) { 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return address < lowest_ever_allocated || address >= highest_ever_allocated; 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocksize_t OS::AllocateAlignment() { 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return getpagesize(); 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Constants used for mmap. 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// kMmapFd is used to pass vm_alloc flags to tag the region with the user 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// defined tag 255 This helps identify V8-allocated regions in memory analysis 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// tools like vmmap(1). 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kMmapFd = VM_MAKE_TAG(255); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const off_t kMmapFdOffset = 0; 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* OS::Allocate(const size_t requested, 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block size_t* allocated, 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_executable) { 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const size_t msize = RoundUp(requested, getpagesize()); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void* mbase = mmap(OS::GetRandomMmapAddr(), 1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch msize, 1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch prot, 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MAP_PRIVATE | MAP_ANON, 1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset); 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mbase == MAP_FAILED) { 16244f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(Isolate::Current(), StringEvent("OS::Allocate", "mmap failed")); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *allocated = msize; 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocatedSpaceLimits(mbase, msize); 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mbase; 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Free(void* address, const size_t size) { 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1240712): munmap has a return value which is ignored here. 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = munmap(address, size); 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Sleep(int milliseconds) { 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block usleep(1000 * milliseconds); 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Abort() { 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Redirect to std abort to signal abnormal program termination 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block abort(); 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::DebugBreak() { 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block asm("int $3"); 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass PosixMemoryMappedFile : public OS::MemoryMappedFile { 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PosixMemoryMappedFile(FILE* file, void* memory, int size) 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : file_(file), memory_(memory), size_(size) { } 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~PosixMemoryMappedFile(); 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual void* memory() { return memory_; } 2011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block virtual int size() { return size_; } 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FILE* file_; 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* memory_; 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_; 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2091e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { 210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FILE* file = fopen(name, "r+"); 2111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (file == NULL) return NULL; 2121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block fseek(file, 0, SEEK_END); 2141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int size = ftell(file); 2151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void* memory = 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mmap(OS::GetRandomMmapAddr(), 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size, 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PROT_READ | PROT_WRITE, 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MAP_SHARED, 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fileno(file), 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 0); 2231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return new PosixMemoryMappedFile(file, memory, size); 2241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 2251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* initial) { 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FILE* file = fopen(name, "w+"); 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (file == NULL) return NULL; 2315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int result = fwrite(initial, size, 1, file); 2325913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (result < 1) { 2335913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck fclose(file); 2345913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck return NULL; 2355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* memory = 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mmap(OS::GetRandomMmapAddr(), 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size, 2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PROT_READ | PROT_WRITE, 2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MAP_SHARED, 2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fileno(file), 2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 0); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new PosixMemoryMappedFile(file, memory, size); 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockPosixMemoryMappedFile::~PosixMemoryMappedFile() { 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (memory_) OS::Free(memory_, size_); 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fclose(file_); 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::LogSharedLibraryAddresses() { 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned int images_count = _dyld_image_count(); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (unsigned int i = 0; i < images_count; ++i) { 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const mach_header* header = _dyld_get_image_header(i); 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (header == NULL) continue; 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if V8_HOST_ARCH_X64 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint64_t size; 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* code_ptr = getsectdatafromheader_64( 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<const mach_header_64*>(header), 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SEG_TEXT, 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SECT_TEXT, 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &size); 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned int size; 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* code_ptr = getsectdatafromheader(header, SEG_TEXT, SECT_TEXT, &size); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (code_ptr == NULL) continue; 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const uintptr_t slide = _dyld_get_image_vmaddr_slide(i); 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const uintptr_t start = reinterpret_cast<uintptr_t>(code_ptr) + slide; 27244f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(Isolate::Current(), 27344f0eee88ff00398ff7f715fab053374d808c90dSteve Block SharedLibraryEvent(_dyld_get_image_name(i), start, start + size)); 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 278f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid OS::SignalCodeMovingGC() { 279f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 280f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 281f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockuint64_t OS::CpuFeaturesImpliedByPlatform() { 283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // MacOSX requires all these to install so we can assume they are present. 284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // These constants are defined by the CPUid instructions. 285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const uint64_t one = 1; 286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return (one << SSE2) | (one << CMOV) | (one << RDTSC) | (one << CPUID); 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint OS::ActivationFrameAlignment() { 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // OS X activation frames must be 16 byte-aligned; see "Mac OS X ABI 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Function Call Guide". 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 16; 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) { 298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke OSMemoryBarrier(); 299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *ptr = value; 300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 303d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeconst char* OS::LocalTimezone(double time) { 304d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (isnan(time)) return ""; 305d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke time_t tv = static_cast<time_t>(floor(time/msPerSecond)); 306d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct tm* t = localtime(&tv); 307d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (NULL == t) return ""; 308d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return t->tm_zone; 309d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 310d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 311d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 312d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkedouble OS::LocalTimeOffset() { 313d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke time_t tv = time(NULL); 314d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct tm* t = localtime(&tv); 315d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // tm_gmtoff includes any daylight savings offset, so subtract it. 316d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return static_cast<double>(t->tm_gmtoff * msPerSecond - 317d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke (t->tm_isdst > 0 ? 3600 * msPerSecond : 0)); 318d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 319d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 320d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint OS::StackWalk(Vector<StackFrame> frames) { 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If weak link to execinfo lib has failed, ie because we are on 10.4, abort. 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (backtrace == NULL) 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 0; 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int frames_size = frames.length(); 32725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen ScopedVector<void*> addresses(frames_size); 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 32925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen int frames_count = backtrace(addresses.start(), frames_size); 33025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 33125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen char** symbols = backtrace_symbols(addresses.start(), frames_count); 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (symbols == NULL) { 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return kStackWalkError; 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < frames_count; i++) { 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frames[i].address = addresses[i]; 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Format a text representation of the frame based on the information 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // available. 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SNPrintF(MutableCStrVector(frames[i].text, 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block kStackWalkMaxTextLen), 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%s", 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block symbols[i]); 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure line termination is in place. 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frames[i].text[kStackWalkMaxTextLen - 1] = '\0'; 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block free(symbols); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return frames_count; 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVirtualMemory::VirtualMemory(size_t size) 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : address_(ReserveRegion(size)), size_(size) { } 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVirtualMemory::VirtualMemory(size_t size, size_t alignment) 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : address_(NULL), size_(0) { 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment()))); 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t request_size = RoundUp(size + alignment, 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<intptr_t>(OS::AllocateAlignment())); 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void* reservation = mmap(OS::GetRandomMmapAddr(), 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch request_size, 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PROT_NONE, 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset); 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (reservation == MAP_FAILED) return; 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address base = static_cast<Address>(reservation); 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address aligned_base = RoundUp(base, alignment); 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_LE(base, aligned_base); 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Unmap extra memory reserved before and after the desired block. 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (aligned_base != base) { 3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t prefix_size = static_cast<size_t>(aligned_base - base); 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::Free(base, prefix_size); 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch request_size -= prefix_size; 3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t aligned_size = RoundUp(size, OS::AllocateAlignment()); 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_LE(aligned_size, request_size); 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (aligned_size != request_size) { 3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t suffix_size = request_size - aligned_size; 3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::Free(aligned_base + aligned_size, suffix_size); 3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch request_size -= suffix_size; 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(aligned_size == request_size); 3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_ = static_cast<void*>(aligned_base); 3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_ = aligned_size; 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVirtualMemory::~VirtualMemory() { 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (IsReserved()) { 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool result = ReleaseRegion(address(), size()); 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(result); 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch USE(result); 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid VirtualMemory::Reset() { 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_ = NULL; 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_ = 0; 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid* VirtualMemory::ReserveRegion(size_t size) { 4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void* result = mmap(OS::GetRandomMmapAddr(), 4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size, 4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PROT_NONE, 4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, 4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset); 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (result == MAP_FAILED) return NULL; 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return result; 4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool VirtualMemory::IsReserved() { 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return address_ != NULL; 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return CommitRegion(address, size, is_executable); 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Guard(void* address) { 4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::Guard(address, OS::CommitPageSize()); 4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::CommitRegion(void* address, 4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t size, 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_executable) { 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (MAP_FAILED == mmap(address, 4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size, 4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch prot, 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MAP_PRIVATE | MAP_ANON | MAP_FIXED, 4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset)) { 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocatedSpaceLimits(address, size); 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool VirtualMemory::Uncommit(void* address, size_t size) { 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return UncommitRegion(address, size); 4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::UncommitRegion(void* address, size_t size) { 4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return mmap(address, 4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size, 4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PROT_NONE, 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED, 4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset) != MAP_FAILED; 4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::ReleaseRegion(void* address, size_t size) { 4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return munmap(address, size) == 0; 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass Thread::PlatformData : public Malloced { 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 4868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PlatformData() : thread_(kNoThread) {} 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_t thread_; // Thread handle for pthread. 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 49085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochThread::Thread(const Options& options) 49285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch : data_(new PlatformData), 4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stack_size_(options.stack_size()) { 4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_name(options.name()); 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockThread::~Thread() { 4998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch delete data_; 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockstatic void SetThreadName(const char* name) { 5049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // pthread_setname_np is only available in 10.6 or later, so test 5059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // for it at runtime. 5069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int (*dynamic_pthread_setname_np)(const char*); 5079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block *reinterpret_cast<void**>(&dynamic_pthread_setname_np) = 5089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block dlsym(RTLD_DEFAULT, "pthread_setname_np"); 5099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (!dynamic_pthread_setname_np) 5109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return; 5119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 5129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Mac OS X does not expose the length limit of the name, so hardcode it. 5139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block static const int kMaxNameLength = 63; 5149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block USE(kMaxNameLength); 5159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(Thread::kMaxThreadNameLength <= kMaxNameLength); 5169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block dynamic_pthread_setname_np(name); 5179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 5189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 5199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void* ThreadEntry(void* arg) { 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Thread* thread = reinterpret_cast<Thread*>(arg); 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This is also initialized by the first argument to pthread_create() but we 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // don't know which thread will run first (the original thread or the new 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // one) so we initialize it here too. 5258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch thread->data()->thread_ = pthread_self(); 5269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block SetThreadName(thread->name()); 5278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(thread->data()->thread_ != kNoThread); 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block thread->Run(); 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid Thread::set_name(const char* name) { 5349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block strncpy(name_, name, sizeof(name_)); 5359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name_[sizeof(name_) - 1] = '\0'; 5369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 5379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 5389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::Start() { 54044f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_t* attr_ptr = NULL; 54144f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_t attr; 54244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (stack_size_ > 0) { 54344f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_init(&attr); 54444f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_)); 54544f0eee88ff00398ff7f715fab053374d808c90dSteve Block attr_ptr = &attr; 54644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 5478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); 5488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(data_->thread_ != kNoThread); 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::Join() { 5538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch pthread_join(data_->thread_, NULL); 5548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 5558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef V8_FAST_TLS_SUPPORTED 5588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic Atomic32 tls_base_offset_initialized = 0; 5608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochintptr_t kMacTlsBaseOffset = 0; 5618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// It's safe to do the initialization more that once, but it has to be 5638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// done at least once. 5648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic void InitializeTlsBaseOffset() { 5658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch const size_t kBufferSize = 128; 5668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch char buffer[kBufferSize]; 5678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch size_t buffer_size = kBufferSize; 5688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int ctl_name[] = { CTL_KERN , KERN_OSRELEASE }; 5698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (sysctl(ctl_name, 2, buffer, &buffer_size, NULL, 0) != 0) { 5708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch V8_Fatal(__FILE__, __LINE__, "V8 failed to get kernel version"); 5718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 5728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // The buffer now contains a string of the form XX.YY.ZZ, where 5738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // XX is the major kernel version component. 5748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Make sure the buffer is 0-terminated. 5758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch buffer[kBufferSize - 1] = '\0'; 5768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch char* period_pos = strchr(buffer, '.'); 5778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch *period_pos = '\0'; 5788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int kernel_version_major = 5798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static_cast<int>(strtol(buffer, NULL, 10)); // NOLINT 5808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // The constants below are taken from pthreads.s from the XNU kernel 5818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // sources archive at www.opensource.apple.com. 5828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (kernel_version_major < 11) { 5838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // 8.x.x (Tiger), 9.x.x (Leopard), 10.x.x (Snow Leopard) have the 5848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // same offsets. 5858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#if defined(V8_HOST_ARCH_IA32) 5868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch kMacTlsBaseOffset = 0x48; 5878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#else 5888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch kMacTlsBaseOffset = 0x60; 5898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif 5908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 5918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // 11.x.x (Lion) changed the offset. 5928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch kMacTlsBaseOffset = 0; 5938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 5948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Release_Store(&tls_base_offset_initialized, 1); 5968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 5978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic void CheckFastTls(Thread::LocalStorageKey key) { 5998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void* expected = reinterpret_cast<void*>(0x1234CAFE); 6008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Thread::SetThreadLocal(key, expected); 6018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void* actual = Thread::GetExistingThreadLocal(key); 6028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (expected != actual) { 6038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch V8_Fatal(__FILE__, __LINE__, 6048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch "V8 failed to initialize fast TLS on current kernel"); 6058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Thread::SetThreadLocal(key, NULL); 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif // V8_FAST_TLS_SUPPORTED 6108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockThread::LocalStorageKey Thread::CreateThreadLocalKey() { 6138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef V8_FAST_TLS_SUPPORTED 6148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool check_fast_tls = false; 6158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (tls_base_offset_initialized == 0) { 6168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch check_fast_tls = true; 6178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch InitializeTlsBaseOffset(); 6188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t key; 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_key_create(&key, NULL); 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 6248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch LocalStorageKey typed_key = static_cast<LocalStorageKey>(key); 6258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef V8_FAST_TLS_SUPPORTED 6268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // If we just initialized fast TLS support, make sure it works. 6278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (check_fast_tls) CheckFastTls(typed_key); 6288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif 6298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return typed_key; 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::DeleteThreadLocalKey(LocalStorageKey key) { 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_key_delete(pthread_key); 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* Thread::GetThreadLocal(LocalStorageKey key) { 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return pthread_getspecific(pthread_key); 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::SetThreadLocal(LocalStorageKey key, void* value) { 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_setspecific(pthread_key, value); 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::YieldCPU() { 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sched_yield(); 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass MacOSMutex : public Mutex { 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MacOSMutex() { 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_mutexattr_t attr; 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_mutexattr_init(&attr); 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_mutex_init(&mutex_, &attr); 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual ~MacOSMutex() { pthread_mutex_destroy(&mutex_); } 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual int Lock() { return pthread_mutex_lock(&mutex_); } 670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual int Unlock() { return pthread_mutex_unlock(&mutex_); } 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual bool TryLock() { 673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int result = pthread_mutex_trylock(&mutex_); 674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Return false if the lock is busy and locking failed. 675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (result == EBUSY) { 676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(result == 0); // Verify no other errors. 679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_mutex_t mutex_; 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMutex* OS::CreateMutex() { 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new MacOSMutex(); 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass MacOSSemaphore : public Semaphore { 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit MacOSSemaphore(int count) { 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block semaphore_create(mach_task_self(), &semaphore_, SYNC_POLICY_FIFO, count); 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~MacOSSemaphore() { 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block semaphore_destroy(mach_task_self(), semaphore_); 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The MacOS mach semaphore documentation claims it does not have spurious 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // wakeups, the way pthreads semaphores do. So the code from the linux 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // platform is not needed here. 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Wait() { semaphore_wait(semaphore_); } 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool Wait(int timeout); 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Signal() { semaphore_signal(semaphore_); } 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block semaphore_t semaphore_; 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool MacOSSemaphore::Wait(int timeout) { 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mach_timespec_t ts; 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ts.tv_sec = timeout / 1000000; 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ts.tv_nsec = (timeout % 1000000) * 1000; 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return semaphore_timedwait(semaphore_, ts) != KERN_OPERATION_TIMED_OUT; 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSemaphore* OS::CreateSemaphore(int count) { 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new MacOSSemaphore(count); 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Sampler::PlatformData : public Malloced { 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 73144f0eee88ff00398ff7f715fab053374d808c90dSteve Block PlatformData() : profiled_thread_(mach_thread_self()) {} 73244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 73344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ~PlatformData() { 73444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Deallocate Mach port for thread. 73544f0eee88ff00398ff7f715fab053374d808c90dSteve Block mach_port_deallocate(mach_task_self(), profiled_thread_); 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 73844f0eee88ff00398ff7f715fab053374d808c90dSteve Block thread_act_t profiled_thread() { return profiled_thread_; } 73944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 74044f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Note: for profiled_thread_ Mach primitives are used instead of PThread's 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // because the latter doesn't provide thread manipulation primitives required. 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For details, consult "Mac OS X Internals" book, Section 7.3. 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block thread_act_t profiled_thread_; 74544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 74644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass SamplerThread : public Thread { 74944f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kSamplerThreadStackSize = 64 * KB; 7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75244f0eee88ff00398ff7f715fab053374d808c90dSteve Block explicit SamplerThread(int interval) 7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)), 75444f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval_(interval) {} 75544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 75644f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void AddActiveSampler(Sampler* sampler) { 7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScopedLock lock(mutex_.Pointer()); 75844f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::AddActiveSampler(sampler); 75944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instance_ == NULL) { 76044f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_ = new SamplerThread(sampler->interval()); 76144f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_->Start(); 76244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(instance_->interval_ == sampler->interval()); 76444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 76744f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void RemoveActiveSampler(Sampler* sampler) { 7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScopedLock lock(mutex_.Pointer()); 76944f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::RemoveActiveSampler(sampler); 77044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { 7713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); 77244f0eee88ff00398ff7f715fab053374d808c90dSteve Block delete instance_; 77344f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_ = NULL; 77444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 77544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 77744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Implement Thread::Run(). 77844f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual void Run() { 77944f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::State state; 78044f0eee88ff00398ff7f715fab053374d808c90dSteve Block while ((state = SamplerRegistry::GetState()) != 78144f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::HAS_NO_SAMPLERS) { 78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool cpu_profiling_enabled = 78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS); 78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled(); 78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // When CPU profiling is enabled both JavaScript and C++ code is 78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // profiled. We must not suspend. 78744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!cpu_profiling_enabled) { 78844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (rate_limiter_.SuspendIfNecessary()) continue; 78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 79044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (cpu_profiling_enabled) { 79144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) { 79244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 79344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (runtime_profiler_enabled) { 79644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) { 79744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 79844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block OS::Sleep(interval_); 801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void DoCpuProfile(Sampler* sampler, void* raw_sampler_thread) { 80544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!sampler->isolate()->IsInitialized()) return; 80644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!sampler->IsProfiling()) return; 80744f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerThread* sampler_thread = 80844f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<SamplerThread*>(raw_sampler_thread); 80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler_thread->SampleContext(sampler); 81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void DoRuntimeProfile(Sampler* sampler, void* ignored) { 81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!sampler->isolate()->IsInitialized()) return; 81444f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->isolate()->runtime_profiler()->NotifyTick(); 81544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 81644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 81744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void SampleContext(Sampler* sampler) { 81844f0eee88ff00398ff7f715fab053374d808c90dSteve Block thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); 81944f0eee88ff00398ff7f715fab053374d808c90dSteve Block TickSample sample_obj; 82044f0eee88ff00398ff7f715fab053374d808c90dSteve Block TickSample* sample = CpuProfiler::TickSampleEvent(sampler->isolate()); 82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (sample == NULL) sample = &sample_obj; 82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 82344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (KERN_SUCCESS != thread_suspend(profiled_thread)) return; 824f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if V8_HOST_ARCH_X64 82644f0eee88ff00398ff7f715fab053374d808c90dSteve Block thread_state_flavor_t flavor = x86_THREAD_STATE64; 82744f0eee88ff00398ff7f715fab053374d808c90dSteve Block x86_thread_state64_t state; 82844f0eee88ff00398ff7f715fab053374d808c90dSteve Block mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if __DARWIN_UNIX03 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define REGISTER_FIELD(name) __r ## name 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define REGISTER_FIELD(name) r ## name 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // __DARWIN_UNIX03 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#elif V8_HOST_ARCH_IA32 83544f0eee88ff00398ff7f715fab053374d808c90dSteve Block thread_state_flavor_t flavor = i386_THREAD_STATE; 83644f0eee88ff00398ff7f715fab053374d808c90dSteve Block i386_thread_state_t state; 83744f0eee88ff00398ff7f715fab053374d808c90dSteve Block mach_msg_type_number_t count = i386_THREAD_STATE_COUNT; 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if __DARWIN_UNIX03 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define REGISTER_FIELD(name) __e ## name 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define REGISTER_FIELD(name) e ## name 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // __DARWIN_UNIX03 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#error Unsupported Mac OS X host architecture. 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_HOST_ARCH 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 84744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (thread_get_state(profiled_thread, 84844f0eee88ff00398ff7f715fab053374d808c90dSteve Block flavor, 84944f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<natural_t*>(&state), 85044f0eee88ff00398ff7f715fab053374d808c90dSteve Block &count) == KERN_SUCCESS) { 85144f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->state = sampler->isolate()->current_vm_state(); 85244f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip)); 85344f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp)); 85444f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp)); 85544f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->SampleStack(sample); 85644f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->Tick(sample); 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 85844f0eee88ff00398ff7f715fab053374d808c90dSteve Block thread_resume(profiled_thread); 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 86044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 86144f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int interval_; 86244f0eee88ff00398ff7f715fab053374d808c90dSteve Block RuntimeProfilerRateLimiter rate_limiter_; 86344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 86444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Protects the process wide state below. 8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static LazyMutex mutex_; 86644f0eee88ff00398ff7f715fab053374d808c90dSteve Block static SamplerThread* instance_; 86744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 86944f0eee88ff00398ff7f715fab053374d808c90dSteve Block DISALLOW_COPY_AND_ASSIGN(SamplerThread); 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef REGISTER_FIELD 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochLazyMutex SamplerThread::mutex_ = LAZY_MUTEX_INITIALIZER; 87644f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSamplerThread* SamplerThread::instance_ = NULL; 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 87944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSampler::Sampler(Isolate* isolate, int interval) 88044f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_(isolate), 88144f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval_(interval), 882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch profiling_(false), 8838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang active_(false), 8848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang samples_taken_(0) { 88544f0eee88ff00398ff7f715fab053374d808c90dSteve Block data_ = new PlatformData; 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSampler::~Sampler() { 89044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!IsActive()); 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete data_; 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Sampler::Start() { 896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsActive()); 897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetActive(true); 89844f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerThread::AddActiveSampler(this); 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Sampler::Stop() { 90344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(IsActive()); 90444f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerThread::RemoveActiveSampler(this); 905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetActive(false); 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 910