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: 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 104 template<NativeType type> 105 class 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 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 */ 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> 149 int NativesCollection<type>::GetBuiltinsCount() { 150 return NativesHolder<type>::get()->GetBuiltinsCount(); 151 } 152 153 template<NativeType type> 154 int NativesCollection<type>::GetDebuggerCount() { 155 return NativesHolder<type>::get()->GetDebuggerCount(); 156 } 157 158 template<NativeType type> 159 int NativesCollection<type>::GetIndex(const char* name) { 160 return NativesHolder<type>::get()->GetIndex(name); 161 } 162 163 template<NativeType type> 164 int NativesCollection<type>::GetRawScriptsSize() { 165 return NativesHolder<type>::get()->GetRawScriptsSize(); 166 } 167 168 template<NativeType type> 169 Vector<const char> NativesCollection<type>::GetRawScriptSource(int index) { 170 return NativesHolder<type>::get()->GetRawScriptSource(index); 171 } 172 173 template<NativeType type> 174 Vector<const char> NativesCollection<type>::GetScriptName(int index) { 175 return NativesHolder<type>::get()->GetScriptName(index); 176 } 177 178 template<NativeType type> 179 Vector<const byte> NativesCollection<type>::GetScriptsSource() { 180 return NativesHolder<type>::get()->GetScriptsSource(); 181 } 182 183 template<NativeType type> 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