ast-value-factory.h 13.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
// Copyright 2014 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

28 29
#ifndef V8_AST_AST_VALUE_FACTORY_H_
#define V8_AST_AST_VALUE_FACTORY_H_
30

31 32
#include <forward_list>

lpy's avatar
lpy committed
33
#include "src/base/hashmap.h"
marja's avatar
marja committed
34
#include "src/conversions.h"
35
#include "src/globals.h"
36
#include "src/heap/factory.h"
37
#include "src/isolate.h"
38 39
#include "src/utils.h"

40
// Ast(Raw|Cons)String and AstValueFactory are for storing strings and
41 42 43 44
// values independent of the V8 heap and internalizing them later. During
// parsing, they are created and stored outside the heap, in AstValueFactory.
// After parsing, the strings and values are internalized (moved into the V8
// heap).
45 46 47
namespace v8 {
namespace internal {

48
class AstRawString final : public ZoneObject {
49
 public:
50
  bool IsEmpty() const { return literal_bytes_.length() == 0; }
51
  int length() const {
52 53
    return is_one_byte() ? literal_bytes_.length()
                         : literal_bytes_.length() / 2;
54
  }
55 56 57
  bool AsArrayIndex(uint32_t* index) const;
  bool IsOneByteEqualTo(const char* data) const;
  uint16_t FirstCharacter() const;
58

59
  void Internalize(Isolate* isolate);
60

61 62 63
  // Access the physical representation:
  bool is_one_byte() const { return is_one_byte_; }
  int byte_length() const { return literal_bytes_.length(); }
64 65 66
  const unsigned char* raw_data() const {
    return literal_bytes_.start();
  }
67

68
  // For storing AstRawStrings in a hash map.
69 70
  uint32_t hash_field() const { return hash_field_; }
  uint32_t Hash() const { return hash_field_ >> Name::kHashShift; }
71

72 73 74 75 76 77 78
  // This function can be called after internalizing.
  V8_INLINE Handle<String> string() const {
    DCHECK_NOT_NULL(string_);
    DCHECK(has_string_);
    return Handle<String>(string_);
  }

79
 private:
80
  friend class AstRawStringInternalizationKey;
81 82
  friend class AstStringConstants;
  friend class AstValueFactory;
83

84 85
  // Members accessed only by the AstValueFactory & related classes:
  static bool Compare(void* a, void* b);
86
  AstRawString(bool is_one_byte, const Vector<const byte>& literal_bytes,
87
               uint32_t hash_field)
88 89
      : next_(nullptr),
        literal_bytes_(literal_bytes),
90
        hash_field_(hash_field),
91 92 93 94 95 96 97 98
        is_one_byte_(is_one_byte) {}
  AstRawString* next() {
    DCHECK(!has_string_);
    return next_;
  }
  AstRawString** next_location() {
    DCHECK(!has_string_);
    return &next_;
99
  }
100

101 102 103 104 105 106 107
  void set_string(Handle<String> string) {
    DCHECK(!string.is_null());
    DCHECK(!has_string_);
    string_ = string.location();
#ifdef DEBUG
    has_string_ = true;
#endif
108
  }
109

110 111 112 113 114 115
  // {string_} is stored as String** instead of a Handle<String> so it can be
  // stored in a union with {next_}.
  union {
    AstRawString* next_;
    String** string_;
  };
116

117
  Vector<const byte> literal_bytes_;  // Memory owned by Zone.
118
  uint32_t hash_field_;
119 120 121 122 123 124 125
  bool is_one_byte_;
#ifdef DEBUG
  // (Debug-only:) Verify the object life-cylce: Some functions may only be
  // called after internalization (that is, after a v8::internal::String has
  // been set); some only before.
  bool has_string_ = false;
#endif
126 127
};

128
class AstConsString final : public ZoneObject {
129
 public:
130 131 132 133 134 135 136 137 138 139
  AstConsString* AddString(Zone* zone, const AstRawString* s) {
    if (s->IsEmpty()) return this;
    if (!IsEmpty()) {
      // We're putting the new string to the head of the list, meaning
      // the string segments will be in reverse order.
      Segment* tmp = new (zone->New(sizeof(Segment))) Segment;
      *tmp = segment_;
      segment_.next = tmp;
    }
    segment_.string = s;
140 141
    return this;
  }
142

143 144 145 146 147
  bool IsEmpty() const {
    DCHECK_IMPLIES(segment_.string == nullptr, segment_.next == nullptr);
    DCHECK_IMPLIES(segment_.string != nullptr, !segment_.string->IsEmpty());
    return segment_.string == nullptr;
  }
148

149
  void Internalize(Isolate* isolate);
150

151 152 153 154 155
  V8_INLINE Handle<String> string() const {
    DCHECK_NOT_NULL(string_);
    return Handle<String>(string_);
  }

156 157
  std::forward_list<const AstRawString*> ToRawStrings() const;

158
 private:
159 160
  friend class AstValueFactory;

161
  AstConsString() : next_(nullptr), segment_({nullptr, nullptr}) {}
162 163 164 165 166 167 168 169 170 171 172 173

  AstConsString* next() const { return next_; }
  AstConsString** next_location() { return &next_; }

  // {string_} is stored as String** instead of a Handle<String> so it can be
  // stored in a union with {next_}.
  void set_string(Handle<String> string) { string_ = string.location(); }
  union {
    AstConsString* next_;
    String** string_;
  };

174 175 176 177 178
  struct Segment {
    const AstRawString* string;
    AstConsString::Segment* next;
  };
  Segment segment_;
179 180
};

181
enum class AstSymbol : uint8_t { kHomeObjectSymbol };
182

183
class AstBigInt {
184
 public:
185 186 187 188
  // |bigint| must be a NUL-terminated string of ASCII characters
  // representing a BigInt (suitable for passing to BigIntLiteral()
  // from conversions.h).
  explicit AstBigInt(const char* bigint) : bigint_(bigint) {}
189

190
  const char* c_str() const { return bigint_; }
191 192

 private:
193
  const char* bigint_;
194 195
};

196
// For generating constants.
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
#define AST_STRING_CONSTANTS(F)                                      \
  F(anonymous_function, "(anonymous function)")                      \
  F(arguments, "arguments")                                          \
  F(async, "async")                                                  \
  F(await, "await")                                                  \
  F(bigint, "bigint")                                                \
  F(boolean, "boolean")                                              \
  F(constructor, "constructor")                                      \
  F(default, "default")                                              \
  F(done, "done")                                                    \
  F(dot, ".")                                                        \
  F(dot_for, ".for")                                                 \
  F(dot_generator_object, ".generator_object")                       \
  F(dot_iterator, ".iterator")                                       \
  F(dot_result, ".result")                                           \
  F(dot_switch_tag, ".switch_tag")                                   \
  F(dot_catch, ".catch")                                             \
  F(empty, "")                                                       \
  F(eval, "eval")                                                    \
  F(function, "function")                                            \
  F(get_space, "get ")                                               \
  F(length, "length")                                                \
  F(let, "let")                                                      \
  F(name, "name")                                                    \
  F(native, "native")                                                \
  F(new_target, ".new.target")                                       \
  F(next, "next")                                                    \
  F(number, "number")                                                \
  F(object, "object")                                                \
  F(proto, "__proto__")                                              \
  F(prototype, "prototype")                                          \
  F(return, "return")                                                \
  F(set_space, "set ")                                               \
  F(star_default_star, "*default*")                                  \
  F(string, "string")                                                \
  F(symbol, "symbol")                                                \
  F(this, "this")                                                    \
  F(this_function, ".this_function")                                 \
  F(throw, "throw")                                                  \
  F(undefined, "undefined")                                          \
  F(use_asm, "use asm")                                              \
  F(use_strict, "use strict")                                        \
239
  F(value, "value")
240

241 242
class AstStringConstants final {
 public:
Yang Guo's avatar
Yang Guo committed
243
  AstStringConstants(Isolate* isolate, uint64_t hash_seed);
244 245

#define F(name, str) \
246
  const AstRawString* name##_string() const { return name##_string_; }
247
  AST_STRING_CONSTANTS(F)
248 249
#undef F

Yang Guo's avatar
Yang Guo committed
250
  uint64_t hash_seed() const { return hash_seed_; }
251 252 253
  const base::CustomMatcherHashMap* string_table() const {
    return &string_table_;
  }
254 255 256

 private:
  Zone zone_;
257
  base::CustomMatcherHashMap string_table_;
Yang Guo's avatar
Yang Guo committed
258
  uint64_t hash_seed_;
259 260

#define F(name, str) AstRawString* name##_string_;
261
  AST_STRING_CONSTANTS(F)
262 263 264 265 266
#undef F

  DISALLOW_COPY_AND_ASSIGN(AstStringConstants);
};

267 268
class AstValueFactory {
 public:
269
  AstValueFactory(Zone* zone, const AstStringConstants* string_constants,
Yang Guo's avatar
Yang Guo committed
270
                  uint64_t hash_seed)
271
      : string_table_(string_constants->string_table()),
272 273
        strings_(nullptr),
        strings_end_(&strings_),
274 275
        cons_strings_(nullptr),
        cons_strings_end_(&cons_strings_),
276
        string_constants_(string_constants),
277
        empty_cons_string_(nullptr),
278 279
        zone_(zone),
        hash_seed_(hash_seed) {
280
    DCHECK_EQ(hash_seed, string_constants->hash_seed());
281 282 283
    std::fill(one_character_strings_,
              one_character_strings_ + arraysize(one_character_strings_),
              nullptr);
284
    empty_cons_string_ = NewConsString();
285 286
  }

287 288
  Zone* zone() const { return zone_; }

289 290
  const AstRawString* GetOneByteString(Vector<const uint8_t> literal) {
    return GetOneByteStringInternal(literal);
291
  }
292 293 294
  const AstRawString* GetOneByteString(const char* string) {
    return GetOneByteString(Vector<const uint8_t>(
        reinterpret_cast<const uint8_t*>(string), StrLength(string)));
295
  }
296 297
  const AstRawString* GetTwoByteString(Vector<const uint16_t> literal) {
    return GetTwoByteStringInternal(literal);
298
  }
299
  const AstRawString* GetString(Handle<String> literal);
300 301 302 303
  V8_EXPORT_PRIVATE AstConsString* NewConsString();
  AstConsString* NewConsString(const AstRawString* str);
  AstConsString* NewConsString(const AstRawString* str1,
                               const AstRawString* str2);
304

305
  V8_EXPORT_PRIVATE void Internalize(Isolate* isolate);
306

307
#define F(name, str)                           \
308
  const AstRawString* name##_string() const {  \
309
    return string_constants_->name##_string(); \
310
  }
311
  AST_STRING_CONSTANTS(F)
312
#undef F
313
  const AstConsString* empty_cons_string() const { return empty_cons_string_; }
314 315

 private:
316
  AstRawString* AddString(AstRawString* string) {
317 318
    *strings_end_ = string;
    strings_end_ = string->next_location();
319 320
    return string;
  }
321 322 323 324 325
  AstConsString* AddConsString(AstConsString* string) {
    *cons_strings_end_ = string;
    cons_strings_end_ = string->next_location();
    return string;
  }
326 327 328
  void ResetStrings() {
    strings_ = nullptr;
    strings_end_ = &strings_;
329 330
    cons_strings_ = nullptr;
    cons_strings_end_ = &cons_strings_;
331
  }
332
  V8_EXPORT_PRIVATE AstRawString* GetOneByteStringInternal(
333 334
      Vector<const uint8_t> literal);
  AstRawString* GetTwoByteStringInternal(Vector<const uint16_t> literal);
335
  AstRawString* GetString(uint32_t hash, bool is_one_byte,
336
                          Vector<const byte> literal_bytes);
337

338
  // All strings are copied here, one after another (no zeroes inbetween).
339
  base::CustomMatcherHashMap string_table_;
heimbuef's avatar
heimbuef committed
340

341
  // We need to keep track of strings_ in order since cons strings require their
342
  // members to be internalized first.
343 344 345 346
  AstRawString* strings_;
  AstRawString** strings_end_;
  AstConsString* cons_strings_;
  AstConsString** cons_strings_end_;
347

348
  // Holds constant string values which are shared across the isolate.
349
  const AstStringConstants* string_constants_;
350
  const AstConsString* empty_cons_string_;
351

352
  // Caches one character lowercase strings (for minified code).
353 354
  AstRawString* one_character_strings_[26];

355 356
  Zone* zone_;

Yang Guo's avatar
Yang Guo committed
357
  uint64_t hash_seed_;
358
};
359 360
}  // namespace internal
}  // namespace v8
361

362
#endif  // V8_AST_AST_VALUE_FACTORY_H_