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 #include "v8.h" 29 30 #include "assembler.h" 31 #include "isolate.h" 32 #include "elements.h" 33 #include "bootstrapper.h" 34 #include "debug.h" 35 #include "deoptimizer.h" 36 #include "frames.h" 37 #include "heap-profiler.h" 38 #include "hydrogen.h" 39 #include "lithium-allocator.h" 40 #include "objects.h" 41 #include "once.h" 42 #include "platform.h" 43 #include "sampler.h" 44 #include "runtime-profiler.h" 45 #include "serialize.h" 46 #include "store-buffer.h" 47 48 namespace v8 { 49 namespace internal { 50 51 V8_DECLARE_ONCE(init_once); 52 53 bool V8::is_running_ = false; 54 bool V8::has_been_set_up_ = false; 55 bool V8::has_been_disposed_ = false; 56 bool V8::has_fatal_error_ = false; 57 bool V8::use_crankshaft_ = true; 58 List<CallCompletedCallback>* V8::call_completed_callbacks_ = NULL; 59 v8::ArrayBuffer::Allocator* V8::array_buffer_allocator_ = NULL; 60 61 static LazyMutex entropy_mutex = LAZY_MUTEX_INITIALIZER; 62 63 static EntropySource entropy_source; 64 65 66 bool V8::Initialize(Deserializer* des) { 67 InitializeOncePerProcess(); 68 69 // The current thread may not yet had entered an isolate to run. 70 // Note the Isolate::Current() may be non-null because for various 71 // initialization purposes an initializing thread may be assigned an isolate 72 // but not actually enter it. 73 if (i::Isolate::CurrentPerIsolateThreadData() == NULL) { 74 i::Isolate::EnterDefaultIsolate(); 75 } 76 77 ASSERT(i::Isolate::CurrentPerIsolateThreadData() != NULL); 78 ASSERT(i::Isolate::CurrentPerIsolateThreadData()->thread_id().Equals( 79 i::ThreadId::Current())); 80 ASSERT(i::Isolate::CurrentPerIsolateThreadData()->isolate() == 81 i::Isolate::Current()); 82 83 if (IsDead()) return false; 84 85 Isolate* isolate = Isolate::Current(); 86 if (isolate->IsInitialized()) return true; 87 88 is_running_ = true; 89 has_been_set_up_ = true; 90 has_fatal_error_ = false; 91 has_been_disposed_ = false; 92 93 return isolate->Init(des); 94 } 95 96 97 void V8::SetFatalError() { 98 is_running_ = false; 99 has_fatal_error_ = true; 100 } 101 102 103 void V8::TearDown() { 104 Isolate* isolate = Isolate::Current(); 105 ASSERT(isolate->IsDefaultIsolate()); 106 107 if (!has_been_set_up_ || has_been_disposed_) return; 108 109 // The isolate has to be torn down before clearing the LOperand 110 // caches so that the optimizing compiler thread (if running) 111 // doesn't see an inconsistent view of the lithium instructions. 112 isolate->TearDown(); 113 delete isolate; 114 115 ElementsAccessor::TearDown(); 116 LOperand::TearDownCaches(); 117 ExternalReference::TearDownMathExpData(); 118 RegisteredExtension::UnregisterAll(); 119 Isolate::GlobalTearDown(); 120 121 is_running_ = false; 122 has_been_disposed_ = true; 123 124 delete call_completed_callbacks_; 125 call_completed_callbacks_ = NULL; 126 127 Sampler::TearDown(); 128 OS::TearDown(); 129 } 130 131 132 static void seed_random(uint32_t* state) { 133 for (int i = 0; i < 2; ++i) { 134 if (FLAG_random_seed != 0) { 135 state[i] = FLAG_random_seed; 136 } else if (entropy_source != NULL) { 137 uint32_t val; 138 ScopedLock lock(entropy_mutex.Pointer()); 139 entropy_source(reinterpret_cast<unsigned char*>(&val), sizeof(uint32_t)); 140 state[i] = val; 141 } else { 142 state[i] = random(); 143 } 144 } 145 } 146 147 148 // Random number generator using George Marsaglia's MWC algorithm. 149 static uint32_t random_base(uint32_t* state) { 150 // Initialize seed using the system random(). 151 // No non-zero seed will ever become zero again. 152 if (state[0] == 0) seed_random(state); 153 154 // Mix the bits. Never replaces state[i] with 0 if it is nonzero. 155 state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16); 156 state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16); 157 158 return (state[0] << 14) + (state[1] & 0x3FFFF); 159 } 160 161 162 void V8::SetEntropySource(EntropySource source) { 163 entropy_source = source; 164 } 165 166 167 void V8::SetReturnAddressLocationResolver( 168 ReturnAddressLocationResolver resolver) { 169 StackFrame::SetReturnAddressLocationResolver(resolver); 170 } 171 172 173 // Used by JavaScript APIs 174 uint32_t V8::Random(Context* context) { 175 ASSERT(context->IsNativeContext()); 176 ByteArray* seed = context->random_seed(); 177 return random_base(reinterpret_cast<uint32_t*>(seed->GetDataStartAddress())); 178 } 179 180 181 // Used internally by the JIT and memory allocator for security 182 // purposes. So, we keep a different state to prevent informations 183 // leaks that could be used in an exploit. 184 uint32_t V8::RandomPrivate(Isolate* isolate) { 185 ASSERT(isolate == Isolate::Current()); 186 return random_base(isolate->private_random_seed()); 187 } 188 189 190 bool V8::IdleNotification(int hint) { 191 // Returning true tells the caller that there is no need to call 192 // IdleNotification again. 193 if (!FLAG_use_idle_notification) return true; 194 195 // Tell the heap that it may want to adjust. 196 return HEAP->IdleNotification(hint); 197 } 198 199 200 void V8::AddCallCompletedCallback(CallCompletedCallback callback) { 201 if (call_completed_callbacks_ == NULL) { // Lazy init. 202 call_completed_callbacks_ = new List<CallCompletedCallback>(); 203 } 204 for (int i = 0; i < call_completed_callbacks_->length(); i++) { 205 if (callback == call_completed_callbacks_->at(i)) return; 206 } 207 call_completed_callbacks_->Add(callback); 208 } 209 210 211 void V8::RemoveCallCompletedCallback(CallCompletedCallback callback) { 212 if (call_completed_callbacks_ == NULL) return; 213 for (int i = 0; i < call_completed_callbacks_->length(); i++) { 214 if (callback == call_completed_callbacks_->at(i)) { 215 call_completed_callbacks_->Remove(i); 216 } 217 } 218 } 219 220 221 void V8::FireCallCompletedCallback(Isolate* isolate) { 222 bool has_call_completed_callbacks = call_completed_callbacks_ != NULL; 223 bool observer_delivery_pending = 224 FLAG_harmony_observation && isolate->observer_delivery_pending(); 225 if (!has_call_completed_callbacks && !observer_delivery_pending) return; 226 HandleScopeImplementer* handle_scope_implementer = 227 isolate->handle_scope_implementer(); 228 if (!handle_scope_implementer->CallDepthIsZero()) return; 229 // Fire callbacks. Increase call depth to prevent recursive callbacks. 230 handle_scope_implementer->IncrementCallDepth(); 231 if (observer_delivery_pending) { 232 JSObject::DeliverChangeRecords(isolate); 233 } 234 if (has_call_completed_callbacks) { 235 for (int i = 0; i < call_completed_callbacks_->length(); i++) { 236 call_completed_callbacks_->at(i)(); 237 } 238 } 239 handle_scope_implementer->DecrementCallDepth(); 240 } 241 242 243 // Use a union type to avoid type-aliasing optimizations in GCC. 244 typedef union { 245 double double_value; 246 uint64_t uint64_t_value; 247 } double_int_union; 248 249 250 Object* V8::FillHeapNumberWithRandom(Object* heap_number, 251 Context* context) { 252 double_int_union r; 253 uint64_t random_bits = Random(context); 254 // Convert 32 random bits to 0.(32 random bits) in a double 255 // by computing: 256 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 257 static const double binary_million = 1048576.0; 258 r.double_value = binary_million; 259 r.uint64_t_value |= random_bits; 260 r.double_value -= binary_million; 261 262 HeapNumber::cast(heap_number)->set_value(r.double_value); 263 return heap_number; 264 } 265 266 267 void V8::InitializeOncePerProcessImpl() { 268 FlagList::EnforceFlagImplications(); 269 if (FLAG_stress_compaction) { 270 FLAG_force_marking_deque_overflows = true; 271 FLAG_gc_global = true; 272 FLAG_max_new_space_size = (1 << (kPageSizeBits - 10)) * 2; 273 } 274 275 if (FLAG_parallel_recompilation && 276 (FLAG_trace_hydrogen || FLAG_trace_hydrogen_stubs)) { 277 FLAG_parallel_recompilation = false; 278 PrintF("Parallel recompilation has been disabled for tracing.\n"); 279 } 280 281 if (FLAG_sweeper_threads <= 0) { 282 if (FLAG_concurrent_sweeping) { 283 FLAG_sweeper_threads = SystemThreadManager:: 284 NumberOfParallelSystemThreads( 285 SystemThreadManager::CONCURRENT_SWEEPING); 286 } else if (FLAG_parallel_sweeping) { 287 FLAG_sweeper_threads = SystemThreadManager:: 288 NumberOfParallelSystemThreads( 289 SystemThreadManager::PARALLEL_SWEEPING); 290 } 291 if (FLAG_sweeper_threads == 0) { 292 FLAG_concurrent_sweeping = false; 293 FLAG_parallel_sweeping = false; 294 } 295 } else if (!FLAG_concurrent_sweeping && !FLAG_parallel_sweeping) { 296 FLAG_sweeper_threads = 0; 297 } 298 299 if (FLAG_parallel_marking) { 300 if (FLAG_marking_threads <= 0) { 301 FLAG_marking_threads = SystemThreadManager:: 302 NumberOfParallelSystemThreads( 303 SystemThreadManager::PARALLEL_MARKING); 304 } 305 if (FLAG_marking_threads == 0) { 306 FLAG_parallel_marking = false; 307 } 308 } else { 309 FLAG_marking_threads = 0; 310 } 311 312 if (FLAG_parallel_recompilation && 313 SystemThreadManager::NumberOfParallelSystemThreads( 314 SystemThreadManager::PARALLEL_RECOMPILATION) == 0) { 315 FLAG_parallel_recompilation = false; 316 } 317 318 OS::SetUp(); 319 Sampler::SetUp(); 320 CPU::SetUp(); 321 use_crankshaft_ = FLAG_crankshaft 322 && !Serializer::enabled() 323 && CPU::SupportsCrankshaft(); 324 OS::PostSetUp(); 325 ElementsAccessor::InitializeOncePerProcess(); 326 LOperand::SetUpCaches(); 327 SetUpJSCallerSavedCodeData(); 328 ExternalReference::SetUp(); 329 Bootstrapper::InitializeOncePerProcess(); 330 } 331 332 333 void V8::InitializeOncePerProcess() { 334 CallOnce(&init_once, &InitializeOncePerProcessImpl); 335 } 336 337 } } // namespace v8::internal 338