1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_AST_AST_VALUE_FACTORY_H_ 29 #define V8_AST_AST_VALUE_FACTORY_H_ 30 31 #include <forward_list> 32 33 #include "src/base/hashmap.h" 34 #include "src/base/logging.h" 35 #include "src/common/globals.h" 36 #include "src/heap/factory.h" 37 #include "src/numbers/conversions.h" 38 39 // Ast(Raw|Cons)String and AstValueFactory are for storing strings and 40 // values independent of the V8 heap and internalizing them later. During 41 // parsing, they are created and stored outside the heap, in AstValueFactory. 42 // After parsing, the strings and values are internalized (moved into the V8 43 // heap). 44 namespace v8 { 45 namespace internal { 46 47 class Isolate; 48 49 class AstRawString final : public ZoneObject { 50 public: 51 static bool Compare(const AstRawString* a, const AstRawString* b); 52 IsEmpty()53 bool IsEmpty() const { return literal_bytes_.length() == 0; } length()54 int length() const { 55 return is_one_byte() ? literal_bytes_.length() 56 : literal_bytes_.length() / 2; 57 } 58 bool AsArrayIndex(uint32_t* index) const; 59 bool IsIntegerIndex() const; 60 V8_EXPORT_PRIVATE bool IsOneByteEqualTo(const char* data) const; 61 uint16_t FirstCharacter() const; 62 63 template <typename LocalIsolate> 64 void Internalize(LocalIsolate* isolate); 65 66 // Access the physical representation: is_one_byte()67 bool is_one_byte() const { return is_one_byte_; } byte_length()68 int byte_length() const { return literal_bytes_.length(); } raw_data()69 const unsigned char* raw_data() const { return literal_bytes_.begin(); } 70 IsPrivateName()71 bool IsPrivateName() const { return length() > 0 && FirstCharacter() == '#'; } 72 73 // For storing AstRawStrings in a hash map. hash_field()74 uint32_t hash_field() const { return hash_field_; } Hash()75 uint32_t Hash() const { return hash_field_ >> Name::kHashShift; } 76 77 // This function can be called after internalizing. string()78 V8_INLINE Handle<String> string() const { 79 DCHECK(has_string_); 80 return string_; 81 } 82 83 private: 84 friend class AstRawStringInternalizationKey; 85 friend class AstStringConstants; 86 friend class AstValueFactory; 87 friend Zone; 88 89 // Members accessed only by the AstValueFactory & related classes: AstRawString(bool is_one_byte,const Vector<const byte> & literal_bytes,uint32_t hash_field)90 AstRawString(bool is_one_byte, const Vector<const byte>& literal_bytes, 91 uint32_t hash_field) 92 : next_(nullptr), 93 literal_bytes_(literal_bytes), 94 hash_field_(hash_field), 95 is_one_byte_(is_one_byte) {} next()96 AstRawString* next() { 97 DCHECK(!has_string_); 98 return next_; 99 } next_location()100 AstRawString** next_location() { 101 DCHECK(!has_string_); 102 return &next_; 103 } 104 set_string(Handle<String> string)105 void set_string(Handle<String> string) { 106 DCHECK(!string.is_null()); 107 DCHECK(!has_string_); 108 string_ = string; 109 #ifdef DEBUG 110 has_string_ = true; 111 #endif 112 } 113 114 union { 115 AstRawString* next_; 116 Handle<String> string_; 117 }; 118 119 Vector<const byte> literal_bytes_; // Memory owned by Zone. 120 uint32_t hash_field_; 121 bool is_one_byte_; 122 #ifdef DEBUG 123 // (Debug-only:) Verify the object life-cylce: Some functions may only be 124 // called after internalization (that is, after a v8::internal::String has 125 // been set); some only before. 126 bool has_string_ = false; 127 #endif 128 }; 129 130 extern template EXPORT_TEMPLATE_DECLARE( 131 V8_EXPORT_PRIVATE) void AstRawString::Internalize(Isolate* isolate); 132 extern template EXPORT_TEMPLATE_DECLARE( 133 V8_EXPORT_PRIVATE) void AstRawString::Internalize(LocalIsolate* isolate); 134 135 class AstConsString final : public ZoneObject { 136 public: AddString(Zone * zone,const AstRawString * s)137 AstConsString* AddString(Zone* zone, const AstRawString* s) { 138 if (s->IsEmpty()) return this; 139 if (!IsEmpty()) { 140 // We're putting the new string to the head of the list, meaning 141 // the string segments will be in reverse order. 142 Segment* tmp = zone->New<Segment>(segment_); 143 segment_.next = tmp; 144 } 145 segment_.string = s; 146 return this; 147 } 148 IsEmpty()149 bool IsEmpty() const { 150 DCHECK_IMPLIES(segment_.string == nullptr, segment_.next == nullptr); 151 DCHECK_IMPLIES(segment_.string != nullptr, !segment_.string->IsEmpty()); 152 return segment_.string == nullptr; 153 } 154 155 template <typename LocalIsolate> GetString(LocalIsolate * isolate)156 Handle<String> GetString(LocalIsolate* isolate) { 157 if (string_.is_null()) { 158 string_ = Allocate(isolate); 159 } 160 return string_; 161 } 162 163 template <typename LocalIsolate> 164 EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) 165 Handle<String> AllocateFlat(LocalIsolate* isolate) const; 166 167 std::forward_list<const AstRawString*> ToRawStrings() const; 168 169 private: 170 friend class AstValueFactory; 171 friend Zone; 172 AstConsString()173 AstConsString() : string_(), segment_({nullptr, nullptr}) {} 174 175 template <typename LocalIsolate> 176 EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) 177 Handle<String> Allocate(LocalIsolate* isolate) const; 178 179 Handle<String> string_; 180 181 // A linked list of AstRawStrings of the contents of this AstConsString. 182 // This list has several properties: 183 // 184 // * For empty strings the string pointer is null, 185 // * Appended raw strings are added to the head of the list, so they are in 186 // reverse order 187 struct Segment { 188 const AstRawString* string; 189 AstConsString::Segment* next; 190 }; 191 Segment segment_; 192 }; 193 194 enum class AstSymbol : uint8_t { kHomeObjectSymbol }; 195 196 class AstBigInt { 197 public: 198 // |bigint| must be a NUL-terminated string of ASCII characters 199 // representing a BigInt (suitable for passing to BigIntLiteral() 200 // from conversions.h). AstBigInt(const char * bigint)201 explicit AstBigInt(const char* bigint) : bigint_(bigint) {} 202 c_str()203 const char* c_str() const { return bigint_; } 204 205 private: 206 const char* bigint_; 207 }; 208 209 struct AstRawStringMapMatcher { operatorAstRawStringMapMatcher210 bool operator()(uint32_t hash1, uint32_t hash2, 211 const AstRawString* lookup_key, 212 const AstRawString* entry_key) const { 213 return hash1 == hash2 && AstRawString::Compare(lookup_key, entry_key); 214 } 215 }; 216 217 using AstRawStringMap = 218 base::TemplateHashMapImpl<const AstRawString*, base::NoHashMapValue, 219 AstRawStringMapMatcher, 220 base::DefaultAllocationPolicy>; 221 222 // For generating constants. 223 #define AST_STRING_CONSTANTS(F) \ 224 F(anonymous, "anonymous") \ 225 F(anonymous_function, "(anonymous function)") \ 226 F(arguments, "arguments") \ 227 F(as, "as") \ 228 F(assert, "assert") \ 229 F(async, "async") \ 230 F(await, "await") \ 231 F(bigint, "bigint") \ 232 F(boolean, "boolean") \ 233 F(computed, "<computed>") \ 234 F(dot_brand, ".brand") \ 235 F(constructor, "constructor") \ 236 F(default, "default") \ 237 F(done, "done") \ 238 F(dot, ".") \ 239 F(dot_default, ".default") \ 240 F(dot_for, ".for") \ 241 F(dot_generator_object, ".generator_object") \ 242 F(dot_result, ".result") \ 243 F(dot_repl_result, ".repl_result") \ 244 F(dot_switch_tag, ".switch_tag") \ 245 F(dot_catch, ".catch") \ 246 F(empty, "") \ 247 F(eval, "eval") \ 248 F(from, "from") \ 249 F(function, "function") \ 250 F(get, "get") \ 251 F(get_space, "get ") \ 252 F(length, "length") \ 253 F(let, "let") \ 254 F(meta, "meta") \ 255 F(name, "name") \ 256 F(native, "native") \ 257 F(new_target, ".new.target") \ 258 F(next, "next") \ 259 F(number, "number") \ 260 F(object, "object") \ 261 F(of, "of") \ 262 F(private_constructor, "#constructor") \ 263 F(proto, "__proto__") \ 264 F(prototype, "prototype") \ 265 F(return, "return") \ 266 F(set, "set") \ 267 F(set_space, "set ") \ 268 F(string, "string") \ 269 F(symbol, "symbol") \ 270 F(target, "target") \ 271 F(this, "this") \ 272 F(this_function, ".this_function") \ 273 F(throw, "throw") \ 274 F(undefined, "undefined") \ 275 F(value, "value") 276 277 class AstStringConstants final { 278 public: 279 AstStringConstants(Isolate* isolate, uint64_t hash_seed); 280 281 #define F(name, str) \ 282 const AstRawString* name##_string() const { return name##_string_; } AST_STRING_CONSTANTS(F)283 AST_STRING_CONSTANTS(F) 284 #undef F 285 286 uint64_t hash_seed() const { return hash_seed_; } string_table()287 const AstRawStringMap* string_table() const { return &string_table_; } 288 289 private: 290 Zone zone_; 291 AstRawStringMap string_table_; 292 uint64_t hash_seed_; 293 294 #define F(name, str) AstRawString* name##_string_; 295 AST_STRING_CONSTANTS(F) 296 #undef F 297 298 DISALLOW_COPY_AND_ASSIGN(AstStringConstants); 299 }; 300 301 class AstValueFactory { 302 public: AstValueFactory(Zone * zone,const AstStringConstants * string_constants,uint64_t hash_seed)303 AstValueFactory(Zone* zone, const AstStringConstants* string_constants, 304 uint64_t hash_seed) 305 : string_table_(string_constants->string_table()), 306 strings_(nullptr), 307 strings_end_(&strings_), 308 string_constants_(string_constants), 309 empty_cons_string_(nullptr), 310 zone_(zone), 311 hash_seed_(hash_seed) { 312 DCHECK_NOT_NULL(zone_); 313 DCHECK_EQ(hash_seed, string_constants->hash_seed()); 314 std::fill(one_character_strings_, 315 one_character_strings_ + arraysize(one_character_strings_), 316 nullptr); 317 empty_cons_string_ = NewConsString(); 318 } 319 zone()320 Zone* zone() const { 321 DCHECK_NOT_NULL(zone_); 322 return zone_; 323 } 324 GetOneByteString(Vector<const uint8_t> literal)325 const AstRawString* GetOneByteString(Vector<const uint8_t> literal) { 326 return GetOneByteStringInternal(literal); 327 } GetOneByteString(const char * string)328 const AstRawString* GetOneByteString(const char* string) { 329 return GetOneByteString(OneByteVector(string)); 330 } GetTwoByteString(Vector<const uint16_t> literal)331 const AstRawString* GetTwoByteString(Vector<const uint16_t> literal) { 332 return GetTwoByteStringInternal(literal); 333 } 334 const AstRawString* GetString(Handle<String> literal); 335 336 // Clones an AstRawString from another ast value factory, adding it to this 337 // factory and returning the clone. 338 const AstRawString* CloneFromOtherFactory(const AstRawString* raw_string); 339 340 V8_EXPORT_PRIVATE AstConsString* NewConsString(); 341 V8_EXPORT_PRIVATE AstConsString* NewConsString(const AstRawString* str); 342 V8_EXPORT_PRIVATE AstConsString* NewConsString(const AstRawString* str1, 343 const AstRawString* str2); 344 345 // Internalize all the strings in the factory, and prevent any more from being 346 // allocated. Multiple calls to Internalize are allowed, for simplicity, where 347 // subsequent calls are a no-op. 348 template <typename LocalIsolate> 349 void Internalize(LocalIsolate* isolate); 350 351 #define F(name, str) \ 352 const AstRawString* name##_string() const { \ 353 return string_constants_->name##_string(); \ 354 } AST_STRING_CONSTANTS(F)355 AST_STRING_CONSTANTS(F) 356 #undef F 357 AstConsString* empty_cons_string() const { return empty_cons_string_; } 358 359 private: AddString(AstRawString * string)360 AstRawString* AddString(AstRawString* string) { 361 *strings_end_ = string; 362 strings_end_ = string->next_location(); 363 return string; 364 } ResetStrings()365 void ResetStrings() { 366 strings_ = nullptr; 367 strings_end_ = &strings_; 368 } 369 V8_EXPORT_PRIVATE const AstRawString* GetOneByteStringInternal( 370 Vector<const uint8_t> literal); 371 const AstRawString* GetTwoByteStringInternal(Vector<const uint16_t> literal); 372 const AstRawString* GetString(uint32_t hash, bool is_one_byte, 373 Vector<const byte> literal_bytes); 374 375 // All strings are copied here. 376 AstRawStringMap string_table_; 377 378 AstRawString* strings_; 379 AstRawString** strings_end_; 380 381 // Holds constant string values which are shared across the isolate. 382 const AstStringConstants* string_constants_; 383 384 AstConsString* empty_cons_string_; 385 386 // Caches one character lowercase strings (for minified code). 387 static const int kMaxOneCharStringValue = 128; 388 const AstRawString* one_character_strings_[kMaxOneCharStringValue]; 389 390 Zone* zone_; 391 392 uint64_t hash_seed_; 393 }; 394 395 extern template EXPORT_TEMPLATE_DECLARE( 396 V8_EXPORT_PRIVATE) void AstValueFactory::Internalize<Isolate>(Isolate* 397 isolate); 398 399 extern template EXPORT_TEMPLATE_DECLARE( 400 V8_EXPORT_PRIVATE) void AstValueFactory:: 401 Internalize<LocalIsolate>(LocalIsolate* isolate); 402 403 } // namespace internal 404 } // namespace v8 405 406 #endif // V8_AST_AST_VALUE_FACTORY_H_ 407