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