Home | History | Annotate | Download | only in src
      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