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/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 88407 : ~NativesStore() {
30 1001946 : for (size_t i = 0; i < native_names_.size(); i++) {
31 500973 : native_names_[i].Dispose();
32 : }
33 88407 : }
34 :
35 1350 : int GetBuiltinsCount() { return static_cast<int>(native_ids_.size()); }
36 : int GetDebuggerCount() { return debugger_count_; }
37 :
38 : Vector<const char> GetScriptSource(int index) {
39 1125396 : return native_source_[index];
40 : }
41 :
42 26440 : Vector<const char> GetScriptName(int index) { return native_names_[index]; }
43 :
44 0 : int GetIndex(const char* id) {
45 0 : for (int i = 0; i < static_cast<int>(native_ids_.size()); ++i) {
46 0 : int native_id_length = native_ids_[i].length();
47 0 : if ((static_cast<int>(strlen(id)) == native_id_length) &&
48 0 : (strncmp(id, native_ids_[i].start(), native_id_length) == 0)) {
49 0 : return i;
50 : }
51 : }
52 0 : UNREACHABLE();
53 : }
54 :
55 0 : Vector<const char> GetScriptsSource() {
56 0 : UNREACHABLE(); // Not implemented.
57 : }
58 :
59 161979 : static NativesStore* MakeFromScriptsSource(SnapshotByteSource* source) {
60 161979 : 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 161979 : int debugger_count = source->GetInt();
67 323958 : for (int i = 0; i < debugger_count; ++i)
68 161979 : store->ReadNameAndContentPair(source);
69 161979 : int library_count = source->GetInt();
70 755902 : for (int i = 0; i < library_count; ++i)
71 593923 : store->ReadNameAndContentPair(source);
72 :
73 161979 : store->debugger_count_ = debugger_count;
74 161979 : return store;
75 : }
76 :
77 : private:
78 161979 : NativesStore() : debugger_count_(0) {}
79 :
80 755902 : Vector<const char> NameFromId(const byte* id, int id_length) {
81 755902 : const char native[] = "native ";
82 755902 : const char extension[] = ".js";
83 : Vector<char> name(Vector<char>::New(id_length + sizeof(native) - 1 +
84 755902 : sizeof(extension) - 1));
85 : memcpy(name.start(), native, sizeof(native) - 1);
86 755902 : memcpy(name.start() + sizeof(native) - 1, id, id_length);
87 755902 : memcpy(name.start() + sizeof(native) - 1 + id_length, extension,
88 : sizeof(extension) - 1);
89 755902 : return Vector<const char>::cast(name);
90 : }
91 :
92 755902 : void ReadNameAndContentPair(SnapshotByteSource* bytes) {
93 : const byte* id;
94 : const byte* source;
95 755902 : int id_length = bytes->GetBlob(&id);
96 755902 : int source_length = bytes->GetBlob(&source);
97 755902 : native_ids_.emplace_back(reinterpret_cast<const char*>(id), id_length);
98 : native_source_.emplace_back(reinterpret_cast<const char*>(source),
99 755902 : source_length);
100 1511804 : native_names_.push_back(NameFromId(id, id_length));
101 755902 : }
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 593259 : static NativesStore* get() {
116 593259 : CHECK(holder_);
117 593259 : return holder_;
118 : }
119 161979 : static void set(NativesStore* store) {
120 161979 : CHECK(store);
121 161979 : holder_ = store;
122 161979 : }
123 57811 : static bool empty() { return holder_ == nullptr; }
124 88497 : static void Dispose() {
125 88497 : delete holder_;
126 88497 : holder_ = nullptr;
127 88497 : }
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 108313 : void ReadNatives() {
143 166124 : if (natives_blob_ && NativesHolder<CORE>::empty()) {
144 53993 : SnapshotByteSource bytes(natives_blob_->data, natives_blob_->raw_size);
145 53993 : NativesHolder<CORE>::set(NativesStore::MakeFromScriptsSource(&bytes));
146 53993 : NativesHolder<EXTRAS>::set(NativesStore::MakeFromScriptsSource(&bytes));
147 : NativesHolder<EXPERIMENTAL_EXTRAS>::set(
148 53993 : NativesStore::MakeFromScriptsSource(&bytes));
149 : DCHECK(!bytes.HasMore());
150 : }
151 108313 : }
152 :
153 :
154 : /**
155 : * Set the Natives (library sources) blob, as generated by js2c + the build
156 : * system.
157 : */
158 53983 : 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 53983 : natives_blob_ = natives_blob;
165 53983 : ReadNatives();
166 53983 : }
167 :
168 :
169 : /**
170 : * Release memory allocated by SetNativesFromFile.
171 : */
172 29499 : void DisposeNatives() {
173 29499 : NativesHolder<CORE>::Dispose();
174 29499 : NativesHolder<EXTRAS>::Dispose();
175 29499 : NativesHolder<EXPERIMENTAL_EXTRAS>::Dispose();
176 29499 : }
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 675 : int NativesCollection<type>::GetBuiltinsCount() {
187 1350 : return NativesHolder<type>::get()->GetBuiltinsCount();
188 : }
189 :
190 : template<NativeType type>
191 16666 : int NativesCollection<type>::GetDebuggerCount() {
192 16666 : return NativesHolder<type>::get()->GetDebuggerCount();
193 : }
194 :
195 : template<NativeType type>
196 0 : int NativesCollection<type>::GetIndex(const char* name) {
197 0 : return NativesHolder<type>::get()->GetIndex(name);
198 : }
199 :
200 : template <NativeType type>
201 562698 : Vector<const char> NativesCollection<type>::GetScriptSource(int index) {
202 1125396 : return NativesHolder<type>::get()->GetScriptSource(index);
203 : }
204 :
205 : template<NativeType type>
206 13220 : Vector<const char> NativesCollection<type>::GetScriptName(int index) {
207 26440 : return NativesHolder<type>::get()->GetScriptName(index);
208 : }
209 :
210 : template <NativeType type>
211 0 : Vector<const char> NativesCollection<type>::GetScriptsSource() {
212 0 : 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
|