69fc6cc2f459c3763c0808a4a8e6ae209b703341
[platform/upstream/v8.git] / src / ast-value-factory.h
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_VALUE_FACTORY_H_
29 #define V8_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 : 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 : public AstString {
119  public:
120   AstConsString(const AstString* left, const AstString* right)
121       : left_(left),
122         right_(right) {}
123
124   int length() const override { return left_->length() + right_->length(); }
125
126   void Internalize(Isolate* isolate) override;
127
128  private:
129   friend class AstValueFactory;
130
131   const AstString* left_;
132   const AstString* right_;
133 };
134
135
136 // AstValue is either a string, a number, a string array, a boolean, or a
137 // special value (null, undefined, the hole).
138 class AstValue : public ZoneObject {
139  public:
140   bool IsString() const {
141     return type_ == STRING;
142   }
143
144   bool IsNumber() const {
145     return type_ == NUMBER || type_ == NUMBER_WITH_DOT || type_ == SMI;
146   }
147
148   bool ContainsDot() const { return type_ == NUMBER_WITH_DOT; }
149
150   const AstRawString* AsString() const {
151     if (type_ == STRING)
152       return string_;
153     UNREACHABLE();
154     return 0;
155   }
156
157   double AsNumber() const {
158     if (type_ == NUMBER || type_ == NUMBER_WITH_DOT)
159       return number_;
160     if (type_ == SMI)
161       return smi_;
162     UNREACHABLE();
163     return 0;
164   }
165
166   bool EqualsString(const AstRawString* string) const {
167     return type_ == STRING && string_ == string;
168   }
169
170   bool IsPropertyName() const;
171
172   bool BooleanValue() const;
173
174   bool IsTheHole() const { return type_ == THE_HOLE; }
175
176   void Internalize(Isolate* isolate);
177
178   // Can be called after Internalize has been called.
179   V8_INLINE Handle<Object> value() const {
180     if (type_ == STRING) {
181       return string_->string();
182     }
183     DCHECK(!value_.is_null());
184     return value_;
185   }
186
187  private:
188   friend class AstValueFactory;
189
190   enum Type {
191     STRING,
192     SYMBOL,
193     NUMBER,
194     NUMBER_WITH_DOT,
195     SMI,
196     BOOLEAN,
197     NULL_TYPE,
198     UNDEFINED,
199     THE_HOLE
200   };
201
202   explicit AstValue(const AstRawString* s) : type_(STRING) { string_ = s; }
203
204   explicit AstValue(const char* name) : type_(SYMBOL) { symbol_name_ = name; }
205
206   explicit AstValue(double n, bool with_dot) {
207     if (with_dot) {
208       type_ = NUMBER_WITH_DOT;
209     } else {
210       type_ = NUMBER;
211     }
212     number_ = n;
213   }
214
215   AstValue(Type t, int i) : type_(t) {
216     DCHECK(type_ == SMI);
217     smi_ = i;
218   }
219
220   explicit AstValue(bool b) : type_(BOOLEAN) { bool_ = b; }
221
222   explicit AstValue(Type t) : type_(t) {
223     DCHECK(t == NULL_TYPE || t == UNDEFINED || t == THE_HOLE);
224   }
225
226   Type type_;
227
228   // Uninternalized value.
229   union {
230     const AstRawString* string_;
231     double number_;
232     int smi_;
233     bool bool_;
234     ZoneList<const AstRawString*>* strings_;
235     const char* symbol_name_;
236   };
237
238   // Internalized value (empty before internalized).
239   Handle<Object> value_;
240 };
241
242
243 // For generating constants.
244 #define STRING_CONSTANTS(F)                     \
245   F(anonymous_function, "(anonymous function)") \
246   F(arguments, "arguments")                     \
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_module, ".module")                      \
256   F(dot_result, ".result")                      \
257   F(dot_switch_tag, ".switch_tag")              \
258   F(empty, "")                                  \
259   F(eval, "eval")                               \
260   F(let, "let")                                 \
261   F(native, "native")                           \
262   F(new_target, ".new.target")                  \
263   F(next, "next")                               \
264   F(proto, "__proto__")                         \
265   F(prototype, "prototype")                     \
266   F(rest_parameter, ".rest_parameter")          \
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 v8::internal
370
371 #undef STRING_CONSTANTS
372 #undef OTHER_CONSTANTS
373
374 #endif  // V8_AST_VALUE_FACTORY_H_