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