Line data Source code
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 97377 : ~NativesStore() {
32 1493114 : for (int i = 0; i < native_names_.length(); i++) {
33 1395737 : native_names_[i].Dispose();
34 : }
35 97377 : }
36 :
37 1344 : int GetBuiltinsCount() { return native_ids_.length(); }
38 : int GetDebuggerCount() { return debugger_count_; }
39 :
40 : Vector<const char> GetScriptSource(int index) {
41 1980224 : return native_source_[index];
42 : }
43 :
44 37346 : Vector<const char> GetScriptName(int index) { return native_names_[index]; }
45 :
46 0 : int GetIndex(const char* id) {
47 0 : for (int i = 0; i < native_ids_.length(); ++i) {
48 0 : int native_id_length = native_ids_[i].length();
49 0 : if ((static_cast<int>(strlen(id)) == native_id_length) &&
50 0 : (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 178434 : static NativesStore* MakeFromScriptsSource(SnapshotByteSource* source) {
64 178434 : 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 178434 : int debugger_count = source->GetInt();
71 356868 : for (int i = 0; i < debugger_count; ++i)
72 178434 : store->ReadNameAndContentPair(source);
73 178434 : int library_count = source->GetInt();
74 1189560 : for (int i = 0; i < library_count; ++i)
75 1011126 : store->ReadNameAndContentPair(source);
76 :
77 178434 : store->debugger_count_ = debugger_count;
78 178434 : return store;
79 : }
80 :
81 : private:
82 178434 : NativesStore() : debugger_count_(0) {}
83 :
84 1189560 : Vector<const char> NameFromId(const byte* id, int id_length) {
85 1189560 : const char native[] = "native ";
86 1189560 : const char extension[] = ".js";
87 : Vector<char> name(Vector<char>::New(id_length + sizeof(native) - 1 +
88 1189560 : sizeof(extension) - 1));
89 : memcpy(name.start(), native, sizeof(native) - 1);
90 1189560 : memcpy(name.start() + sizeof(native) - 1, id, id_length);
91 1189560 : memcpy(name.start() + sizeof(native) - 1 + id_length, extension,
92 : sizeof(extension) - 1);
93 1189560 : return Vector<const char>::cast(name);
94 : }
95 :
96 1189560 : void ReadNameAndContentPair(SnapshotByteSource* bytes) {
97 : const byte* id;
98 : const byte* source;
99 1189560 : int id_length = bytes->GetBlob(&id);
100 1189560 : int source_length = bytes->GetBlob(&source);
101 1189560 : Vector<const char> id_vector(reinterpret_cast<const char*>(id), id_length);
102 : Vector<const char> source_vector(reinterpret_cast<const char*>(source),
103 1189560 : source_length);
104 1189560 : native_ids_.Add(id_vector);
105 1189560 : native_source_.Add(source_vector);
106 1189560 : native_names_.Add(NameFromId(id, id_length));
107 1189560 : }
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 1033080 : static NativesStore* get() {
122 1033080 : CHECK(holder_);
123 1033080 : return holder_;
124 : }
125 178434 : static void set(NativesStore* store) {
126 178434 : CHECK(store);
127 178434 : holder_ = store;
128 178434 : }
129 64462 : static bool empty() { return holder_ == NULL; }
130 97485 : static void Dispose() {
131 97485 : delete holder_;
132 97485 : holder_ = NULL;
133 97485 : }
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 119388 : void ReadNatives() {
151 183850 : if (natives_blob_ && NativesHolder<CORE>::empty()) {
152 59478 : SnapshotByteSource bytes(natives_blob_->data, natives_blob_->raw_size);
153 59478 : NativesHolder<CORE>::set(NativesStore::MakeFromScriptsSource(&bytes));
154 59478 : NativesHolder<EXTRAS>::set(NativesStore::MakeFromScriptsSource(&bytes));
155 : NativesHolder<EXPERIMENTAL_EXTRAS>::set(
156 59478 : NativesStore::MakeFromScriptsSource(&bytes));
157 : DCHECK(!bytes.HasMore());
158 : }
159 119388 : }
160 :
161 :
162 : /**
163 : * Set the Natives (library sources) blob, as generated by js2c + the build
164 : * system.
165 : */
166 59466 : void SetNativesFromFile(StartupData* natives_blob) {
167 : DCHECK(!natives_blob_);
168 : DCHECK(natives_blob);
169 : DCHECK(natives_blob->data);
170 : DCHECK(natives_blob->raw_size > 0);
171 :
172 59466 : natives_blob_ = natives_blob;
173 59466 : ReadNatives();
174 59466 : }
175 :
176 :
177 : /**
178 : * Release memory allocated by SetNativesFromFile.
179 : */
180 32495 : void DisposeNatives() {
181 32495 : NativesHolder<CORE>::Dispose();
182 32495 : NativesHolder<EXTRAS>::Dispose();
183 32495 : NativesHolder<EXPERIMENTAL_EXTRAS>::Dispose();
184 32495 : }
185 :
186 :
187 : // Implement NativesCollection<T> bsaed on NativesHolder + NativesStore.
188 : //
189 : // (The callers expect a purely static interface, since this is how the
190 : // natives are usually compiled in. Since we implement them based on
191 : // runtime content, we have to implement this indirection to offer
192 : // a static interface.)
193 : template<NativeType type>
194 1344 : int NativesCollection<type>::GetBuiltinsCount() {
195 2688 : return NativesHolder<type>::get()->GetBuiltinsCount();
196 : }
197 :
198 : template<NativeType type>
199 22951 : int NativesCollection<type>::GetDebuggerCount() {
200 22951 : return NativesHolder<type>::get()->GetDebuggerCount();
201 : }
202 :
203 : template<NativeType type>
204 0 : int NativesCollection<type>::GetIndex(const char* name) {
205 0 : return NativesHolder<type>::get()->GetIndex(name);
206 : }
207 :
208 : template <NativeType type>
209 990112 : Vector<const char> NativesCollection<type>::GetScriptSource(int index) {
210 1980224 : return NativesHolder<type>::get()->GetScriptSource(index);
211 : }
212 :
213 : template<NativeType type>
214 18673 : Vector<const char> NativesCollection<type>::GetScriptName(int index) {
215 37346 : return NativesHolder<type>::get()->GetScriptName(index);
216 : }
217 :
218 : template <NativeType type>
219 0 : Vector<const char> NativesCollection<type>::GetScriptsSource() {
220 0 : return NativesHolder<type>::get()->GetScriptsSource();
221 : }
222 :
223 :
224 : // Explicit template instantiations.
225 : #define INSTANTIATE_TEMPLATES(T) \
226 : template int NativesCollection<T>::GetBuiltinsCount(); \
227 : template int NativesCollection<T>::GetDebuggerCount(); \
228 : template int NativesCollection<T>::GetIndex(const char* name); \
229 : template Vector<const char> NativesCollection<T>::GetScriptSource(int i); \
230 : template Vector<const char> NativesCollection<T>::GetScriptName(int i); \
231 : template Vector<const char> NativesCollection<T>::GetScriptsSource();
232 : INSTANTIATE_TEMPLATES(CORE)
233 : INSTANTIATE_TEMPLATES(EXTRAS)
234 : INSTANTIATE_TEMPLATES(EXPERIMENTAL_EXTRAS)
235 : #undef INSTANTIATE_TEMPLATES
236 :
237 : } // namespace internal
238 : } // namespace v8
|