Home | History | Annotate | Download | only in snapshot
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/snapshot/natives.h"
      6 
      7 #include "src/base/logging.h"
      8 #include "src/snapshot/snapshot-source-sink.h"
      9 #include "src/vector.h"
     10 
     11 #ifndef V8_USE_EXTERNAL_STARTUP_DATA
     12 #error natives-external.cc is used only for the external snapshot build.
     13 #endif  // V8_USE_EXTERNAL_STARTUP_DATA
     14 
     15 
     16 namespace v8 {
     17 namespace internal {
     18 
     19 
     20 /**
     21  * NativesStore stores the 'native' (builtin) JS libraries.
     22  *
     23  * NativesStore needs to be initialized before using V8, usually by the
     24  * embedder calling v8::SetNativesDataBlob, which calls SetNativesFromFile
     25  * below.
     26  */
     27 class NativesStore {
     28  public:
     29   ~NativesStore() {
     30     for (size_t i = 0; i < native_names_.size(); i++) {
     31       native_names_[i].Dispose();
     32     }
     33   }
     34 
     35   int GetBuiltinsCount() { return static_cast<int>(native_ids_.size()); }
     36   int GetDebuggerCount() { return debugger_count_; }
     37 
     38   Vector<const char> GetScriptSource(int index) {
     39     return native_source_[index];
     40   }
     41 
     42   Vector<const char> GetScriptName(int index) { return native_names_[index]; }
     43 
     44   int GetIndex(const char* id) {
     45     for (int i = 0; i < static_cast<int>(native_ids_.size()); ++i) {
     46       int native_id_length = native_ids_[i].length();
     47       if ((static_cast<int>(strlen(id)) == native_id_length) &&
     48           (strncmp(id, native_ids_[i].start(), native_id_length) == 0)) {
     49         return i;
     50       }
     51     }
     52     UNREACHABLE();
     53   }
     54 
     55   Vector<const char> GetScriptsSource() {
     56     UNREACHABLE();  // Not implemented.
     57   }
     58 
     59   static NativesStore* MakeFromScriptsSource(SnapshotByteSource* source) {
     60     NativesStore* store = new NativesStore;
     61 
     62     // We expect the libraries in the following format:
     63     //   int: # of debugger sources.
     64     //   2N blobs: N pairs of source name + actual source.
     65     //   then, repeat for non-debugger sources.
     66     int debugger_count = source->GetInt();
     67     for (int i = 0; i < debugger_count; ++i)
     68       store->ReadNameAndContentPair(source);
     69     int library_count = source->GetInt();
     70     for (int i = 0; i < library_count; ++i)
     71       store->ReadNameAndContentPair(source);
     72 
     73     store->debugger_count_ = debugger_count;
     74     return store;
     75   }
     76 
     77  private:
     78   NativesStore() : debugger_count_(0) {}
     79 
     80   Vector<const char> NameFromId(const byte* id, int id_length) {
     81     const char native[] = "native ";
     82     const char extension[] = ".js";
     83     Vector<char> name(Vector<char>::New(id_length + sizeof(native) - 1 +
     84                                         sizeof(extension) - 1));
     85     memcpy(name.start(), native, sizeof(native) - 1);
     86     memcpy(name.start() + sizeof(native) - 1, id, id_length);
     87     memcpy(name.start() + sizeof(native) - 1 + id_length, extension,
     88            sizeof(extension) - 1);
     89     return Vector<const char>::cast(name);
     90   }
     91 
     92   void ReadNameAndContentPair(SnapshotByteSource* bytes) {
     93     const byte* id;
     94     const byte* source;
     95     int id_length = bytes->GetBlob(&id);
     96     int source_length = bytes->GetBlob(&source);
     97     native_ids_.emplace_back(reinterpret_cast<const char*>(id), id_length);
     98     native_source_.emplace_back(reinterpret_cast<const char*>(source),
     99                                 source_length);
    100     native_names_.push_back(NameFromId(id, id_length));
    101   }
    102 
    103   std::vector<Vector<const char>> native_ids_;
    104   std::vector<Vector<const char>> native_names_;
    105   std::vector<Vector<const char>> native_source_;
    106   int debugger_count_;
    107 
    108   DISALLOW_COPY_AND_ASSIGN(NativesStore);
    109 };
    110 
    111 
    112 template<NativeType type>
    113 class NativesHolder {
    114  public:
    115   static NativesStore* get() {
    116     CHECK(holder_);
    117     return holder_;
    118   }
    119   static void set(NativesStore* store) {
    120     CHECK(store);
    121     holder_ = store;
    122   }
    123   static bool empty() { return holder_ == nullptr; }
    124   static void Dispose() {
    125     delete holder_;
    126     holder_ = nullptr;
    127   }
    128 
    129  private:
    130   static NativesStore* holder_;
    131 };
    132 
    133 template <NativeType type>
    134 NativesStore* NativesHolder<type>::holder_ = nullptr;
    135 
    136 // The natives blob. Memory is owned by caller.
    137 static StartupData* natives_blob_ = nullptr;
    138 
    139 /**
    140  * Read the Natives blob, as previously set by SetNativesFromFile.
    141  */
    142 void ReadNatives() {
    143   if (natives_blob_ && NativesHolder<CORE>::empty()) {
    144     SnapshotByteSource bytes(natives_blob_->data, natives_blob_->raw_size);
    145     NativesHolder<CORE>::set(NativesStore::MakeFromScriptsSource(&bytes));
    146     NativesHolder<EXTRAS>::set(NativesStore::MakeFromScriptsSource(&bytes));
    147     NativesHolder<EXPERIMENTAL_EXTRAS>::set(
    148         NativesStore::MakeFromScriptsSource(&bytes));
    149     DCHECK(!bytes.HasMore());
    150   }
    151 }
    152 
    153 
    154 /**
    155  * Set the Natives (library sources) blob, as generated by js2c + the build
    156  * system.
    157  */
    158 void SetNativesFromFile(StartupData* natives_blob) {
    159   DCHECK(!natives_blob_);
    160   DCHECK(natives_blob);
    161   DCHECK(natives_blob->data);
    162   DCHECK_GT(natives_blob->raw_size, 0);
    163 
    164   natives_blob_ = natives_blob;
    165   ReadNatives();
    166 }
    167 
    168 
    169 /**
    170  * Release memory allocated by SetNativesFromFile.
    171  */
    172 void DisposeNatives() {
    173   NativesHolder<CORE>::Dispose();
    174   NativesHolder<EXTRAS>::Dispose();
    175   NativesHolder<EXPERIMENTAL_EXTRAS>::Dispose();
    176 }
    177 
    178 
    179 // Implement NativesCollection<T> bsaed on NativesHolder + NativesStore.
    180 //
    181 // (The callers expect a purely static interface, since this is how the
    182 //  natives are usually compiled in. Since we implement them based on
    183 //  runtime content, we have to implement this indirection to offer
    184 //  a static interface.)
    185 template<NativeType type>
    186 int NativesCollection<type>::GetBuiltinsCount() {
    187   return NativesHolder<type>::get()->GetBuiltinsCount();
    188 }
    189 
    190 template<NativeType type>
    191 int NativesCollection<type>::GetDebuggerCount() {
    192   return NativesHolder<type>::get()->GetDebuggerCount();
    193 }
    194 
    195 template<NativeType type>
    196 int NativesCollection<type>::GetIndex(const char* name) {
    197   return NativesHolder<type>::get()->GetIndex(name);
    198 }
    199 
    200 template <NativeType type>
    201 Vector<const char> NativesCollection<type>::GetScriptSource(int index) {
    202   return NativesHolder<type>::get()->GetScriptSource(index);
    203 }
    204 
    205 template<NativeType type>
    206 Vector<const char> NativesCollection<type>::GetScriptName(int index) {
    207   return NativesHolder<type>::get()->GetScriptName(index);
    208 }
    209 
    210 template <NativeType type>
    211 Vector<const char> NativesCollection<type>::GetScriptsSource() {
    212   return NativesHolder<type>::get()->GetScriptsSource();
    213 }
    214 
    215 
    216 // Explicit template instantiations.
    217 #define INSTANTIATE_TEMPLATES(T)                                            \
    218   template int NativesCollection<T>::GetBuiltinsCount();                    \
    219   template int NativesCollection<T>::GetDebuggerCount();                    \
    220   template int NativesCollection<T>::GetIndex(const char* name);            \
    221   template Vector<const char> NativesCollection<T>::GetScriptSource(int i); \
    222   template Vector<const char> NativesCollection<T>::GetScriptName(int i);   \
    223   template Vector<const char> NativesCollection<T>::GetScriptsSource();
    224 INSTANTIATE_TEMPLATES(CORE)
    225 INSTANTIATE_TEMPLATES(EXTRAS)
    226 INSTANTIATE_TEMPLATES(EXPERIMENTAL_EXTRAS)
    227 #undef INSTANTIATE_TEMPLATES
    228 
    229 }  // namespace internal
    230 }  // namespace v8
    231