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 Equal(const AstRawString* lhs, const AstRawString* rhs); 52 53 // Returns 0 if lhs is equal to rhs. 54 // Returns <0 if lhs is less than rhs in code point order. 55 // Returns >0 if lhs is greater than than rhs in code point order. 56 static int Compare(const AstRawString* lhs, const AstRawString* rhs); 57 IsEmpty()58 bool IsEmpty() const { return literal_bytes_.length() == 0; } length()59 int length() const { 60 return is_one_byte() ? literal_bytes_.length() 61 : literal_bytes_.length() / 2; 62 } 63 bool AsArrayIndex(uint32_t* index) const; 64 bool IsIntegerIndex() const; 65 V8_EXPORT_PRIVATE bool IsOneByteEqualTo(const char* data) const; 66 uint16_t FirstCharacter() const; 67 68 template <typename IsolateT> 69 void Internalize(IsolateT* isolate); 70 71 // Access the physical representation: is_one_byte()72 bool is_one_byte() const { return is_one_byte_; } byte_length()73 int byte_length() const { return literal_bytes_.length(); } raw_data()74 const unsigned char* raw_data() const { return literal_bytes_.begin(); } 75 IsPrivateName()76 bool IsPrivateName() const { return length() > 0 && FirstCharacter() == '#'; } 77 78 // For storing AstRawStrings in a hash map. raw_hash_field()79 uint32_t raw_hash_field() const { return raw_hash_field_; } Hash()80 uint32_t Hash() const { 81 // Hash field must be computed. 82 DCHECK_EQ(raw_hash_field_ & Name::kHashNotComputedMask, 0); 83 return Name::HashBits::decode(raw_hash_field_); 84 } 85 86 // This function can be called after internalizing. string()87 V8_INLINE Handle<String> string() const { 88 DCHECK(has_string_); 89 return string_; 90 } 91 92 private: 93 friend class AstRawStringInternalizationKey; 94 friend class AstStringConstants; 95 friend class AstValueFactory; 96 friend Zone; 97 98 // Members accessed only by the AstValueFactory & related classes: AstRawString(bool is_one_byte,const base::Vector<const byte> & literal_bytes,uint32_t raw_hash_field)99 AstRawString(bool is_one_byte, const base::Vector<const byte>& literal_bytes, 100 uint32_t raw_hash_field) 101 : next_(nullptr), 102 literal_bytes_(literal_bytes), 103 raw_hash_field_(raw_hash_field), 104 is_one_byte_(is_one_byte) {} next()105 AstRawString* next() { 106 DCHECK(!has_string_); 107 return next_; 108 } next_location()109 AstRawString** next_location() { 110 DCHECK(!has_string_); 111 return &next_; 112 } 113 set_string(Handle<String> string)114 void set_string(Handle<String> string) { 115 DCHECK(!string.is_null()); 116 DCHECK(!has_string_); 117 string_ = string; 118 #ifdef DEBUG 119 has_string_ = true; 120 #endif 121 } 122 123 union { 124 AstRawString* next_; 125 Handle<String> string_; 126 }; 127 128 base::Vector<const byte> literal_bytes_; // Memory owned by Zone. 129 uint32_t raw_hash_field_; 130 bool is_one_byte_; 131 #ifdef DEBUG 132 // (Debug-only:) Verify the object life-cylce: Some functions may only be 133 // called after internalization (that is, after a v8::internal::String has 134 // been set); some only before. 135 bool has_string_ = false; 136 #endif 137 }; 138 139 extern template EXPORT_TEMPLATE_DECLARE( 140 V8_EXPORT_PRIVATE) void AstRawString::Internalize(Isolate* isolate); 141 extern template EXPORT_TEMPLATE_DECLARE( 142 V8_EXPORT_PRIVATE) void AstRawString::Internalize(LocalIsolate* isolate); 143 144 class AstConsString final : public ZoneObject { 145 public: AddString(Zone * zone,const AstRawString * s)146 AstConsString* AddString(Zone* zone, const AstRawString* s) { 147 if (s->IsEmpty()) return this; 148 if (!IsEmpty()) { 149 // We're putting the new string to the head of the list, meaning 150 // the string segments will be in reverse order. 151 Segment* tmp = zone->New<Segment>(segment_); 152 segment_.next = tmp; 153 } 154 segment_.string = s; 155 return this; 156 } 157 IsEmpty()158 bool IsEmpty() const { 159 DCHECK_IMPLIES(segment_.string == nullptr, segment_.next == nullptr); 160 DCHECK_IMPLIES(segment_.string != nullptr, !segment_.string->IsEmpty()); 161 return segment_.string == nullptr; 162 } 163 164 template <typename IsolateT> GetString(IsolateT * isolate)165 Handle<String> GetString(IsolateT* isolate) { 166 if (string_.is_null()) { 167 string_ = Allocate(isolate); 168 } 169 return string_; 170 } 171 172 template <typename IsolateT> 173 EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) 174 Handle<String> AllocateFlat(IsolateT* isolate) const; 175 176 std::forward_list<const AstRawString*> ToRawStrings() const; 177 178 private: 179 friend class AstValueFactory; 180 friend Zone; 181 AstConsString()182 AstConsString() : string_(), segment_({nullptr, nullptr}) {} 183 184 template <typename IsolateT> 185 EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) 186 Handle<String> Allocate(IsolateT* isolate) const; 187 188 Handle<String> string_; 189 190 // A linked list of AstRawStrings of the contents of this AstConsString. 191 // This list has several properties: 192 // 193 // * For empty strings the string pointer is null, 194 // * Appended raw strings are added to the head of the list, so they are in 195 // reverse order 196 struct Segment { 197 const AstRawString* string; 198 AstConsString::Segment* next; 199 }; 200 Segment segment_; 201 }; 202 203 class AstBigInt { 204 public: 205 // |bigint| must be a NUL-terminated string of ASCII characters 206 // representing a BigInt (suitable for passing to BigIntLiteral() 207 // from conversions.h). AstBigInt(const char * bigint)208 explicit AstBigInt(const char* bigint) : bigint_(bigint) {} 209 c_str()210 const char* c_str() const { return bigint_; } 211 212 private: 213 const char* bigint_; 214 }; 215 216 struct AstRawStringMapMatcher { operatorAstRawStringMapMatcher217 bool operator()(uint32_t hash1, uint32_t hash2, 218 const AstRawString* lookup_key, 219 const AstRawString* entry_key) const { 220 return hash1 == hash2 && AstRawString::Equal(lookup_key, entry_key); 221 } 222 }; 223 224 using AstRawStringMap = 225 base::TemplateHashMapImpl<const AstRawString*, base::NoHashMapValue, 226 AstRawStringMapMatcher, 227 base::DefaultAllocationPolicy>; 228 229 // For generating constants. 230 #define AST_STRING_CONSTANTS(F) \ 231 F(anonymous, "anonymous") \ 232 F(anonymous_function, "(anonymous function)") \ 233 F(arguments, "arguments") \ 234 F(as, "as") \ 235 F(assert, "assert") \ 236 F(async, "async") \ 237 F(await, "await") \ 238 F(bigint, "bigint") \ 239 F(boolean, "boolean") \ 240 F(computed, "<computed>") \ 241 F(dot_brand, ".brand") \ 242 F(constructor, "constructor") \ 243 F(default, "default") \ 244 F(done, "done") \ 245 F(dot, ".") \ 246 F(dot_default, ".default") \ 247 F(dot_for, ".for") \ 248 F(dot_generator_object, ".generator_object") \ 249 F(dot_home_object, ".home_object") \ 250 F(dot_result, ".result") \ 251 F(dot_repl_result, ".repl_result") \ 252 F(dot_static_home_object, ".static_home_object") \ 253 F(dot_switch_tag, ".switch_tag") \ 254 F(dot_catch, ".catch") \ 255 F(empty, "") \ 256 F(eval, "eval") \ 257 F(from, "from") \ 258 F(function, "function") \ 259 F(get, "get") \ 260 F(get_space, "get ") \ 261 F(length, "length") \ 262 F(let, "let") \ 263 F(meta, "meta") \ 264 F(name, "name") \ 265 F(native, "native") \ 266 F(new_target, ".new.target") \ 267 F(next, "next") \ 268 F(number, "number") \ 269 F(object, "object") \ 270 F(of, "of") \ 271 F(private_constructor, "#constructor") \ 272 F(proto, "__proto__") \ 273 F(prototype, "prototype") \ 274 F(return, "return") \ 275 F(set, "set") \ 276 F(set_space, "set ") \ 277 F(string, "string") \ 278 F(symbol, "symbol") \ 279 F(target, "target") \ 280 F(this, "this") \ 281 F(this_function, ".this_function") \ 282 F(throw, "throw") \ 283 F(undefined, "undefined") \ 284 F(value, "value") 285 286 class AstStringConstants final { 287 public: 288 AstStringConstants(Isolate* isolate, uint64_t hash_seed); 289 AstStringConstants(const AstStringConstants&) = delete; 290 AstStringConstants& operator=(const AstStringConstants&) = delete; 291 292 #define F(name, str) \ 293 const AstRawString* name##_string() const { return name##_string_; } AST_STRING_CONSTANTS(F)294 AST_STRING_CONSTANTS(F) 295 #undef F 296 297 uint64_t hash_seed() const { return hash_seed_; } string_table()298 const AstRawStringMap* string_table() const { return &string_table_; } 299 300 private: 301 Zone zone_; 302 AstRawStringMap string_table_; 303 uint64_t hash_seed_; 304 305 #define F(name, str) AstRawString* name##_string_; 306 AST_STRING_CONSTANTS(F) 307 #undef F 308 }; 309 310 class AstValueFactory { 311 public: AstValueFactory(Zone * zone,const AstStringConstants * string_constants,uint64_t hash_seed)312 AstValueFactory(Zone* zone, const AstStringConstants* string_constants, 313 uint64_t hash_seed) 314 : AstValueFactory(zone, zone, string_constants, hash_seed) {} 315 AstValueFactory(Zone * ast_raw_string_zone,Zone * single_parse_zone,const AstStringConstants * string_constants,uint64_t hash_seed)316 AstValueFactory(Zone* ast_raw_string_zone, Zone* single_parse_zone, 317 const AstStringConstants* string_constants, 318 uint64_t hash_seed) 319 : string_table_(string_constants->string_table()), 320 strings_(nullptr), 321 strings_end_(&strings_), 322 string_constants_(string_constants), 323 empty_cons_string_(nullptr), 324 ast_raw_string_zone_(ast_raw_string_zone), 325 single_parse_zone_(single_parse_zone), 326 hash_seed_(hash_seed) { 327 DCHECK_NOT_NULL(ast_raw_string_zone_); 328 DCHECK_NOT_NULL(single_parse_zone_); 329 DCHECK_EQ(hash_seed, string_constants->hash_seed()); 330 std::fill(one_character_strings_, 331 one_character_strings_ + arraysize(one_character_strings_), 332 nullptr); 333 334 // Allocate the empty ConsString in the AstRawString Zone instead of the 335 // single parse Zone like other ConsStrings, because unlike those it can be 336 // reused across parses. 337 empty_cons_string_ = ast_raw_string_zone_->New<AstConsString>(); 338 } 339 ast_raw_string_zone()340 Zone* ast_raw_string_zone() const { 341 DCHECK_NOT_NULL(ast_raw_string_zone_); 342 return ast_raw_string_zone_; 343 } 344 single_parse_zone()345 Zone* single_parse_zone() const { 346 DCHECK_NOT_NULL(single_parse_zone_); 347 return single_parse_zone_; 348 } 349 GetOneByteString(base::Vector<const uint8_t> literal)350 const AstRawString* GetOneByteString(base::Vector<const uint8_t> literal) { 351 return GetOneByteStringInternal(literal); 352 } GetOneByteString(const char * string)353 const AstRawString* GetOneByteString(const char* string) { 354 return GetOneByteString(base::OneByteVector(string)); 355 } GetTwoByteString(base::Vector<const uint16_t> literal)356 const AstRawString* GetTwoByteString(base::Vector<const uint16_t> literal) { 357 return GetTwoByteStringInternal(literal); 358 } 359 const AstRawString* GetString(String literal, 360 const SharedStringAccessGuardIfNeeded&); 361 362 V8_EXPORT_PRIVATE AstConsString* NewConsString(); 363 V8_EXPORT_PRIVATE AstConsString* NewConsString(const AstRawString* str); 364 V8_EXPORT_PRIVATE AstConsString* NewConsString(const AstRawString* str1, 365 const AstRawString* str2); 366 367 // Internalize all the strings in the factory, and prevent any more from being 368 // allocated. Multiple calls to Internalize are allowed, for simplicity, where 369 // subsequent calls are a no-op. 370 template <typename IsolateT> 371 void Internalize(IsolateT* isolate); 372 373 #define F(name, str) \ 374 const AstRawString* name##_string() const { \ 375 return string_constants_->name##_string(); \ 376 } AST_STRING_CONSTANTS(F)377 AST_STRING_CONSTANTS(F) 378 #undef F 379 AstConsString* empty_cons_string() const { return empty_cons_string_; } 380 381 private: AddString(AstRawString * string)382 AstRawString* AddString(AstRawString* string) { 383 *strings_end_ = string; 384 strings_end_ = string->next_location(); 385 return string; 386 } ResetStrings()387 void ResetStrings() { 388 strings_ = nullptr; 389 strings_end_ = &strings_; 390 } 391 V8_EXPORT_PRIVATE const AstRawString* GetOneByteStringInternal( 392 base::Vector<const uint8_t> literal); 393 const AstRawString* GetTwoByteStringInternal( 394 base::Vector<const uint16_t> literal); 395 const AstRawString* GetString(uint32_t raw_hash_field, bool is_one_byte, 396 base::Vector<const byte> literal_bytes); 397 398 // All strings are copied here. 399 AstRawStringMap string_table_; 400 401 AstRawString* strings_; 402 AstRawString** strings_end_; 403 404 // Holds constant string values which are shared across the isolate. 405 const AstStringConstants* string_constants_; 406 407 AstConsString* empty_cons_string_; 408 409 // Caches one character lowercase strings (for minified code). 410 static const int kMaxOneCharStringValue = 128; 411 const AstRawString* one_character_strings_[kMaxOneCharStringValue]; 412 413 Zone* ast_raw_string_zone_; 414 Zone* single_parse_zone_; 415 416 uint64_t hash_seed_; 417 }; 418 419 extern template EXPORT_TEMPLATE_DECLARE( 420 V8_EXPORT_PRIVATE) void AstValueFactory::Internalize<Isolate>(Isolate* 421 isolate); 422 423 extern template EXPORT_TEMPLATE_DECLARE( 424 V8_EXPORT_PRIVATE) void AstValueFactory:: 425 Internalize<LocalIsolate>(LocalIsolate* isolate); 426 427 } // namespace internal 428 } // namespace v8 429 430 #endif // V8_AST_AST_VALUE_FACTORY_H_ 431