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 119692 : ~NativesStore() {
30 179538 : for (size_t i = 0; i < native_names_.size(); i++) {
31 : native_names_[i].Dispose();
32 : }
33 59846 : }
34 :
35 220 : int GetBuiltinsCount() { return static_cast<int>(native_ids_.size()); }
36 :
37 : Vector<const char> GetScriptSource(int index) {
38 124868 : return native_source_[index];
39 : }
40 :
41 220 : Vector<const char> GetScriptName(int index) { return native_names_[index]; }
42 :
43 0 : int GetIndex(const char* id) {
44 0 : for (int i = 0; i < static_cast<int>(native_ids_.size()); ++i) {
45 0 : int native_id_length = native_ids_[i].length();
46 0 : if ((static_cast<int>(strlen(id)) == native_id_length) &&
47 0 : (strncmp(id, native_ids_[i].start(), native_id_length) == 0)) {
48 0 : return i;
49 : }
50 : }
51 0 : UNREACHABLE();
52 : }
53 :
54 0 : Vector<const char> GetScriptsSource() {
55 0 : UNREACHABLE(); // Not implemented.
56 : }
57 :
58 61011 : static NativesStore* MakeFromScriptsSource(SnapshotByteSource* source) {
59 61011 : NativesStore* store = new NativesStore;
60 :
61 : // We expect the libraries in the following format:
62 : // int: # of sources.
63 : // 2N blobs: N pairs of source name + actual source.
64 61011 : int library_count = source->GetInt();
65 183033 : for (int i = 0; i < library_count; ++i)
66 61011 : store->ReadNameAndContentPair(source);
67 :
68 61011 : return store;
69 : }
70 :
71 : private:
72 : NativesStore() = default;
73 :
74 61011 : Vector<const char> NameFromId(const byte* id, int id_length) {
75 61011 : const char native[] = "native ";
76 61011 : const char extension[] = ".js";
77 : Vector<char> name(Vector<char>::New(id_length + sizeof(native) - 1 +
78 61011 : sizeof(extension) - 1));
79 : memcpy(name.start(), native, sizeof(native) - 1);
80 61011 : memcpy(name.start() + sizeof(native) - 1, id, id_length);
81 61011 : memcpy(name.start() + sizeof(native) - 1 + id_length, extension,
82 : sizeof(extension) - 1);
83 61011 : return Vector<const char>::cast(name);
84 : }
85 :
86 61011 : void ReadNameAndContentPair(SnapshotByteSource* bytes) {
87 : const byte* id;
88 : const byte* source;
89 61011 : int id_length = bytes->GetBlob(&id);
90 61011 : int source_length = bytes->GetBlob(&source);
91 61011 : native_ids_.emplace_back(reinterpret_cast<const char*>(id), id_length);
92 122022 : native_source_.emplace_back(reinterpret_cast<const char*>(source),
93 61011 : source_length);
94 122022 : native_names_.push_back(NameFromId(id, id_length));
95 61011 : }
96 :
97 : std::vector<Vector<const char>> native_ids_;
98 : std::vector<Vector<const char>> native_names_;
99 : std::vector<Vector<const char>> native_source_;
100 :
101 : DISALLOW_COPY_AND_ASSIGN(NativesStore);
102 : };
103 :
104 :
105 : template<NativeType type>
106 : class NativesHolder {
107 : public:
108 : static NativesStore* get() {
109 62764 : CHECK(holder_);
110 : return holder_;
111 : }
112 : static void set(NativesStore* store) {
113 61011 : CHECK(store);
114 61011 : holder_ = store;
115 : }
116 65574 : static bool empty() { return holder_ == nullptr; }
117 59886 : static void Dispose() {
118 59886 : delete holder_;
119 59886 : holder_ = nullptr;
120 59886 : }
121 :
122 : private:
123 : static NativesStore* holder_;
124 : };
125 :
126 : template <NativeType type>
127 : NativesStore* NativesHolder<type>::holder_ = nullptr;
128 :
129 : // The natives blob. Memory is owned by caller.
130 : static StartupData* natives_blob_ = nullptr;
131 :
132 : /**
133 : * Read the Natives blob, as previously set by SetNativesFromFile.
134 : */
135 122316 : void ReadNatives() {
136 187890 : if (natives_blob_ && NativesHolder<EXTRAS>::empty()) {
137 61011 : SnapshotByteSource bytes(natives_blob_->data, natives_blob_->raw_size);
138 61011 : NativesHolder<EXTRAS>::set(NativesStore::MakeFromScriptsSource(&bytes));
139 : DCHECK(!bytes.HasMore());
140 : }
141 122316 : }
142 :
143 :
144 : /**
145 : * Set the Natives (library sources) blob, as generated by js2c + the build
146 : * system.
147 : */
148 61001 : void SetNativesFromFile(StartupData* natives_blob) {
149 : DCHECK(!natives_blob_);
150 : DCHECK(natives_blob);
151 : DCHECK(natives_blob->data);
152 : DCHECK_GT(natives_blob->raw_size, 0);
153 :
154 61001 : natives_blob_ = natives_blob;
155 61001 : ReadNatives();
156 61001 : }
157 :
158 :
159 : /**
160 : * Release memory allocated by SetNativesFromFile.
161 : */
162 59886 : void DisposeNatives() {
163 59886 : NativesHolder<EXTRAS>::Dispose();
164 59886 : }
165 :
166 :
167 : // Implement NativesCollection<T> bsaed on NativesHolder + NativesStore.
168 : //
169 : // (The callers expect a purely static interface, since this is how the
170 : // natives are usually compiled in. Since we implement them based on
171 : // runtime content, we have to implement this indirection to offer
172 : // a static interface.)
173 : template<NativeType type>
174 220 : int NativesCollection<type>::GetBuiltinsCount() {
175 220 : return NativesHolder<type>::get()->GetBuiltinsCount();
176 : }
177 :
178 : template<NativeType type>
179 0 : int NativesCollection<type>::GetIndex(const char* name) {
180 0 : return NativesHolder<type>::get()->GetIndex(name);
181 : }
182 :
183 : template <NativeType type>
184 62434 : Vector<const char> NativesCollection<type>::GetScriptSource(int index) {
185 62434 : return NativesHolder<type>::get()->GetScriptSource(index);
186 : }
187 :
188 : template<NativeType type>
189 110 : Vector<const char> NativesCollection<type>::GetScriptName(int index) {
190 110 : return NativesHolder<type>::get()->GetScriptName(index);
191 : }
192 :
193 : template <NativeType type>
194 0 : Vector<const char> NativesCollection<type>::GetScriptsSource() {
195 0 : return NativesHolder<type>::get()->GetScriptsSource();
196 : }
197 :
198 :
199 : // Explicit template instantiations.
200 : #define INSTANTIATE_TEMPLATES(T) \
201 : template int NativesCollection<T>::GetBuiltinsCount(); \
202 : template int NativesCollection<T>::GetIndex(const char* name); \
203 : template Vector<const char> NativesCollection<T>::GetScriptSource(int i); \
204 : template Vector<const char> NativesCollection<T>::GetScriptName(int i); \
205 : template Vector<const char> NativesCollection<T>::GetScriptsSource();
206 : INSTANTIATE_TEMPLATES(EXTRAS)
207 : #undef INSTANTIATE_TEMPLATES
208 :
209 : } // namespace internal
210 122002 : } // namespace v8
|