Home | History | Annotate | Download | only in src
      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/natives.h"
      6 
      7 #include "src/base/logging.h"
      8 #include "src/list.h"
      9 #include "src/list-inl.h"
     10 #include "src/snapshot-source-sink.h"
     11 #include "src/vector.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 
     17 /**
     18  * NativesStore stores the 'native' (builtin) JS libraries.
     19  *
     20  * NativesStore needs to be initialized before using V8, usually by the
     21  * embedder calling v8::SetNativesDataBlob, which calls SetNativesFromFile
     22  * below.
     23  */
     24 class NativesStore {
     25  public:
     26   ~NativesStore() {}
     27 
     28   int GetBuiltinsCount() { return native_names_.length(); }
     29   int GetDebuggerCount() { return debugger_count_; }
     30   Vector<const char> GetScriptName(int index) { return native_names_[index]; }
     31   Vector<const char> GetRawScriptSource(int index) {
     32     return native_source_[index];
     33   }
     34 
     35   int GetIndex(const char* name) {
     36     for (int i = 0; i < native_names_.length(); ++i) {
     37       int native_name_length = native_names_[i].length();
     38       if ((static_cast<int>(strlen(name)) == native_name_length) &&
     39           (strncmp(name, native_names_[i].start(), native_name_length) == 0)) {
     40         return i;
     41       }
     42     }
     43     DCHECK(false);
     44     return -1;
     45   }
     46 
     47   int GetRawScriptsSize() {
     48     DCHECK(false);  // Used for compression. Doesn't really make sense here.
     49     return 0;
     50   }
     51 
     52   Vector<const byte> GetScriptsSource() {
     53     DCHECK(false);  // Used for compression. Doesn't really make sense here.
     54     return Vector<const byte>();
     55   }
     56 
     57   static NativesStore* MakeFromScriptsSource(SnapshotByteSource* source) {
     58     NativesStore* store = new NativesStore;
     59 
     60     // We expect the libraries in the following format:
     61     //   int: # of debugger sources.
     62     //   2N blobs: N pairs of source name + actual source.
     63     //   then, repeat for non-debugger sources.
     64     int debugger_count = source->GetInt();
     65     for (int i = 0; i < debugger_count; ++i)
     66       store->ReadNameAndContentPair(source);
     67     int library_count = source->GetInt();
     68     for (int i = 0; i < library_count; ++i)
     69       store->ReadNameAndContentPair(source);
     70 
     71     store->debugger_count_ = debugger_count;
     72     return store;
     73   }
     74 
     75  private:
     76   NativesStore() : debugger_count_(0) {}
     77 
     78   bool ReadNameAndContentPair(SnapshotByteSource* bytes) {
     79     const byte* name;
     80     int name_length;
     81     const byte* source;
     82     int source_length;
     83     bool success = bytes->GetBlob(&name, &name_length) &&
     84                    bytes->GetBlob(&source, &source_length);
     85     if (success) {
     86       Vector<const char> name_vector(
     87           reinterpret_cast<const char*>(name), name_length);
     88       Vector<const char> source_vector(
     89           reinterpret_cast<const char*>(source), source_length);
     90       native_names_.Add(name_vector);
     91       native_source_.Add(source_vector);
     92     }
     93     return success;
     94   }
     95 
     96   List<Vector<const char> > native_names_;
     97   List<Vector<const char> > native_source_;
     98   int debugger_count_;
     99 
    100   DISALLOW_COPY_AND_ASSIGN(NativesStore);
    101 };
    102 
    103 
    104 template<NativeType type>
    105 class NativesHolder {
    106  public:
    107   static NativesStore* get() {
    108     DCHECK(holder_);
    109     return holder_;
    110   }
    111   static void set(NativesStore* store) {
    112     DCHECK(store);
    113     holder_ = store;
    114   }
    115 
    116  private:
    117   static NativesStore* holder_;
    118 };
    119 
    120 template<NativeType type>
    121 NativesStore* NativesHolder<type>::holder_ = NULL;
    122 
    123 
    124 /**
    125  * Read the Natives (library sources) blob, as generated by js2c + the build
    126  * system.
    127  */
    128 void SetNativesFromFile(StartupData* natives_blob) {
    129   DCHECK(natives_blob);
    130   DCHECK(natives_blob->data);
    131   DCHECK(natives_blob->raw_size > 0);
    132 
    133   SnapshotByteSource bytes(
    134       reinterpret_cast<const byte*>(natives_blob->data),
    135       natives_blob->raw_size);
    136   NativesHolder<CORE>::set(NativesStore::MakeFromScriptsSource(&bytes));
    137   NativesHolder<EXPERIMENTAL>::set(NativesStore::MakeFromScriptsSource(&bytes));
    138   DCHECK(!bytes.HasMore());
    139 }
    140 
    141 
    142 // Implement NativesCollection<T> bsaed on NativesHolder + NativesStore.
    143 //
    144 // (The callers expect a purely static interface, since this is how the
    145 //  natives are usually compiled in. Since we implement them based on
    146 //  runtime content, we have to implement this indirection to offer
    147 //  a static interface.)
    148 template<NativeType type>
    149 int NativesCollection<type>::GetBuiltinsCount() {
    150   return NativesHolder<type>::get()->GetBuiltinsCount();
    151 }
    152 
    153 template<NativeType type>
    154 int NativesCollection<type>::GetDebuggerCount() {
    155   return NativesHolder<type>::get()->GetDebuggerCount();
    156 }
    157 
    158 template<NativeType type>
    159 int NativesCollection<type>::GetIndex(const char* name) {
    160   return NativesHolder<type>::get()->GetIndex(name);
    161 }
    162 
    163 template<NativeType type>
    164 int NativesCollection<type>::GetRawScriptsSize() {
    165   return NativesHolder<type>::get()->GetRawScriptsSize();
    166 }
    167 
    168 template<NativeType type>
    169 Vector<const char> NativesCollection<type>::GetRawScriptSource(int index) {
    170   return NativesHolder<type>::get()->GetRawScriptSource(index);
    171 }
    172 
    173 template<NativeType type>
    174 Vector<const char> NativesCollection<type>::GetScriptName(int index) {
    175   return NativesHolder<type>::get()->GetScriptName(index);
    176 }
    177 
    178 template<NativeType type>
    179 Vector<const byte> NativesCollection<type>::GetScriptsSource() {
    180   return NativesHolder<type>::get()->GetScriptsSource();
    181 }
    182 
    183 template<NativeType type>
    184 void NativesCollection<type>::SetRawScriptsSource(
    185     Vector<const char> raw_source) {
    186   CHECK(false);  // Use SetNativesFromFile for this implementation.
    187 }
    188 
    189 
    190 // The compiler can't 'see' all uses of the static methods and hence
    191 // my chose to elide them. This we'll explicitly instantiate these.
    192 template class NativesCollection<CORE>;
    193 template class NativesCollection<EXPERIMENTAL>;
    194 template class NativesCollection<D8>;
    195 template class NativesCollection<TEST>;
    196 
    197 }  // namespace v8::internal
    198 }  // namespace v8
    199