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
13namespace v8 {
14namespace 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 */
24class NativesStore {
25 public:
26  ~NativesStore() {}
27
28  int GetBuiltinsCount() { return native_names_.length(); }
29  int GetDebuggerCount() { return debugger_count_; }
30  Vector<const char> GetScriptName(int index) { return native_names_[index]; }
31  Vector<const char> GetRawScriptSource(int index) {
32    return native_source_[index];
33  }
34
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
47  int GetRawScriptsSize() {
48    DCHECK(false);  // Used for compression. Doesn't really make sense here.
49    return 0;
50  }
51
52  Vector<const byte> GetScriptsSource() {
53    DCHECK(false);  // Used for compression. Doesn't really make sense here.
54    return Vector<const byte>();
55  }
56
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:
76  NativesStore() : debugger_count_(0) {}
77
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
104template<NativeType type>
105class NativesHolder {
106 public:
107  static NativesStore* get() {
108    DCHECK(holder_);
109    return holder_;
110  }
111  static void set(NativesStore* store) {
112    DCHECK(store);
113    holder_ = store;
114  }
115
116 private:
117  static NativesStore* holder_;
118};
119
120template<NativeType type>
121NativesStore* NativesHolder<type>::holder_ = NULL;
122
123
124/**
125 * Read the Natives (library sources) blob, as generated by js2c + the build
126 * system.
127 */
128void 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.)
148template<NativeType type>
149int NativesCollection<type>::GetBuiltinsCount() {
150  return NativesHolder<type>::get()->GetBuiltinsCount();
151}
152
153template<NativeType type>
154int NativesCollection<type>::GetDebuggerCount() {
155  return NativesHolder<type>::get()->GetDebuggerCount();
156}
157
158template<NativeType type>
159int NativesCollection<type>::GetIndex(const char* name) {
160  return NativesHolder<type>::get()->GetIndex(name);
161}
162
163template<NativeType type>
164int NativesCollection<type>::GetRawScriptsSize() {
165  return NativesHolder<type>::get()->GetRawScriptsSize();
166}
167
168template<NativeType type>
169Vector<const char> NativesCollection<type>::GetRawScriptSource(int index) {
170  return NativesHolder<type>::get()->GetRawScriptSource(index);
171}
172
173template<NativeType type>
174Vector<const char> NativesCollection<type>::GetScriptName(int index) {
175  return NativesHolder<type>::get()->GetScriptName(index);
176}
177
178template<NativeType type>
179Vector<const byte> NativesCollection<type>::GetScriptsSource() {
180  return NativesHolder<type>::get()->GetScriptsSource();
181}
182
183template<NativeType type>
184void 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.
192template class NativesCollection<CORE>;
193template class NativesCollection<EXPERIMENTAL>;
194template class NativesCollection<D8>;
195template class NativesCollection<TEST>;
196
197}  // namespace v8::internal
198}  // namespace v8
199