natives-external.cc 5.93 KB
Newer Older
1 2 3 4 5 6
// 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.

#include "src/natives.h"

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

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


18 19 20 21 22 23 24 25 26 27 28 29 30
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:
31 32 33 34 35
  ~NativesStore() {
    for (int i = 0; i < native_names_.length(); i++) {
      native_names_[i].Dispose();
    }
  }
36

37
  int GetBuiltinsCount() { return native_ids_.length(); }
38
  int GetDebuggerCount() { return debugger_count_; }
39

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

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

46 47 48 49 50
  int GetIndex(const char* id) {
    for (int i = 0; i < native_ids_.length(); ++i) {
      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)) {
51 52 53
        return i;
      }
    }
54
    DCHECK(false);
55 56 57
    return -1;
  }

58 59 60
  Vector<const char> GetScriptsSource() {
    DCHECK(false);  // Not implemented.
    return Vector<const char>();
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
  }

  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) {}

84
  Vector<const char> NameFromId(const byte* id, int id_length) {
85 86 87 88 89 90 91 92
    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);
93 94 95
    return Vector<const char>::cast(name);
  }

96
  bool ReadNameAndContentPair(SnapshotByteSource* bytes) {
97 98
    const byte* id;
    int id_length;
99 100
    const byte* source;
    int source_length;
101
    bool success = bytes->GetBlob(&id, &id_length) &&
102 103
                   bytes->GetBlob(&source, &source_length);
    if (success) {
104 105
      Vector<const char> id_vector(reinterpret_cast<const char*>(id),
                                   id_length);
106 107
      Vector<const char> source_vector(
          reinterpret_cast<const char*>(source), source_length);
108
      native_ids_.Add(id_vector);
109
      native_source_.Add(source_vector);
110
      native_names_.Add(NameFromId(id, id_length));
111 112 113 114
    }
    return success;
  }

115
  List<Vector<const char> > native_ids_;
116 117 118 119 120 121 122 123 124 125 126 127
  List<Vector<const char> > native_names_;
  List<Vector<const char> > native_source_;
  int debugger_count_;

  DISALLOW_COPY_AND_ASSIGN(NativesStore);
};


template<NativeType type>
class NativesHolder {
 public:
  static NativesStore* get() {
128
    DCHECK(holder_);
129 130 131
    return holder_;
  }
  static void set(NativesStore* store) {
132
    DCHECK(store);
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
    holder_ = store;
  }

 private:
  static NativesStore* holder_;
};

template<NativeType type>
NativesStore* NativesHolder<type>::holder_ = NULL;


/**
 * Read the Natives (library sources) blob, as generated by js2c + the build
 * system.
 */
void SetNativesFromFile(StartupData* natives_blob) {
149 150 151
  DCHECK(natives_blob);
  DCHECK(natives_blob->data);
  DCHECK(natives_blob->raw_size > 0);
152

153
  SnapshotByteSource bytes(natives_blob->data, natives_blob->raw_size);
154 155
  NativesHolder<CORE>::set(NativesStore::MakeFromScriptsSource(&bytes));
  NativesHolder<EXPERIMENTAL>::set(NativesStore::MakeFromScriptsSource(&bytes));
156
  DCHECK(!bytes.HasMore());
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
}


// 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);
}

181 182 183
template <NativeType type>
Vector<const char> NativesCollection<type>::GetScriptSource(int index) {
  return NativesHolder<type>::get()->GetScriptSource(index);
184 185 186 187 188 189 190
}

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

191 192
template <NativeType type>
Vector<const char> NativesCollection<type>::GetScriptsSource() {
193 194 195 196 197
  return NativesHolder<type>::get()->GetScriptsSource();
}


// The compiler can't 'see' all uses of the static methods and hence
198
// my choice to elide them. This we'll explicitly instantiate these.
199 200 201 202 203
template class NativesCollection<CORE>;
template class NativesCollection<EXPERIMENTAL>;

}  // namespace v8::internal
}  // namespace v8