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