// 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" #include "src/base/logging.h" #include "src/list.h" #include "src/list-inl.h" #include "src/snapshot-source-sink.h" #include "src/vector.h" #ifndef V8_USE_EXTERNAL_STARTUP_DATA #error natives-external.cc is used only for the external snapshot build. #endif // V8_USE_EXTERNAL_STARTUP_DATA 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: ~NativesStore() { for (int i = 0; i < native_names_.length(); i++) { native_names_[i].Dispose(); } } int GetBuiltinsCount() { return native_ids_.length(); } int GetDebuggerCount() { return debugger_count_; } Vector GetScriptSource(int index) { return native_source_[index]; } Vector GetScriptName(int index) { return native_names_[index]; } 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(strlen(id)) == native_id_length) && (strncmp(id, native_ids_[i].start(), native_id_length) == 0)) { return i; } } DCHECK(false); return -1; } Vector GetScriptsSource() { DCHECK(false); // Not implemented. return Vector(); } 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) {} Vector NameFromId(const byte* id, int id_length) { const char native[] = "native "; const char extension[] = ".js"; Vector name(Vector::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); return Vector::cast(name); } bool ReadNameAndContentPair(SnapshotByteSource* bytes) { const byte* id; int id_length; const byte* source; int source_length; bool success = bytes->GetBlob(&id, &id_length) && bytes->GetBlob(&source, &source_length); if (success) { Vector id_vector(reinterpret_cast(id), id_length); Vector source_vector( reinterpret_cast(source), source_length); native_ids_.Add(id_vector); native_source_.Add(source_vector); native_names_.Add(NameFromId(id, id_length)); } return success; } List > native_ids_; List > native_names_; List > native_source_; int debugger_count_; DISALLOW_COPY_AND_ASSIGN(NativesStore); }; template class NativesHolder { public: static NativesStore* get() { DCHECK(holder_); return holder_; } static void set(NativesStore* store) { DCHECK(store); holder_ = store; } private: static NativesStore* holder_; }; template NativesStore* NativesHolder::holder_ = NULL; /** * Read the Natives (library sources) blob, as generated by js2c + the build * system. */ void SetNativesFromFile(StartupData* natives_blob) { DCHECK(natives_blob); DCHECK(natives_blob->data); DCHECK(natives_blob->raw_size > 0); SnapshotByteSource bytes(natives_blob->data, natives_blob->raw_size); NativesHolder::set(NativesStore::MakeFromScriptsSource(&bytes)); NativesHolder::set(NativesStore::MakeFromScriptsSource(&bytes)); DCHECK(!bytes.HasMore()); } // Implement NativesCollection 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 int NativesCollection::GetBuiltinsCount() { return NativesHolder::get()->GetBuiltinsCount(); } template int NativesCollection::GetDebuggerCount() { return NativesHolder::get()->GetDebuggerCount(); } template int NativesCollection::GetIndex(const char* name) { return NativesHolder::get()->GetIndex(name); } template Vector NativesCollection::GetScriptSource(int index) { return NativesHolder::get()->GetScriptSource(index); } template Vector NativesCollection::GetScriptName(int index) { return NativesHolder::get()->GetScriptName(index); } template Vector NativesCollection::GetScriptsSource() { return NativesHolder::get()->GetScriptsSource(); } // The compiler can't 'see' all uses of the static methods and hence // my choice to elide them. This we'll explicitly instantiate these. template class NativesCollection; template class NativesCollection; } // namespace v8::internal } // namespace v8