OLD | NEW |
1 // Copyright 2006-2010 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 28 matching lines...) Expand all Loading... |
39 #include "scanner.h" | 39 #include "scanner.h" |
40 #include "scopeinfo.h" | 40 #include "scopeinfo.h" |
41 #include "simulator.h" | 41 #include "simulator.h" |
42 #include "stub-cache.h" | 42 #include "stub-cache.h" |
43 #include "oprofile-agent.h" | 43 #include "oprofile-agent.h" |
44 | 44 |
45 namespace v8 { | 45 namespace v8 { |
46 namespace internal { | 46 namespace internal { |
47 | 47 |
48 | 48 |
| 49 // Create a dummy thread that will wait forever on a semaphore. The only |
| 50 // purpose for this thread is to have some stack area to save essential data |
| 51 // into for use by a stacks only core dump (aka minidump). |
| 52 class PreallocatedMemoryThread: public Thread { |
| 53 public: |
| 54 char* data() { |
| 55 if (data_ready_semaphore_ != NULL) { |
| 56 // Initial access is guarded until the data has been published. |
| 57 data_ready_semaphore_->Wait(); |
| 58 delete data_ready_semaphore_; |
| 59 data_ready_semaphore_ = NULL; |
| 60 } |
| 61 return data_; |
| 62 } |
| 63 |
| 64 unsigned length() { |
| 65 if (data_ready_semaphore_ != NULL) { |
| 66 // Initial access is guarded until the data has been published. |
| 67 data_ready_semaphore_->Wait(); |
| 68 delete data_ready_semaphore_; |
| 69 data_ready_semaphore_ = NULL; |
| 70 } |
| 71 return length_; |
| 72 } |
| 73 |
| 74 // Stop the PreallocatedMemoryThread and release its resources. |
| 75 void StopThread() { |
| 76 keep_running_ = false; |
| 77 wait_for_ever_semaphore_->Signal(); |
| 78 |
| 79 // Wait for the thread to terminate. |
| 80 Join(); |
| 81 |
| 82 if (data_ready_semaphore_ != NULL) { |
| 83 delete data_ready_semaphore_; |
| 84 data_ready_semaphore_ = NULL; |
| 85 } |
| 86 |
| 87 delete wait_for_ever_semaphore_; |
| 88 wait_for_ever_semaphore_ = NULL; |
| 89 } |
| 90 |
| 91 protected: |
| 92 // When the thread starts running it will allocate a fixed number of bytes |
| 93 // on the stack and publish the location of this memory for others to use. |
| 94 void Run() { |
| 95 EmbeddedVector<char, 15 * 1024> local_buffer; |
| 96 |
| 97 // Initialize the buffer with a known good value. |
| 98 OS::StrNCpy(local_buffer, "Trace data was not generated.\n", |
| 99 local_buffer.length()); |
| 100 |
| 101 // Publish the local buffer and signal its availability. |
| 102 data_ = local_buffer.start(); |
| 103 length_ = local_buffer.length(); |
| 104 data_ready_semaphore_->Signal(); |
| 105 |
| 106 while (keep_running_) { |
| 107 // This thread will wait here until the end of time. |
| 108 wait_for_ever_semaphore_->Wait(); |
| 109 } |
| 110 |
| 111 // Make sure we access the buffer after the wait to remove all possibility |
| 112 // of it being optimized away. |
| 113 OS::StrNCpy(local_buffer, "PreallocatedMemoryThread shutting down.\n", |
| 114 local_buffer.length()); |
| 115 } |
| 116 |
| 117 |
| 118 private: |
| 119 PreallocatedMemoryThread() |
| 120 : keep_running_(true), |
| 121 wait_for_ever_semaphore_(OS::CreateSemaphore(0)), |
| 122 data_ready_semaphore_(OS::CreateSemaphore(0)), |
| 123 data_(NULL), |
| 124 length_(0) { |
| 125 } |
| 126 |
| 127 // Used to make sure that the thread keeps looping even for spurious wakeups. |
| 128 bool keep_running_; |
| 129 |
| 130 // This semaphore is used by the PreallocatedMemoryThread to wait for ever. |
| 131 Semaphore* wait_for_ever_semaphore_; |
| 132 // Semaphore to signal that the data has been initialized. |
| 133 Semaphore* data_ready_semaphore_; |
| 134 |
| 135 // Location and size of the preallocated memory block. |
| 136 char* data_; |
| 137 unsigned length_; |
| 138 |
| 139 friend class Isolate; |
| 140 |
| 141 DISALLOW_COPY_AND_ASSIGN(PreallocatedMemoryThread); |
| 142 }; |
| 143 |
| 144 |
| 145 void Isolate::PreallocatedMemoryThreadStart() { |
| 146 if (preallocated_memory_thread_ != NULL) return; |
| 147 preallocated_memory_thread_ = new PreallocatedMemoryThread(); |
| 148 preallocated_memory_thread_->Start(); |
| 149 } |
| 150 |
| 151 |
| 152 void Isolate::PreallocatedMemoryThreadStop() { |
| 153 if (preallocated_memory_thread_ == NULL) return; |
| 154 preallocated_memory_thread_->StopThread(); |
| 155 // Done with the thread entirely. |
| 156 delete preallocated_memory_thread_; |
| 157 preallocated_memory_thread_ = NULL; |
| 158 } |
| 159 |
49 #ifdef V8_USE_TLS_FOR_GLOBAL_ISOLATE | 160 #ifdef V8_USE_TLS_FOR_GLOBAL_ISOLATE |
50 Thread::LocalStorageKey Isolate::global_isolate_key_; | 161 Thread::LocalStorageKey Isolate::global_isolate_key_; |
51 | 162 |
52 | 163 |
53 Isolate* Isolate::InitThreadForGlobalIsolate() { | 164 Isolate* Isolate::InitThreadForGlobalIsolate() { |
54 ASSERT(global_isolate_ != NULL); | 165 ASSERT(global_isolate_ != NULL); |
55 Thread::SetThreadLocal(global_isolate_key_, global_isolate_); | 166 Thread::SetThreadLocal(global_isolate_key_, global_isolate_); |
56 return global_isolate_; | 167 return global_isolate_; |
57 } | 168 } |
58 #endif | 169 #endif |
59 | 170 |
| 171 |
60 Isolate* Isolate::global_isolate_ = NULL; | 172 Isolate* Isolate::global_isolate_ = NULL; |
61 int Isolate::number_of_isolates_ = 0; | 173 int Isolate::number_of_isolates_ = 0; |
62 | 174 |
63 | 175 |
64 class IsolateInitializer { | 176 class IsolateInitializer { |
65 public: | 177 public: |
66 IsolateInitializer() { | 178 IsolateInitializer() { |
67 Isolate::InitOnce(); | 179 Isolate::InitOnce(); |
68 } | 180 } |
69 }; | 181 }; |
70 | 182 |
71 | |
72 static IsolateInitializer isolate_initializer; | 183 static IsolateInitializer isolate_initializer; |
73 | 184 |
74 | 185 |
75 void Isolate::InitOnce() { | 186 void Isolate::InitOnce() { |
76 ASSERT(global_isolate_ == NULL); | 187 ASSERT(global_isolate_ == NULL); |
77 #ifdef V8_USE_TLS_FOR_GLOBAL_ISOLATE | 188 #ifdef V8_USE_TLS_FOR_GLOBAL_ISOLATE |
78 global_isolate_key_ = Thread::CreateThreadLocalKey(); | 189 global_isolate_key_ = Thread::CreateThreadLocalKey(); |
79 #endif | 190 #endif |
80 global_isolate_ = new Isolate(); | 191 global_isolate_ = new Isolate(); |
81 CHECK(global_isolate_->PreInit()); | 192 CHECK(global_isolate_->PreInit()); |
(...skipping 20 matching lines...) Expand all Loading... |
102 #ifdef V8_USE_TLS_FOR_GLOBAL_ISOLATE | 213 #ifdef V8_USE_TLS_FOR_GLOBAL_ISOLATE |
103 Thread::SetThreadLocal(global_isolate_key_, NULL); | 214 Thread::SetThreadLocal(global_isolate_key_, NULL); |
104 #endif | 215 #endif |
105 return NULL; | 216 return NULL; |
106 } | 217 } |
107 } | 218 } |
108 | 219 |
109 | 220 |
110 Isolate::Isolate() | 221 Isolate::Isolate() |
111 : state_(UNINITIALIZED), | 222 : state_(UNINITIALIZED), |
| 223 stack_trace_nesting_level_(0), |
| 224 incomplete_message_(NULL), |
| 225 preallocated_memory_thread_(NULL), |
| 226 preallocated_message_space_(NULL), |
112 bootstrapper_(NULL), | 227 bootstrapper_(NULL), |
113 compilation_cache_(new CompilationCache()), | 228 compilation_cache_(new CompilationCache()), |
114 cpu_features_(NULL), | 229 cpu_features_(NULL), |
115 break_access_(OS::CreateMutex()), | 230 break_access_(OS::CreateMutex()), |
116 stub_cache_(NULL), | 231 stub_cache_(NULL), |
117 transcendental_cache_(new TranscendentalCache()), | 232 transcendental_cache_(new TranscendentalCache()), |
118 keyed_lookup_cache_(new KeyedLookupCache()), | 233 keyed_lookup_cache_(new KeyedLookupCache()), |
119 context_slot_cache_(new ContextSlotCache()), | 234 context_slot_cache_(new ContextSlotCache()), |
120 descriptor_lookup_cache_(new DescriptorLookupCache()), | 235 descriptor_lookup_cache_(new DescriptorLookupCache()), |
121 handle_scope_implementer_(NULL), | 236 handle_scope_implementer_(NULL), |
122 scanner_character_classes_(new ScannerCharacterClasses()) { | 237 scanner_character_classes_(new ScannerCharacterClasses()) { |
| 238 memset(isolate_addresses_, 0, |
| 239 sizeof(isolate_addresses_[0]) * (k_isolate_address_count + 1)); |
| 240 |
123 heap_.isolate_ = this; | 241 heap_.isolate_ = this; |
124 stack_guard_.isolate_ = this; | 242 stack_guard_.isolate_ = this; |
125 | 243 |
126 handle_scope_data_.Initialize(); | 244 handle_scope_data_.Initialize(); |
127 | 245 |
128 #define ISOLATE_INIT_EXECUTE(type, name, initial_value) \ | 246 #define ISOLATE_INIT_EXECUTE(type, name, initial_value) \ |
129 name##_ = (initial_value); | 247 name##_ = (initial_value); |
130 ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE) | 248 ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE) |
131 #undef ISOLATE_INIT_EXECUTE | 249 #undef ISOLATE_INIT_EXECUTE |
132 | 250 |
133 #define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length) \ | 251 #define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length) \ |
134 memset(name##_, 0, sizeof(type) * length); | 252 memset(name##_, 0, sizeof(type) * length); |
135 ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE) | 253 ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE) |
136 #undef ISOLATE_INIT_ARRAY_EXECUTE | 254 #undef ISOLATE_INIT_ARRAY_EXECUTE |
137 } | 255 } |
138 | 256 |
139 | 257 |
| 258 void Isolate::TearDownAndRecreateGlobalIsolate() { |
| 259 if (global_isolate_ != NULL) { |
| 260 delete global_isolate_; |
| 261 global_isolate_ = NULL; |
| 262 } |
| 263 |
| 264 global_isolate_ = new Isolate(); |
| 265 global_isolate_->PreInit(); |
| 266 } |
| 267 |
| 268 |
140 Isolate::~Isolate() { | 269 Isolate::~Isolate() { |
| 270 if (state_ == INITIALIZED) { |
| 271 OProfileAgent::TearDown(); |
| 272 if (FLAG_preemption) { |
| 273 v8::Locker locker; |
| 274 v8::Locker::StopPreemption(); |
| 275 } |
| 276 Builtins::TearDown(); |
| 277 bootstrapper_->TearDown(); |
| 278 |
| 279 // Remove the external reference to the preallocated stack memory. |
| 280 delete preallocated_message_space_; |
| 281 preallocated_message_space_ = NULL; |
| 282 PreallocatedMemoryThreadStop(); |
| 283 |
| 284 HeapProfiler::TearDown(); |
| 285 CpuProfiler::TearDown(); |
| 286 heap_.TearDown(); |
| 287 Logger::TearDown(); |
| 288 } |
141 delete scanner_character_classes_; | 289 delete scanner_character_classes_; |
142 scanner_character_classes_ = NULL; | 290 scanner_character_classes_ = NULL; |
143 | 291 |
144 delete descriptor_lookup_cache_; | 292 delete descriptor_lookup_cache_; |
145 descriptor_lookup_cache_ = NULL; | 293 descriptor_lookup_cache_ = NULL; |
146 delete context_slot_cache_; | 294 delete context_slot_cache_; |
147 context_slot_cache_ = NULL; | 295 context_slot_cache_ = NULL; |
148 delete keyed_lookup_cache_; | 296 delete keyed_lookup_cache_; |
149 keyed_lookup_cache_ = NULL; | 297 keyed_lookup_cache_ = NULL; |
150 | 298 |
(...skipping 20 matching lines...) Expand all Loading... |
171 InitThreadForGlobalIsolate(); | 319 InitThreadForGlobalIsolate(); |
172 #endif | 320 #endif |
173 | 321 |
174 // Safe after setting Heap::isolate_, initializing StackGuard and | 322 // Safe after setting Heap::isolate_, initializing StackGuard and |
175 // ensuring that Isolate::Current() == this. | 323 // ensuring that Isolate::Current() == this. |
176 heap_.SetStackLimits(); | 324 heap_.SetStackLimits(); |
177 | 325 |
178 #ifdef DEBUG | 326 #ifdef DEBUG |
179 DisallowAllocationFailure disallow_allocation_failure; | 327 DisallowAllocationFailure disallow_allocation_failure; |
180 #endif | 328 #endif |
| 329 |
| 330 #define C(name) isolate_addresses_[Isolate::k_##name] = \ |
| 331 reinterpret_cast<Address>(name()); |
| 332 ISOLATE_ADDRESS_LIST(C) |
| 333 ISOLATE_ADDRESS_LIST_PROF(C) |
| 334 #undef C |
| 335 |
181 bootstrapper_ = new Bootstrapper(); | 336 bootstrapper_ = new Bootstrapper(); |
182 cpu_features_ = new CpuFeatures(); | 337 cpu_features_ = new CpuFeatures(); |
183 handle_scope_implementer_ = new HandleScopeImplementer(); | 338 handle_scope_implementer_ = new HandleScopeImplementer(); |
184 stub_cache_ = new StubCache(); | 339 stub_cache_ = new StubCache(); |
185 state_ = PREINITIALIZED; | 340 state_ = PREINITIALIZED; |
186 return true; | 341 return true; |
187 } | 342 } |
188 | 343 |
189 | 344 |
| 345 void Isolate::InitializeThreadLocal() { |
| 346 thread_local_top_.Initialize(); |
| 347 clear_pending_exception(); |
| 348 clear_pending_message(); |
| 349 clear_scheduled_exception(); |
| 350 } |
| 351 |
| 352 |
190 bool Isolate::Init(Deserializer* des) { | 353 bool Isolate::Init(Deserializer* des) { |
191 ASSERT(global_isolate_ == this); | 354 ASSERT(global_isolate_ == this); |
| 355 ASSERT(state_ != INITIALIZED); |
192 | 356 |
193 bool create_heap_objects = des == NULL; | 357 bool create_heap_objects = des == NULL; |
194 | 358 |
195 #ifdef DEBUG | 359 #ifdef DEBUG |
196 // The initialization process does not handle memory exhaustion. | 360 // The initialization process does not handle memory exhaustion. |
197 DisallowAllocationFailure disallow_allocation_failure; | 361 DisallowAllocationFailure disallow_allocation_failure; |
198 #endif | 362 #endif |
199 | 363 |
200 if (state_ == UNINITIALIZED && !PreInit()) return false; | 364 if (state_ == UNINITIALIZED && !PreInit()) return false; |
201 | 365 |
(...skipping 21 matching lines...) Expand all Loading... |
223 | 387 |
224 // Setup the object heap | 388 // Setup the object heap |
225 ASSERT(!heap_.HasBeenSetup()); | 389 ASSERT(!heap_.HasBeenSetup()); |
226 if (!heap_.Setup(create_heap_objects)) { | 390 if (!heap_.Setup(create_heap_objects)) { |
227 V8::SetFatalError(); | 391 V8::SetFatalError(); |
228 return false; | 392 return false; |
229 } | 393 } |
230 | 394 |
231 bootstrapper_->Initialize(create_heap_objects); | 395 bootstrapper_->Initialize(create_heap_objects); |
232 Builtins::Setup(create_heap_objects); | 396 Builtins::Setup(create_heap_objects); |
233 Top::Initialize(); | 397 |
| 398 InitializeThreadLocal(); |
| 399 |
| 400 // Only preallocate on the first initialization. |
| 401 if (FLAG_preallocate_message_memory && preallocated_message_space_ == NULL) { |
| 402 // Start the thread which will set aside some memory. |
| 403 PreallocatedMemoryThreadStart(); |
| 404 preallocated_message_space_ = |
| 405 new NoAllocationStringAllocator( |
| 406 preallocated_memory_thread_->data(), |
| 407 preallocated_memory_thread_->length()); |
| 408 PreallocatedStorage::Init(preallocated_memory_thread_->length() / 4); |
| 409 } |
234 | 410 |
235 if (FLAG_preemption) { | 411 if (FLAG_preemption) { |
236 v8::Locker locker; | 412 v8::Locker locker; |
237 v8::Locker::StartPreemption(100); | 413 v8::Locker::StartPreemption(100); |
238 } | 414 } |
239 | 415 |
240 #ifdef ENABLE_DEBUGGER_SUPPORT | 416 #ifdef ENABLE_DEBUGGER_SUPPORT |
241 Debug::Setup(create_heap_objects); | 417 Debug::Setup(create_heap_objects); |
242 #endif | 418 #endif |
243 stub_cache_->Initialize(create_heap_objects); | 419 stub_cache_->Initialize(create_heap_objects); |
(...skipping 22 matching lines...) Expand all Loading... |
266 LOG(LogCodeObjects()); | 442 LOG(LogCodeObjects()); |
267 LOG(LogCompiledFunctions()); | 443 LOG(LogCompiledFunctions()); |
268 } | 444 } |
269 | 445 |
270 state_ = INITIALIZED; | 446 state_ = INITIALIZED; |
271 return true; | 447 return true; |
272 } | 448 } |
273 | 449 |
274 | 450 |
275 } } // namespace v8::internal | 451 } } // namespace v8::internal |
OLD | NEW |