natives-external.cc 6.92 KB
Newer Older
1 2 3 4
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "src/snapshot/natives.h"
6

7
#include "src/base/logging.h"
8
#include "src/snapshot/snapshot-source-sink.h"
9 10
#include "src/vector.h"

11 12 13 14 15
#ifndef V8_USE_EXTERNAL_STARTUP_DATA
#error natives-external.cc is used only for the external snapshot build.
#endif  // V8_USE_EXTERNAL_STARTUP_DATA


16 17 18 19 20 21 22 23 24 25 26 27 28
namespace v8 {
namespace internal {


/**
 * NativesStore stores the 'native' (builtin) JS libraries.
 *
 * NativesStore needs to be initialized before using V8, usually by the
 * embedder calling v8::SetNativesDataBlob, which calls SetNativesFromFile
 * below.
 */
class NativesStore {
 public:
29
  ~NativesStore() {
30
    for (size_t i = 0; i < native_names_.size(); i++) {
31 32 33
      native_names_[i].Dispose();
    }
  }
34

35
  int GetBuiltinsCount() { return static_cast<int>(native_ids_.size()); }
36
  int GetDebuggerCount() { return debugger_count_; }
37

38
  Vector<const char> GetScriptSource(int index) {
39 40 41
    return native_source_[index];
  }

42 43
  Vector<const char> GetScriptName(int index) { return native_names_[index]; }

44
  int GetIndex(const char* id) {
45
    for (int i = 0; i < static_cast<int>(native_ids_.size()); ++i) {
46 47 48
      int native_id_length = native_ids_[i].length();
      if ((static_cast<int>(strlen(id)) == native_id_length) &&
          (strncmp(id, native_ids_[i].start(), native_id_length) == 0)) {
49 50 51
        return i;
      }
    }
52
    UNREACHABLE();
53 54
  }

55
  Vector<const char> GetScriptsSource() {
56
    UNREACHABLE();  // Not implemented.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
  }

  static NativesStore* MakeFromScriptsSource(SnapshotByteSource* source) {
    NativesStore* store = new NativesStore;

    // We expect the libraries in the following format:
    //   int: # of debugger sources.
    //   2N blobs: N pairs of source name + actual source.
    //   then, repeat for non-debugger sources.
    int debugger_count = source->GetInt();
    for (int i = 0; i < debugger_count; ++i)
      store->ReadNameAndContentPair(source);
    int library_count = source->GetInt();
    for (int i = 0; i < library_count; ++i)
      store->ReadNameAndContentPair(source);

    store->debugger_count_ = debugger_count;
    return store;
  }

 private:
  NativesStore() : debugger_count_(0) {}

80
  Vector<const char> NameFromId(const byte* id, int id_length) {
81 82 83 84 85 86 87 88
    const char native[] = "native ";
    const char extension[] = ".js";
    Vector<char> name(Vector<char>::New(id_length + sizeof(native) - 1 +
                                        sizeof(extension) - 1));
    memcpy(name.start(), native, sizeof(native) - 1);
    memcpy(name.start() + sizeof(native) - 1, id, id_length);
    memcpy(name.start() + sizeof(native) - 1 + id_length, extension,
           sizeof(extension) - 1);
89 90 91
    return Vector<const char>::cast(name);
  }

92
  void ReadNameAndContentPair(SnapshotByteSource* bytes) {
93
    const byte* id;
94
    const byte* source;
95 96
    int id_length = bytes->GetBlob(&id);
    int source_length = bytes->GetBlob(&source);
97 98 99 100
    native_ids_.emplace_back(reinterpret_cast<const char*>(id), id_length);
    native_source_.emplace_back(reinterpret_cast<const char*>(source),
                                source_length);
    native_names_.push_back(NameFromId(id, id_length));
101 102
  }

103 104 105
  std::vector<Vector<const char>> native_ids_;
  std::vector<Vector<const char>> native_names_;
  std::vector<Vector<const char>> native_source_;
106 107 108 109 110 111 112 113 114 115
  int debugger_count_;

  DISALLOW_COPY_AND_ASSIGN(NativesStore);
};


template<NativeType type>
class NativesHolder {
 public:
  static NativesStore* get() {
116
    CHECK(holder_);
117 118 119
    return holder_;
  }
  static void set(NativesStore* store) {
120
    CHECK(store);
121 122
    holder_ = store;
  }
123
  static bool empty() { return holder_ == nullptr; }
124 125
  static void Dispose() {
    delete holder_;
126
    holder_ = nullptr;
127
  }
128 129 130 131 132

 private:
  static NativesStore* holder_;
};

133 134
template <NativeType type>
NativesStore* NativesHolder<type>::holder_ = nullptr;
135

136
// The natives blob. Memory is owned by caller.
137
static StartupData* natives_blob_ = nullptr;
138 139 140 141 142 143 144 145

/**
 * Read the Natives blob, as previously set by SetNativesFromFile.
 */
void ReadNatives() {
  if (natives_blob_ && NativesHolder<CORE>::empty()) {
    SnapshotByteSource bytes(natives_blob_->data, natives_blob_->raw_size);
    NativesHolder<CORE>::set(NativesStore::MakeFromScriptsSource(&bytes));
146
    NativesHolder<EXTRAS>::set(NativesStore::MakeFromScriptsSource(&bytes));
147 148
    NativesHolder<EXPERIMENTAL_EXTRAS>::set(
        NativesStore::MakeFromScriptsSource(&bytes));
149 150 151 152 153
    DCHECK(!bytes.HasMore());
  }
}


154
/**
155
 * Set the Natives (library sources) blob, as generated by js2c + the build
156 157 158
 * system.
 */
void SetNativesFromFile(StartupData* natives_blob) {
159
  DCHECK(!natives_blob_);
160 161
  DCHECK(natives_blob);
  DCHECK(natives_blob->data);
162
  DCHECK_GT(natives_blob->raw_size, 0);
163

164 165
  natives_blob_ = natives_blob;
  ReadNatives();
166 167 168
}


169 170 171 172 173
/**
 * Release memory allocated by SetNativesFromFile.
 */
void DisposeNatives() {
  NativesHolder<CORE>::Dispose();
174
  NativesHolder<EXTRAS>::Dispose();
175
  NativesHolder<EXPERIMENTAL_EXTRAS>::Dispose();
176 177 178
}


179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
// Implement NativesCollection<T> bsaed on NativesHolder + NativesStore.
//
// (The callers expect a purely static interface, since this is how the
//  natives are usually compiled in. Since we implement them based on
//  runtime content, we have to implement this indirection to offer
//  a static interface.)
template<NativeType type>
int NativesCollection<type>::GetBuiltinsCount() {
  return NativesHolder<type>::get()->GetBuiltinsCount();
}

template<NativeType type>
int NativesCollection<type>::GetDebuggerCount() {
  return NativesHolder<type>::get()->GetDebuggerCount();
}

template<NativeType type>
int NativesCollection<type>::GetIndex(const char* name) {
  return NativesHolder<type>::get()->GetIndex(name);
}

200 201 202
template <NativeType type>
Vector<const char> NativesCollection<type>::GetScriptSource(int index) {
  return NativesHolder<type>::get()->GetScriptSource(index);
203 204 205 206 207 208 209
}

template<NativeType type>
Vector<const char> NativesCollection<type>::GetScriptName(int index) {
  return NativesHolder<type>::get()->GetScriptName(index);
}

210 211
template <NativeType type>
Vector<const char> NativesCollection<type>::GetScriptsSource() {
212 213 214 215
  return NativesHolder<type>::get()->GetScriptsSource();
}


216 217 218 219 220 221 222 223 224 225
// Explicit template instantiations.
#define INSTANTIATE_TEMPLATES(T)                                            \
  template int NativesCollection<T>::GetBuiltinsCount();                    \
  template int NativesCollection<T>::GetDebuggerCount();                    \
  template int NativesCollection<T>::GetIndex(const char* name);            \
  template Vector<const char> NativesCollection<T>::GetScriptSource(int i); \
  template Vector<const char> NativesCollection<T>::GetScriptName(int i);   \
  template Vector<const char> NativesCollection<T>::GetScriptsSource();
INSTANTIATE_TEMPLATES(CORE)
INSTANTIATE_TEMPLATES(EXTRAS)
226
INSTANTIATE_TEMPLATES(EXPERIMENTAL_EXTRAS)
227 228
#undef INSTANTIATE_TEMPLATES

229
}  // namespace internal
230
}  // namespace v8