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 "src/api.h" 32 #include "src/base/hashmap.h" 33 #include "src/utils.h" 34 35 // AstString, AstValue and AstValueFactory are for storing strings and values 36 // independent of the V8 heap and internalizing them later. During parsing, 37 // AstStrings and AstValues are created and stored outside the heap, in 38 // AstValueFactory. After parsing, the strings and values are internalized 39 // (moved into the V8 heap). 40 namespace v8 { 41 namespace internal { 42 43 class AstString : public ZoneObject { 44 public: ~AstString()45 virtual ~AstString() {} 46 47 virtual int length() const = 0; IsEmpty()48 bool IsEmpty() const { return length() == 0; } 49 50 // Puts the string into the V8 heap. 51 virtual void Internalize(Isolate* isolate) = 0; 52 53 // This function can be called after internalizing. string()54 V8_INLINE Handle<String> string() const { 55 DCHECK(!string_.is_null()); 56 return string_; 57 } 58 59 protected: 60 // This is null until the string is internalized. 61 Handle<String> string_; 62 }; 63 64 65 class AstRawString final : public AstString { 66 public: length()67 int length() const override { 68 if (is_one_byte_) 69 return literal_bytes_.length(); 70 return literal_bytes_.length() / 2; 71 } 72 byte_length()73 int byte_length() const { return literal_bytes_.length(); } 74 75 void Internalize(Isolate* isolate) override; 76 77 bool AsArrayIndex(uint32_t* index) const; 78 79 // The string is not null-terminated, use length() to find out the length. raw_data()80 const unsigned char* raw_data() const { 81 return literal_bytes_.start(); 82 } is_one_byte()83 bool is_one_byte() const { return is_one_byte_; } 84 bool IsOneByteEqualTo(const char* data) const; FirstCharacter()85 uint16_t FirstCharacter() const { 86 if (is_one_byte_) 87 return literal_bytes_[0]; 88 const uint16_t* c = 89 reinterpret_cast<const uint16_t*>(literal_bytes_.start()); 90 return *c; 91 } 92 93 // For storing AstRawStrings in a hash map. hash()94 uint32_t hash() const { 95 return hash_; 96 } 97 98 private: 99 friend class AstValueFactory; 100 friend class AstRawStringInternalizationKey; 101 AstRawString(bool is_one_byte,const Vector<const byte> & literal_bytes,uint32_t hash)102 AstRawString(bool is_one_byte, const Vector<const byte>& literal_bytes, 103 uint32_t hash) 104 : is_one_byte_(is_one_byte), literal_bytes_(literal_bytes), hash_(hash) {} 105 AstRawString()106 AstRawString() 107 : is_one_byte_(true), 108 hash_(0) {} 109 110 bool is_one_byte_; 111 112 // Points to memory owned by Zone. 113 Vector<const byte> literal_bytes_; 114 uint32_t hash_; 115 }; 116 117 118 class AstConsString final : public AstString { 119 public: AstConsString(const AstString * left,const AstString * right)120 AstConsString(const AstString* left, const AstString* right) 121 : length_(left->length() + right->length()), left_(left), right_(right) {} 122 length()123 int length() const override { return length_; } 124 125 void Internalize(Isolate* isolate) override; 126 127 private: 128 const int length_; 129 const AstString* left_; 130 const AstString* right_; 131 }; 132 133 134 // AstValue is either a string, a number, a string array, a boolean, or a 135 // special value (null, undefined, the hole). 136 class AstValue : public ZoneObject { 137 public: IsString()138 bool IsString() const { 139 return type_ == STRING; 140 } 141 IsNumber()142 bool IsNumber() const { 143 return type_ == NUMBER || type_ == NUMBER_WITH_DOT || type_ == SMI; 144 } 145 ContainsDot()146 bool ContainsDot() const { return type_ == NUMBER_WITH_DOT; } 147 AsString()148 const AstRawString* AsString() const { 149 if (type_ == STRING) 150 return string_; 151 UNREACHABLE(); 152 return 0; 153 } 154 AsNumber()155 double AsNumber() const { 156 if (type_ == NUMBER || type_ == NUMBER_WITH_DOT) 157 return number_; 158 if (type_ == SMI) 159 return smi_; 160 UNREACHABLE(); 161 return 0; 162 } 163 EqualsString(const AstRawString * string)164 bool EqualsString(const AstRawString* string) const { 165 return type_ == STRING && string_ == string; 166 } 167 168 bool IsPropertyName() const; 169 170 bool BooleanValue() const; 171 IsTheHole()172 bool IsTheHole() const { return type_ == THE_HOLE; } 173 174 void Internalize(Isolate* isolate); 175 176 // Can be called after Internalize has been called. value()177 V8_INLINE Handle<Object> value() const { 178 if (type_ == STRING) { 179 return string_->string(); 180 } 181 DCHECK(!value_.is_null()); 182 return value_; 183 } 184 185 private: 186 friend class AstValueFactory; 187 188 enum Type { 189 STRING, 190 SYMBOL, 191 NUMBER, 192 NUMBER_WITH_DOT, 193 SMI, 194 BOOLEAN, 195 NULL_TYPE, 196 UNDEFINED, 197 THE_HOLE 198 }; 199 AstValue(const AstRawString * s)200 explicit AstValue(const AstRawString* s) : type_(STRING) { string_ = s; } 201 AstValue(const char * name)202 explicit AstValue(const char* name) : type_(SYMBOL) { symbol_name_ = name; } 203 AstValue(double n,bool with_dot)204 explicit AstValue(double n, bool with_dot) { 205 if (with_dot) { 206 type_ = NUMBER_WITH_DOT; 207 } else { 208 type_ = NUMBER; 209 } 210 number_ = n; 211 } 212 AstValue(Type t,int i)213 AstValue(Type t, int i) : type_(t) { 214 DCHECK(type_ == SMI); 215 smi_ = i; 216 } 217 AstValue(bool b)218 explicit AstValue(bool b) : type_(BOOLEAN) { bool_ = b; } 219 AstValue(Type t)220 explicit AstValue(Type t) : type_(t) { 221 DCHECK(t == NULL_TYPE || t == UNDEFINED || t == THE_HOLE); 222 } 223 224 Type type_; 225 226 // Uninternalized value. 227 union { 228 const AstRawString* string_; 229 double number_; 230 int smi_; 231 bool bool_; 232 ZoneList<const AstRawString*>* strings_; 233 const char* symbol_name_; 234 }; 235 236 // Internalized value (empty before internalized). 237 Handle<Object> value_; 238 }; 239 240 241 // For generating constants. 242 #define STRING_CONSTANTS(F) \ 243 F(anonymous_function, "(anonymous function)") \ 244 F(arguments, "arguments") \ 245 F(async, "async") \ 246 F(await, "await") \ 247 F(constructor, "constructor") \ 248 F(default, "default") \ 249 F(done, "done") \ 250 F(dot, ".") \ 251 F(dot_for, ".for") \ 252 F(dot_generator, ".generator") \ 253 F(dot_generator_object, ".generator_object") \ 254 F(dot_iterator, ".iterator") \ 255 F(dot_result, ".result") \ 256 F(dot_switch_tag, ".switch_tag") \ 257 F(dot_catch, ".catch") \ 258 F(empty, "") \ 259 F(eval, "eval") \ 260 F(function, "function") \ 261 F(get_space, "get ") \ 262 F(let, "let") \ 263 F(native, "native") \ 264 F(new_target, ".new.target") \ 265 F(next, "next") \ 266 F(proto, "__proto__") \ 267 F(prototype, "prototype") \ 268 F(return, "return") \ 269 F(set_space, "set ") \ 270 F(this, "this") \ 271 F(this_function, ".this_function") \ 272 F(throw, "throw") \ 273 F(undefined, "undefined") \ 274 F(use_asm, "use asm") \ 275 F(use_strict, "use strict") \ 276 F(value, "value") 277 278 #define OTHER_CONSTANTS(F) \ 279 F(true_value) \ 280 F(false_value) \ 281 F(null_value) \ 282 F(undefined_value) \ 283 F(the_hole_value) 284 285 class AstValueFactory { 286 public: AstValueFactory(Zone * zone,uint32_t hash_seed)287 AstValueFactory(Zone* zone, uint32_t hash_seed) 288 : string_table_(AstRawStringCompare), 289 zone_(zone), 290 isolate_(NULL), 291 hash_seed_(hash_seed) { 292 #define F(name, str) name##_string_ = NULL; 293 STRING_CONSTANTS(F) 294 #undef F 295 #define F(name) name##_ = NULL; 296 OTHER_CONSTANTS(F) 297 #undef F 298 } 299 zone()300 Zone* zone() const { return zone_; } 301 GetOneByteString(Vector<const uint8_t> literal)302 const AstRawString* GetOneByteString(Vector<const uint8_t> literal) { 303 return GetOneByteStringInternal(literal); 304 } GetOneByteString(const char * string)305 const AstRawString* GetOneByteString(const char* string) { 306 return GetOneByteString(Vector<const uint8_t>( 307 reinterpret_cast<const uint8_t*>(string), StrLength(string))); 308 } GetTwoByteString(Vector<const uint16_t> literal)309 const AstRawString* GetTwoByteString(Vector<const uint16_t> literal) { 310 return GetTwoByteStringInternal(literal); 311 } 312 const AstRawString* GetString(Handle<String> literal); 313 const AstConsString* NewConsString(const AstString* left, 314 const AstString* right); 315 316 void Internalize(Isolate* isolate); IsInternalized()317 bool IsInternalized() { 318 return isolate_ != NULL; 319 } 320 321 #define F(name, str) \ 322 const AstRawString* name##_string() { \ 323 if (name##_string_ == NULL) { \ 324 const char* data = str; \ 325 name##_string_ = GetOneByteString( \ 326 Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), \ 327 static_cast<int>(strlen(data)))); \ 328 } \ 329 return name##_string_; \ 330 } 331 STRING_CONSTANTS(F) 332 #undef F 333 334 const AstValue* NewString(const AstRawString* string); 335 // A JavaScript symbol (ECMA-262 edition 6). 336 const AstValue* NewSymbol(const char* name); 337 const AstValue* NewNumber(double number, bool with_dot = false); 338 const AstValue* NewSmi(int number); 339 const AstValue* NewBoolean(bool b); 340 const AstValue* NewStringList(ZoneList<const AstRawString*>* strings); 341 const AstValue* NewNull(); 342 const AstValue* NewUndefined(); 343 const AstValue* NewTheHole(); 344 345 private: 346 AstRawString* GetOneByteStringInternal(Vector<const uint8_t> literal); 347 AstRawString* GetTwoByteStringInternal(Vector<const uint16_t> literal); 348 AstRawString* GetString(uint32_t hash, bool is_one_byte, 349 Vector<const byte> literal_bytes); 350 351 static bool AstRawStringCompare(void* a, void* b); 352 353 // All strings are copied here, one after another (no NULLs inbetween). 354 base::HashMap string_table_; 355 // For keeping track of all AstValues and AstRawStrings we've created (so that 356 // they can be internalized later). 357 List<AstValue*> values_; 358 List<AstString*> strings_; 359 Zone* zone_; 360 Isolate* isolate_; 361 362 uint32_t hash_seed_; 363 364 #define F(name, str) const AstRawString* name##_string_; 365 STRING_CONSTANTS(F) 366 #undef F 367 368 #define F(name) AstValue* name##_; 369 OTHER_CONSTANTS(F) 370 #undef F 371 }; 372 } // namespace internal 373 } // namespace v8 374 375 #undef STRING_CONSTANTS 376 #undef OTHER_CONSTANTS 377 378 #endif // V8_AST_AST_VALUE_FACTORY_H_ 379