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:
~NativesStore()26   ~NativesStore() {}
27 
GetBuiltinsCount()28   int GetBuiltinsCount() { return native_names_.length(); }
GetDebuggerCount()29   int GetDebuggerCount() { return debugger_count_; }
GetScriptName(int index)30   Vector<const char> GetScriptName(int index) { return native_names_[index]; }
GetRawScriptSource(int index)31   Vector<const char> GetRawScriptSource(int index) {
32     return native_source_[index];
33   }
34 
GetIndex(const char * name)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 
GetRawScriptsSize()47   int GetRawScriptsSize() {
48     DCHECK(false);  // Used for compression. Doesn't really make sense here.
49     return 0;
50   }
51 
GetScriptsSource()52   Vector<const byte> GetScriptsSource() {
53     DCHECK(false);  // Used for compression. Doesn't really make sense here.
54     return Vector<const byte>();
55   }
56 
MakeFromScriptsSource(SnapshotByteSource * source)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:
NativesStore()76   NativesStore() : debugger_count_(0) {}
77 
ReadNameAndContentPair(SnapshotByteSource * bytes)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:
get()107   static NativesStore* get() {
108     DCHECK(holder_);
109     return holder_;
110   }
set(NativesStore * store)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  */
SetNativesFromFile(StartupData * natives_blob)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>
GetBuiltinsCount()149 int NativesCollection<type>::GetBuiltinsCount() {
150   return NativesHolder<type>::get()->GetBuiltinsCount();
151 }
152 
153 template<NativeType type>
GetDebuggerCount()154 int NativesCollection<type>::GetDebuggerCount() {
155   return NativesHolder<type>::get()->GetDebuggerCount();
156 }
157 
158 template<NativeType type>
GetIndex(const char * name)159 int NativesCollection<type>::GetIndex(const char* name) {
160   return NativesHolder<type>::get()->GetIndex(name);
161 }
162 
163 template<NativeType type>
GetRawScriptsSize()164 int NativesCollection<type>::GetRawScriptsSize() {
165   return NativesHolder<type>::get()->GetRawScriptsSize();
166 }
167 
168 template<NativeType type>
GetRawScriptSource(int index)169 Vector<const char> NativesCollection<type>::GetRawScriptSource(int index) {
170   return NativesHolder<type>::get()->GetRawScriptSource(index);
171 }
172 
173 template<NativeType type>
GetScriptName(int index)174 Vector<const char> NativesCollection<type>::GetScriptName(int index) {
175   return NativesHolder<type>::get()->GetScriptName(index);
176 }
177 
178 template<NativeType type>
GetScriptsSource()179 Vector<const byte> NativesCollection<type>::GetScriptsSource() {
180   return NativesHolder<type>::get()->GetScriptsSource();
181 }
182 
183 template<NativeType type>
SetRawScriptsSource(Vector<const char> raw_source)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