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