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/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: 45 virtual ~AstString() {} 46 47 virtual int length() const = 0; 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. 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: 67 int length() const override { 68 if (is_one_byte_) 69 return literal_bytes_.length(); 70 return literal_bytes_.length() / 2; 71 } 72 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. 80 const unsigned char* raw_data() const { 81 return literal_bytes_.start(); 82 } 83 bool is_one_byte() const { return is_one_byte_; } 84 bool IsOneByteEqualTo(const char* data) const; 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. 94 uint32_t hash() const { 95 return hash_; 96 } 97 98 private: 99 friend class AstValueFactory; 100 friend class AstRawStringInternalizationKey; 101 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 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: 120 AstConsString(const AstString* left, const AstString* right) 121 : length_(left->length() + right->length()), left_(left), right_(right) {} 122 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: 138 bool IsString() const { 139 return type_ == STRING; 140 } 141 142 bool IsNumber() const { 143 return type_ == NUMBER || type_ == NUMBER_WITH_DOT || type_ == SMI; 144 } 145 146 bool ContainsDot() const { return type_ == NUMBER_WITH_DOT; } 147 148 const AstRawString* AsString() const { 149 if (type_ == STRING) 150 return string_; 151 UNREACHABLE(); 152 return 0; 153 } 154 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 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 172 bool IsTheHole() const { return type_ == THE_HOLE; } 173 174 void Internalize(Isolate* isolate); 175 176 // Can be called after Internalize has been called. 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 200 explicit AstValue(const AstRawString* s) : type_(STRING) { string_ = s; } 201 202 explicit AstValue(const char* name) : type_(SYMBOL) { symbol_name_ = name; } 203 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 213 AstValue(Type t, int i) : type_(t) { 214 DCHECK(type_ == SMI); 215 smi_ = i; 216 } 217 218 explicit AstValue(bool b) : type_(BOOLEAN) { bool_ = b; } 219 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(constructor, "constructor") \ 246 F(default, "default") \ 247 F(done, "done") \ 248 F(dot, ".") \ 249 F(dot_for, ".for") \ 250 F(dot_generator, ".generator") \ 251 F(dot_generator_object, ".generator_object") \ 252 F(dot_iterator, ".iterator") \ 253 F(dot_result, ".result") \ 254 F(dot_switch_tag, ".switch_tag") \ 255 F(dot_catch, ".catch") \ 256 F(empty, "") \ 257 F(eval, "eval") \ 258 F(get_space, "get ") \ 259 F(let, "let") \ 260 F(native, "native") \ 261 F(new_target, ".new.target") \ 262 F(next, "next") \ 263 F(proto, "__proto__") \ 264 F(prototype, "prototype") \ 265 F(rest_parameter, ".rest_parameter") \ 266 F(set_space, "set ") \ 267 F(this, "this") \ 268 F(this_function, ".this_function") \ 269 F(undefined, "undefined") \ 270 F(use_asm, "use asm") \ 271 F(use_strong, "use strong") \ 272 F(use_strict, "use strict") \ 273 F(value, "value") 274 275 #define OTHER_CONSTANTS(F) \ 276 F(true_value) \ 277 F(false_value) \ 278 F(null_value) \ 279 F(undefined_value) \ 280 F(the_hole_value) 281 282 class AstValueFactory { 283 public: 284 AstValueFactory(Zone* zone, uint32_t hash_seed) 285 : string_table_(AstRawStringCompare), 286 zone_(zone), 287 isolate_(NULL), 288 hash_seed_(hash_seed) { 289 #define F(name, str) name##_string_ = NULL; 290 STRING_CONSTANTS(F) 291 #undef F 292 #define F(name) name##_ = NULL; 293 OTHER_CONSTANTS(F) 294 #undef F 295 } 296 297 Zone* zone() const { return zone_; } 298 299 const AstRawString* GetOneByteString(Vector<const uint8_t> literal) { 300 return GetOneByteStringInternal(literal); 301 } 302 const AstRawString* GetOneByteString(const char* string) { 303 return GetOneByteString(Vector<const uint8_t>( 304 reinterpret_cast<const uint8_t*>(string), StrLength(string))); 305 } 306 const AstRawString* GetTwoByteString(Vector<const uint16_t> literal) { 307 return GetTwoByteStringInternal(literal); 308 } 309 const AstRawString* GetString(Handle<String> literal); 310 const AstConsString* NewConsString(const AstString* left, 311 const AstString* right); 312 313 void Internalize(Isolate* isolate); 314 bool IsInternalized() { 315 return isolate_ != NULL; 316 } 317 318 #define F(name, str) \ 319 const AstRawString* name##_string() { \ 320 if (name##_string_ == NULL) { \ 321 const char* data = str; \ 322 name##_string_ = GetOneByteString( \ 323 Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), \ 324 static_cast<int>(strlen(data)))); \ 325 } \ 326 return name##_string_; \ 327 } 328 STRING_CONSTANTS(F) 329 #undef F 330 331 const AstValue* NewString(const AstRawString* string); 332 // A JavaScript symbol (ECMA-262 edition 6). 333 const AstValue* NewSymbol(const char* name); 334 const AstValue* NewNumber(double number, bool with_dot = false); 335 const AstValue* NewSmi(int number); 336 const AstValue* NewBoolean(bool b); 337 const AstValue* NewStringList(ZoneList<const AstRawString*>* strings); 338 const AstValue* NewNull(); 339 const AstValue* NewUndefined(); 340 const AstValue* NewTheHole(); 341 342 private: 343 AstRawString* GetOneByteStringInternal(Vector<const uint8_t> literal); 344 AstRawString* GetTwoByteStringInternal(Vector<const uint16_t> literal); 345 AstRawString* GetString(uint32_t hash, bool is_one_byte, 346 Vector<const byte> literal_bytes); 347 348 static bool AstRawStringCompare(void* a, void* b); 349 350 // All strings are copied here, one after another (no NULLs inbetween). 351 HashMap string_table_; 352 // For keeping track of all AstValues and AstRawStrings we've created (so that 353 // they can be internalized later). 354 List<AstValue*> values_; 355 List<AstString*> strings_; 356 Zone* zone_; 357 Isolate* isolate_; 358 359 uint32_t hash_seed_; 360 361 #define F(name, str) const AstRawString* name##_string_; 362 STRING_CONSTANTS(F) 363 #undef F 364 365 #define F(name) AstValue* name##_; 366 OTHER_CONSTANTS(F) 367 #undef F 368 }; 369 } // namespace internal 370 } // namespace v8 371 372 #undef STRING_CONSTANTS 373 #undef OTHER_CONSTANTS 374 375 #endif // V8_AST_AST_VALUE_FACTORY_H_ 376