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