Home | History | Annotate | Download | only in ast
      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