| OLD | NEW |
| (Empty) |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef V8_AST_H_ | |
| 6 #define V8_AST_H_ | |
| 7 | |
| 8 #include "src/assembler.h" | |
| 9 #include "src/ast-value-factory.h" | |
| 10 #include "src/bailout-reason.h" | |
| 11 #include "src/base/flags.h" | |
| 12 #include "src/base/smart-pointers.h" | |
| 13 #include "src/factory.h" | |
| 14 #include "src/isolate.h" | |
| 15 #include "src/list.h" | |
| 16 #include "src/modules.h" | |
| 17 #include "src/regexp/jsregexp.h" | |
| 18 #include "src/runtime/runtime.h" | |
| 19 #include "src/small-pointer-list.h" | |
| 20 #include "src/token.h" | |
| 21 #include "src/types.h" | |
| 22 #include "src/utils.h" | |
| 23 #include "src/variables.h" | |
| 24 | |
| 25 namespace v8 { | |
| 26 namespace internal { | |
| 27 | |
| 28 // The abstract syntax tree is an intermediate, light-weight | |
| 29 // representation of the parsed JavaScript code suitable for | |
| 30 // compilation to native code. | |
| 31 | |
| 32 // Nodes are allocated in a separate zone, which allows faster | |
| 33 // allocation and constant-time deallocation of the entire syntax | |
| 34 // tree. | |
| 35 | |
| 36 | |
| 37 // ---------------------------------------------------------------------------- | |
| 38 // Nodes of the abstract syntax tree. Only concrete classes are | |
| 39 // enumerated here. | |
| 40 | |
| 41 #define DECLARATION_NODE_LIST(V) \ | |
| 42 V(VariableDeclaration) \ | |
| 43 V(FunctionDeclaration) \ | |
| 44 V(ImportDeclaration) \ | |
| 45 V(ExportDeclaration) | |
| 46 | |
| 47 #define STATEMENT_NODE_LIST(V) \ | |
| 48 V(Block) \ | |
| 49 V(ExpressionStatement) \ | |
| 50 V(EmptyStatement) \ | |
| 51 V(SloppyBlockFunctionStatement) \ | |
| 52 V(IfStatement) \ | |
| 53 V(ContinueStatement) \ | |
| 54 V(BreakStatement) \ | |
| 55 V(ReturnStatement) \ | |
| 56 V(WithStatement) \ | |
| 57 V(SwitchStatement) \ | |
| 58 V(DoWhileStatement) \ | |
| 59 V(WhileStatement) \ | |
| 60 V(ForStatement) \ | |
| 61 V(ForInStatement) \ | |
| 62 V(ForOfStatement) \ | |
| 63 V(TryCatchStatement) \ | |
| 64 V(TryFinallyStatement) \ | |
| 65 V(DebuggerStatement) | |
| 66 | |
| 67 #define EXPRESSION_NODE_LIST(V) \ | |
| 68 V(FunctionLiteral) \ | |
| 69 V(ClassLiteral) \ | |
| 70 V(NativeFunctionLiteral) \ | |
| 71 V(Conditional) \ | |
| 72 V(VariableProxy) \ | |
| 73 V(Literal) \ | |
| 74 V(RegExpLiteral) \ | |
| 75 V(ObjectLiteral) \ | |
| 76 V(ArrayLiteral) \ | |
| 77 V(Assignment) \ | |
| 78 V(Yield) \ | |
| 79 V(Throw) \ | |
| 80 V(Property) \ | |
| 81 V(Call) \ | |
| 82 V(CallNew) \ | |
| 83 V(CallRuntime) \ | |
| 84 V(UnaryOperation) \ | |
| 85 V(CountOperation) \ | |
| 86 V(BinaryOperation) \ | |
| 87 V(CompareOperation) \ | |
| 88 V(Spread) \ | |
| 89 V(ThisFunction) \ | |
| 90 V(SuperPropertyReference) \ | |
| 91 V(SuperCallReference) \ | |
| 92 V(CaseClause) \ | |
| 93 V(EmptyParentheses) \ | |
| 94 V(DoExpression) | |
| 95 | |
| 96 #define AST_NODE_LIST(V) \ | |
| 97 DECLARATION_NODE_LIST(V) \ | |
| 98 STATEMENT_NODE_LIST(V) \ | |
| 99 EXPRESSION_NODE_LIST(V) | |
| 100 | |
| 101 // Forward declarations | |
| 102 class AstNodeFactory; | |
| 103 class AstVisitor; | |
| 104 class Declaration; | |
| 105 class Module; | |
| 106 class BreakableStatement; | |
| 107 class Expression; | |
| 108 class IterationStatement; | |
| 109 class MaterializedLiteral; | |
| 110 class Statement; | |
| 111 class TypeFeedbackOracle; | |
| 112 | |
| 113 class RegExpAlternative; | |
| 114 class RegExpAssertion; | |
| 115 class RegExpAtom; | |
| 116 class RegExpBackReference; | |
| 117 class RegExpCapture; | |
| 118 class RegExpCharacterClass; | |
| 119 class RegExpCompiler; | |
| 120 class RegExpDisjunction; | |
| 121 class RegExpEmpty; | |
| 122 class RegExpLookaround; | |
| 123 class RegExpQuantifier; | |
| 124 class RegExpText; | |
| 125 | |
| 126 #define DEF_FORWARD_DECLARATION(type) class type; | |
| 127 AST_NODE_LIST(DEF_FORWARD_DECLARATION) | |
| 128 #undef DEF_FORWARD_DECLARATION | |
| 129 | |
| 130 | |
| 131 // Typedef only introduced to avoid unreadable code. | |
| 132 typedef ZoneList<Handle<String>> ZoneStringList; | |
| 133 typedef ZoneList<Handle<Object>> ZoneObjectList; | |
| 134 | |
| 135 | |
| 136 #define DECLARE_NODE_TYPE(type) \ | |
| 137 void Accept(AstVisitor* v) override; \ | |
| 138 AstNode::NodeType node_type() const final { return AstNode::k##type; } \ | |
| 139 friend class AstNodeFactory; | |
| 140 | |
| 141 | |
| 142 class FeedbackVectorSlotCache { | |
| 143 public: | |
| 144 explicit FeedbackVectorSlotCache(Zone* zone) | |
| 145 : zone_(zone), | |
| 146 hash_map_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, | |
| 147 ZoneAllocationPolicy(zone)) {} | |
| 148 | |
| 149 void Put(Variable* variable, FeedbackVectorSlot slot) { | |
| 150 ZoneHashMap::Entry* entry = hash_map_.LookupOrInsert( | |
| 151 variable, ComputePointerHash(variable), ZoneAllocationPolicy(zone_)); | |
| 152 entry->value = reinterpret_cast<void*>(slot.ToInt()); | |
| 153 } | |
| 154 | |
| 155 ZoneHashMap::Entry* Get(Variable* variable) const { | |
| 156 return hash_map_.Lookup(variable, ComputePointerHash(variable)); | |
| 157 } | |
| 158 | |
| 159 private: | |
| 160 Zone* zone_; | |
| 161 ZoneHashMap hash_map_; | |
| 162 }; | |
| 163 | |
| 164 | |
| 165 class AstProperties final BASE_EMBEDDED { | |
| 166 public: | |
| 167 enum Flag { | |
| 168 kNoFlags = 0, | |
| 169 kDontSelfOptimize = 1 << 0, | |
| 170 kDontCrankshaft = 1 << 1 | |
| 171 }; | |
| 172 | |
| 173 typedef base::Flags<Flag> Flags; | |
| 174 | |
| 175 explicit AstProperties(Zone* zone) : node_count_(0), spec_(zone) {} | |
| 176 | |
| 177 Flags& flags() { return flags_; } | |
| 178 Flags flags() const { return flags_; } | |
| 179 int node_count() { return node_count_; } | |
| 180 void add_node_count(int count) { node_count_ += count; } | |
| 181 | |
| 182 const FeedbackVectorSpec* get_spec() const { return &spec_; } | |
| 183 FeedbackVectorSpec* get_spec() { return &spec_; } | |
| 184 | |
| 185 private: | |
| 186 Flags flags_; | |
| 187 int node_count_; | |
| 188 FeedbackVectorSpec spec_; | |
| 189 }; | |
| 190 | |
| 191 DEFINE_OPERATORS_FOR_FLAGS(AstProperties::Flags) | |
| 192 | |
| 193 | |
| 194 class AstNode: public ZoneObject { | |
| 195 public: | |
| 196 #define DECLARE_TYPE_ENUM(type) k##type, | |
| 197 enum NodeType { | |
| 198 AST_NODE_LIST(DECLARE_TYPE_ENUM) | |
| 199 kInvalid = -1 | |
| 200 }; | |
| 201 #undef DECLARE_TYPE_ENUM | |
| 202 | |
| 203 void* operator new(size_t size, Zone* zone) { return zone->New(size); } | |
| 204 | |
| 205 explicit AstNode(int position): position_(position) {} | |
| 206 virtual ~AstNode() {} | |
| 207 | |
| 208 virtual void Accept(AstVisitor* v) = 0; | |
| 209 virtual NodeType node_type() const = 0; | |
| 210 int position() const { return position_; } | |
| 211 | |
| 212 // Type testing & conversion functions overridden by concrete subclasses. | |
| 213 #define DECLARE_NODE_FUNCTIONS(type) \ | |
| 214 bool Is##type() const { return node_type() == AstNode::k##type; } \ | |
| 215 type* As##type() { \ | |
| 216 return Is##type() ? reinterpret_cast<type*>(this) : NULL; \ | |
| 217 } \ | |
| 218 const type* As##type() const { \ | |
| 219 return Is##type() ? reinterpret_cast<const type*>(this) : NULL; \ | |
| 220 } | |
| 221 AST_NODE_LIST(DECLARE_NODE_FUNCTIONS) | |
| 222 #undef DECLARE_NODE_FUNCTIONS | |
| 223 | |
| 224 virtual BreakableStatement* AsBreakableStatement() { return NULL; } | |
| 225 virtual IterationStatement* AsIterationStatement() { return NULL; } | |
| 226 virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; } | |
| 227 | |
| 228 // The interface for feedback slots, with default no-op implementations for | |
| 229 // node types which don't actually have this. Note that this is conceptually | |
| 230 // not really nice, but multiple inheritance would introduce yet another | |
| 231 // vtable entry per node, something we don't want for space reasons. | |
| 232 virtual void AssignFeedbackVectorSlots(Isolate* isolate, | |
| 233 FeedbackVectorSpec* spec, | |
| 234 FeedbackVectorSlotCache* cache) {} | |
| 235 | |
| 236 private: | |
| 237 // Hidden to prevent accidental usage. It would have to load the | |
| 238 // current zone from the TLS. | |
| 239 void* operator new(size_t size); | |
| 240 | |
| 241 friend class CaseClause; // Generates AST IDs. | |
| 242 | |
| 243 int position_; | |
| 244 }; | |
| 245 | |
| 246 | |
| 247 class Statement : public AstNode { | |
| 248 public: | |
| 249 explicit Statement(Zone* zone, int position) : AstNode(position) {} | |
| 250 | |
| 251 bool IsEmpty() { return AsEmptyStatement() != NULL; } | |
| 252 virtual bool IsJump() const { return false; } | |
| 253 }; | |
| 254 | |
| 255 | |
| 256 class SmallMapList final { | |
| 257 public: | |
| 258 SmallMapList() {} | |
| 259 SmallMapList(int capacity, Zone* zone) : list_(capacity, zone) {} | |
| 260 | |
| 261 void Reserve(int capacity, Zone* zone) { list_.Reserve(capacity, zone); } | |
| 262 void Clear() { list_.Clear(); } | |
| 263 void Sort() { list_.Sort(); } | |
| 264 | |
| 265 bool is_empty() const { return list_.is_empty(); } | |
| 266 int length() const { return list_.length(); } | |
| 267 | |
| 268 void AddMapIfMissing(Handle<Map> map, Zone* zone) { | |
| 269 if (!Map::TryUpdate(map).ToHandle(&map)) return; | |
| 270 for (int i = 0; i < length(); ++i) { | |
| 271 if (at(i).is_identical_to(map)) return; | |
| 272 } | |
| 273 Add(map, zone); | |
| 274 } | |
| 275 | |
| 276 void FilterForPossibleTransitions(Map* root_map) { | |
| 277 for (int i = list_.length() - 1; i >= 0; i--) { | |
| 278 if (at(i)->FindRootMap() != root_map) { | |
| 279 list_.RemoveElement(list_.at(i)); | |
| 280 } | |
| 281 } | |
| 282 } | |
| 283 | |
| 284 void Add(Handle<Map> handle, Zone* zone) { | |
| 285 list_.Add(handle.location(), zone); | |
| 286 } | |
| 287 | |
| 288 Handle<Map> at(int i) const { | |
| 289 return Handle<Map>(list_.at(i)); | |
| 290 } | |
| 291 | |
| 292 Handle<Map> first() const { return at(0); } | |
| 293 Handle<Map> last() const { return at(length() - 1); } | |
| 294 | |
| 295 private: | |
| 296 // The list stores pointers to Map*, that is Map**, so it's GC safe. | |
| 297 SmallPointerList<Map*> list_; | |
| 298 | |
| 299 DISALLOW_COPY_AND_ASSIGN(SmallMapList); | |
| 300 }; | |
| 301 | |
| 302 | |
| 303 class Expression : public AstNode { | |
| 304 public: | |
| 305 enum Context { | |
| 306 // Not assigned a context yet, or else will not be visited during | |
| 307 // code generation. | |
| 308 kUninitialized, | |
| 309 // Evaluated for its side effects. | |
| 310 kEffect, | |
| 311 // Evaluated for its value (and side effects). | |
| 312 kValue, | |
| 313 // Evaluated for control flow (and side effects). | |
| 314 kTest | |
| 315 }; | |
| 316 | |
| 317 // True iff the expression is a valid reference expression. | |
| 318 virtual bool IsValidReferenceExpression() const { return false; } | |
| 319 | |
| 320 // Helpers for ToBoolean conversion. | |
| 321 virtual bool ToBooleanIsTrue() const { return false; } | |
| 322 virtual bool ToBooleanIsFalse() const { return false; } | |
| 323 | |
| 324 // Symbols that cannot be parsed as array indices are considered property | |
| 325 // names. We do not treat symbols that can be array indexes as property | |
| 326 // names because [] for string objects is handled only by keyed ICs. | |
| 327 virtual bool IsPropertyName() const { return false; } | |
| 328 | |
| 329 // True iff the expression is a literal represented as a smi. | |
| 330 bool IsSmiLiteral() const; | |
| 331 | |
| 332 // True iff the expression is a string literal. | |
| 333 bool IsStringLiteral() const; | |
| 334 | |
| 335 // True iff the expression is the null literal. | |
| 336 bool IsNullLiteral() const; | |
| 337 | |
| 338 // True if we can prove that the expression is the undefined literal. | |
| 339 bool IsUndefinedLiteral(Isolate* isolate) const; | |
| 340 | |
| 341 // True iff the expression is a valid target for an assignment. | |
| 342 bool IsValidReferenceExpressionOrThis() const; | |
| 343 | |
| 344 // Expression type bounds | |
| 345 Bounds bounds() const { return bounds_; } | |
| 346 void set_bounds(Bounds bounds) { bounds_ = bounds; } | |
| 347 | |
| 348 // Type feedback information for assignments and properties. | |
| 349 virtual bool IsMonomorphic() { | |
| 350 UNREACHABLE(); | |
| 351 return false; | |
| 352 } | |
| 353 virtual SmallMapList* GetReceiverTypes() { | |
| 354 UNREACHABLE(); | |
| 355 return NULL; | |
| 356 } | |
| 357 virtual KeyedAccessStoreMode GetStoreMode() const { | |
| 358 UNREACHABLE(); | |
| 359 return STANDARD_STORE; | |
| 360 } | |
| 361 virtual IcCheckType GetKeyType() const { | |
| 362 UNREACHABLE(); | |
| 363 return ELEMENT; | |
| 364 } | |
| 365 | |
| 366 // TODO(rossberg): this should move to its own AST node eventually. | |
| 367 virtual void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle); | |
| 368 uint16_t to_boolean_types() const { | |
| 369 return ToBooleanTypesField::decode(bit_field_); | |
| 370 } | |
| 371 | |
| 372 void set_base_id(int id) { base_id_ = id; } | |
| 373 static int num_ids() { return parent_num_ids() + 2; } | |
| 374 BailoutId id() const { return BailoutId(local_id(0)); } | |
| 375 TypeFeedbackId test_id() const { return TypeFeedbackId(local_id(1)); } | |
| 376 | |
| 377 protected: | |
| 378 Expression(Zone* zone, int pos) | |
| 379 : AstNode(pos), | |
| 380 base_id_(BailoutId::None().ToInt()), | |
| 381 bounds_(Bounds::Unbounded()), | |
| 382 bit_field_(0) {} | |
| 383 static int parent_num_ids() { return 0; } | |
| 384 void set_to_boolean_types(uint16_t types) { | |
| 385 bit_field_ = ToBooleanTypesField::update(bit_field_, types); | |
| 386 } | |
| 387 | |
| 388 int base_id() const { | |
| 389 DCHECK(!BailoutId(base_id_).IsNone()); | |
| 390 return base_id_; | |
| 391 } | |
| 392 | |
| 393 private: | |
| 394 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 395 | |
| 396 int base_id_; | |
| 397 Bounds bounds_; | |
| 398 class ToBooleanTypesField : public BitField16<uint16_t, 0, 9> {}; | |
| 399 uint16_t bit_field_; | |
| 400 // Ends with 16-bit field; deriving classes in turn begin with | |
| 401 // 16-bit fields for optimum packing efficiency. | |
| 402 }; | |
| 403 | |
| 404 | |
| 405 class BreakableStatement : public Statement { | |
| 406 public: | |
| 407 enum BreakableType { | |
| 408 TARGET_FOR_ANONYMOUS, | |
| 409 TARGET_FOR_NAMED_ONLY | |
| 410 }; | |
| 411 | |
| 412 // The labels associated with this statement. May be NULL; | |
| 413 // if it is != NULL, guaranteed to contain at least one entry. | |
| 414 ZoneList<const AstRawString*>* labels() const { return labels_; } | |
| 415 | |
| 416 // Type testing & conversion. | |
| 417 BreakableStatement* AsBreakableStatement() final { return this; } | |
| 418 | |
| 419 // Code generation | |
| 420 Label* break_target() { return &break_target_; } | |
| 421 | |
| 422 // Testers. | |
| 423 bool is_target_for_anonymous() const { | |
| 424 return breakable_type_ == TARGET_FOR_ANONYMOUS; | |
| 425 } | |
| 426 | |
| 427 void set_base_id(int id) { base_id_ = id; } | |
| 428 static int num_ids() { return parent_num_ids() + 2; } | |
| 429 BailoutId EntryId() const { return BailoutId(local_id(0)); } | |
| 430 BailoutId ExitId() const { return BailoutId(local_id(1)); } | |
| 431 | |
| 432 protected: | |
| 433 BreakableStatement(Zone* zone, ZoneList<const AstRawString*>* labels, | |
| 434 BreakableType breakable_type, int position) | |
| 435 : Statement(zone, position), | |
| 436 labels_(labels), | |
| 437 breakable_type_(breakable_type), | |
| 438 base_id_(BailoutId::None().ToInt()) { | |
| 439 DCHECK(labels == NULL || labels->length() > 0); | |
| 440 } | |
| 441 static int parent_num_ids() { return 0; } | |
| 442 | |
| 443 int base_id() const { | |
| 444 DCHECK(!BailoutId(base_id_).IsNone()); | |
| 445 return base_id_; | |
| 446 } | |
| 447 | |
| 448 private: | |
| 449 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 450 | |
| 451 ZoneList<const AstRawString*>* labels_; | |
| 452 BreakableType breakable_type_; | |
| 453 Label break_target_; | |
| 454 int base_id_; | |
| 455 }; | |
| 456 | |
| 457 | |
| 458 class Block final : public BreakableStatement { | |
| 459 public: | |
| 460 DECLARE_NODE_TYPE(Block) | |
| 461 | |
| 462 ZoneList<Statement*>* statements() { return &statements_; } | |
| 463 bool ignore_completion_value() const { return ignore_completion_value_; } | |
| 464 | |
| 465 static int num_ids() { return parent_num_ids() + 1; } | |
| 466 BailoutId DeclsId() const { return BailoutId(local_id(0)); } | |
| 467 | |
| 468 bool IsJump() const override { | |
| 469 return !statements_.is_empty() && statements_.last()->IsJump() | |
| 470 && labels() == NULL; // Good enough as an approximation... | |
| 471 } | |
| 472 | |
| 473 Scope* scope() const { return scope_; } | |
| 474 void set_scope(Scope* scope) { scope_ = scope; } | |
| 475 | |
| 476 protected: | |
| 477 Block(Zone* zone, ZoneList<const AstRawString*>* labels, int capacity, | |
| 478 bool ignore_completion_value, int pos) | |
| 479 : BreakableStatement(zone, labels, TARGET_FOR_NAMED_ONLY, pos), | |
| 480 statements_(capacity, zone), | |
| 481 ignore_completion_value_(ignore_completion_value), | |
| 482 scope_(NULL) {} | |
| 483 static int parent_num_ids() { return BreakableStatement::num_ids(); } | |
| 484 | |
| 485 private: | |
| 486 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 487 | |
| 488 ZoneList<Statement*> statements_; | |
| 489 bool ignore_completion_value_; | |
| 490 Scope* scope_; | |
| 491 }; | |
| 492 | |
| 493 | |
| 494 class DoExpression final : public Expression { | |
| 495 public: | |
| 496 DECLARE_NODE_TYPE(DoExpression) | |
| 497 | |
| 498 Block* block() { return block_; } | |
| 499 VariableProxy* result() { return result_; } | |
| 500 | |
| 501 protected: | |
| 502 DoExpression(Zone* zone, Block* block, VariableProxy* result, int pos) | |
| 503 : Expression(zone, pos), block_(block), result_(result) { | |
| 504 DCHECK_NOT_NULL(block_); | |
| 505 DCHECK_NOT_NULL(result_); | |
| 506 } | |
| 507 static int parent_num_ids() { return Expression::num_ids(); } | |
| 508 | |
| 509 private: | |
| 510 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 511 | |
| 512 Block* block_; | |
| 513 VariableProxy* result_; | |
| 514 }; | |
| 515 | |
| 516 | |
| 517 class Declaration : public AstNode { | |
| 518 public: | |
| 519 VariableProxy* proxy() const { return proxy_; } | |
| 520 VariableMode mode() const { return mode_; } | |
| 521 Scope* scope() const { return scope_; } | |
| 522 virtual InitializationFlag initialization() const = 0; | |
| 523 virtual bool IsInlineable() const; | |
| 524 | |
| 525 protected: | |
| 526 Declaration(Zone* zone, VariableProxy* proxy, VariableMode mode, Scope* scope, | |
| 527 int pos) | |
| 528 : AstNode(pos), mode_(mode), proxy_(proxy), scope_(scope) { | |
| 529 DCHECK(IsDeclaredVariableMode(mode)); | |
| 530 } | |
| 531 | |
| 532 private: | |
| 533 VariableMode mode_; | |
| 534 VariableProxy* proxy_; | |
| 535 | |
| 536 // Nested scope from which the declaration originated. | |
| 537 Scope* scope_; | |
| 538 }; | |
| 539 | |
| 540 | |
| 541 class VariableDeclaration final : public Declaration { | |
| 542 public: | |
| 543 DECLARE_NODE_TYPE(VariableDeclaration) | |
| 544 | |
| 545 InitializationFlag initialization() const override { | |
| 546 return mode() == VAR ? kCreatedInitialized : kNeedsInitialization; | |
| 547 } | |
| 548 | |
| 549 bool is_class_declaration() const { return is_class_declaration_; } | |
| 550 | |
| 551 // VariableDeclarations can be grouped into consecutive declaration | |
| 552 // groups. Each VariableDeclaration is associated with the start position of | |
| 553 // the group it belongs to. The positions are used for strong mode scope | |
| 554 // checks for classes and functions. | |
| 555 int declaration_group_start() const { return declaration_group_start_; } | |
| 556 | |
| 557 protected: | |
| 558 VariableDeclaration(Zone* zone, VariableProxy* proxy, VariableMode mode, | |
| 559 Scope* scope, int pos, bool is_class_declaration = false, | |
| 560 int declaration_group_start = -1) | |
| 561 : Declaration(zone, proxy, mode, scope, pos), | |
| 562 is_class_declaration_(is_class_declaration), | |
| 563 declaration_group_start_(declaration_group_start) {} | |
| 564 | |
| 565 bool is_class_declaration_; | |
| 566 int declaration_group_start_; | |
| 567 }; | |
| 568 | |
| 569 | |
| 570 class FunctionDeclaration final : public Declaration { | |
| 571 public: | |
| 572 DECLARE_NODE_TYPE(FunctionDeclaration) | |
| 573 | |
| 574 FunctionLiteral* fun() const { return fun_; } | |
| 575 InitializationFlag initialization() const override { | |
| 576 return kCreatedInitialized; | |
| 577 } | |
| 578 bool IsInlineable() const override; | |
| 579 | |
| 580 protected: | |
| 581 FunctionDeclaration(Zone* zone, | |
| 582 VariableProxy* proxy, | |
| 583 VariableMode mode, | |
| 584 FunctionLiteral* fun, | |
| 585 Scope* scope, | |
| 586 int pos) | |
| 587 : Declaration(zone, proxy, mode, scope, pos), | |
| 588 fun_(fun) { | |
| 589 DCHECK(mode == VAR || mode == LET || mode == CONST); | |
| 590 DCHECK(fun != NULL); | |
| 591 } | |
| 592 | |
| 593 private: | |
| 594 FunctionLiteral* fun_; | |
| 595 }; | |
| 596 | |
| 597 | |
| 598 class ImportDeclaration final : public Declaration { | |
| 599 public: | |
| 600 DECLARE_NODE_TYPE(ImportDeclaration) | |
| 601 | |
| 602 const AstRawString* import_name() const { return import_name_; } | |
| 603 const AstRawString* module_specifier() const { return module_specifier_; } | |
| 604 void set_module_specifier(const AstRawString* module_specifier) { | |
| 605 DCHECK(module_specifier_ == NULL); | |
| 606 module_specifier_ = module_specifier; | |
| 607 } | |
| 608 InitializationFlag initialization() const override { | |
| 609 return kNeedsInitialization; | |
| 610 } | |
| 611 | |
| 612 protected: | |
| 613 ImportDeclaration(Zone* zone, VariableProxy* proxy, | |
| 614 const AstRawString* import_name, | |
| 615 const AstRawString* module_specifier, Scope* scope, int pos) | |
| 616 : Declaration(zone, proxy, IMPORT, scope, pos), | |
| 617 import_name_(import_name), | |
| 618 module_specifier_(module_specifier) {} | |
| 619 | |
| 620 private: | |
| 621 const AstRawString* import_name_; | |
| 622 const AstRawString* module_specifier_; | |
| 623 }; | |
| 624 | |
| 625 | |
| 626 class ExportDeclaration final : public Declaration { | |
| 627 public: | |
| 628 DECLARE_NODE_TYPE(ExportDeclaration) | |
| 629 | |
| 630 InitializationFlag initialization() const override { | |
| 631 return kCreatedInitialized; | |
| 632 } | |
| 633 | |
| 634 protected: | |
| 635 ExportDeclaration(Zone* zone, VariableProxy* proxy, Scope* scope, int pos) | |
| 636 : Declaration(zone, proxy, LET, scope, pos) {} | |
| 637 }; | |
| 638 | |
| 639 | |
| 640 class Module : public AstNode { | |
| 641 public: | |
| 642 ModuleDescriptor* descriptor() const { return descriptor_; } | |
| 643 Block* body() const { return body_; } | |
| 644 | |
| 645 protected: | |
| 646 Module(Zone* zone, int pos) | |
| 647 : AstNode(pos), descriptor_(ModuleDescriptor::New(zone)), body_(NULL) {} | |
| 648 Module(Zone* zone, ModuleDescriptor* descriptor, int pos, Block* body = NULL) | |
| 649 : AstNode(pos), descriptor_(descriptor), body_(body) {} | |
| 650 | |
| 651 private: | |
| 652 ModuleDescriptor* descriptor_; | |
| 653 Block* body_; | |
| 654 }; | |
| 655 | |
| 656 | |
| 657 class IterationStatement : public BreakableStatement { | |
| 658 public: | |
| 659 // Type testing & conversion. | |
| 660 IterationStatement* AsIterationStatement() final { return this; } | |
| 661 | |
| 662 Statement* body() const { return body_; } | |
| 663 void set_body(Statement* s) { body_ = s; } | |
| 664 | |
| 665 static int num_ids() { return parent_num_ids() + 1; } | |
| 666 BailoutId OsrEntryId() const { return BailoutId(local_id(0)); } | |
| 667 virtual BailoutId ContinueId() const = 0; | |
| 668 virtual BailoutId StackCheckId() const = 0; | |
| 669 | |
| 670 // Code generation | |
| 671 Label* continue_target() { return &continue_target_; } | |
| 672 | |
| 673 protected: | |
| 674 IterationStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos) | |
| 675 : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos), | |
| 676 body_(NULL) {} | |
| 677 static int parent_num_ids() { return BreakableStatement::num_ids(); } | |
| 678 void Initialize(Statement* body) { body_ = body; } | |
| 679 | |
| 680 private: | |
| 681 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 682 | |
| 683 Statement* body_; | |
| 684 Label continue_target_; | |
| 685 }; | |
| 686 | |
| 687 | |
| 688 class DoWhileStatement final : public IterationStatement { | |
| 689 public: | |
| 690 DECLARE_NODE_TYPE(DoWhileStatement) | |
| 691 | |
| 692 void Initialize(Expression* cond, Statement* body) { | |
| 693 IterationStatement::Initialize(body); | |
| 694 cond_ = cond; | |
| 695 } | |
| 696 | |
| 697 Expression* cond() const { return cond_; } | |
| 698 | |
| 699 static int num_ids() { return parent_num_ids() + 2; } | |
| 700 BailoutId ContinueId() const override { return BailoutId(local_id(0)); } | |
| 701 BailoutId StackCheckId() const override { return BackEdgeId(); } | |
| 702 BailoutId BackEdgeId() const { return BailoutId(local_id(1)); } | |
| 703 | |
| 704 protected: | |
| 705 DoWhileStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos) | |
| 706 : IterationStatement(zone, labels, pos), cond_(NULL) {} | |
| 707 static int parent_num_ids() { return IterationStatement::num_ids(); } | |
| 708 | |
| 709 private: | |
| 710 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 711 | |
| 712 Expression* cond_; | |
| 713 }; | |
| 714 | |
| 715 | |
| 716 class WhileStatement final : public IterationStatement { | |
| 717 public: | |
| 718 DECLARE_NODE_TYPE(WhileStatement) | |
| 719 | |
| 720 void Initialize(Expression* cond, Statement* body) { | |
| 721 IterationStatement::Initialize(body); | |
| 722 cond_ = cond; | |
| 723 } | |
| 724 | |
| 725 Expression* cond() const { return cond_; } | |
| 726 | |
| 727 static int num_ids() { return parent_num_ids() + 1; } | |
| 728 BailoutId ContinueId() const override { return EntryId(); } | |
| 729 BailoutId StackCheckId() const override { return BodyId(); } | |
| 730 BailoutId BodyId() const { return BailoutId(local_id(0)); } | |
| 731 | |
| 732 protected: | |
| 733 WhileStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos) | |
| 734 : IterationStatement(zone, labels, pos), cond_(NULL) {} | |
| 735 static int parent_num_ids() { return IterationStatement::num_ids(); } | |
| 736 | |
| 737 private: | |
| 738 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 739 | |
| 740 Expression* cond_; | |
| 741 }; | |
| 742 | |
| 743 | |
| 744 class ForStatement final : public IterationStatement { | |
| 745 public: | |
| 746 DECLARE_NODE_TYPE(ForStatement) | |
| 747 | |
| 748 void Initialize(Statement* init, | |
| 749 Expression* cond, | |
| 750 Statement* next, | |
| 751 Statement* body) { | |
| 752 IterationStatement::Initialize(body); | |
| 753 init_ = init; | |
| 754 cond_ = cond; | |
| 755 next_ = next; | |
| 756 } | |
| 757 | |
| 758 Statement* init() const { return init_; } | |
| 759 Expression* cond() const { return cond_; } | |
| 760 Statement* next() const { return next_; } | |
| 761 | |
| 762 static int num_ids() { return parent_num_ids() + 2; } | |
| 763 BailoutId ContinueId() const override { return BailoutId(local_id(0)); } | |
| 764 BailoutId StackCheckId() const override { return BodyId(); } | |
| 765 BailoutId BodyId() const { return BailoutId(local_id(1)); } | |
| 766 | |
| 767 protected: | |
| 768 ForStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos) | |
| 769 : IterationStatement(zone, labels, pos), | |
| 770 init_(NULL), | |
| 771 cond_(NULL), | |
| 772 next_(NULL) {} | |
| 773 static int parent_num_ids() { return IterationStatement::num_ids(); } | |
| 774 | |
| 775 private: | |
| 776 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 777 | |
| 778 Statement* init_; | |
| 779 Expression* cond_; | |
| 780 Statement* next_; | |
| 781 }; | |
| 782 | |
| 783 | |
| 784 class ForEachStatement : public IterationStatement { | |
| 785 public: | |
| 786 enum VisitMode { | |
| 787 ENUMERATE, // for (each in subject) body; | |
| 788 ITERATE // for (each of subject) body; | |
| 789 }; | |
| 790 | |
| 791 void Initialize(Expression* each, Expression* subject, Statement* body) { | |
| 792 IterationStatement::Initialize(body); | |
| 793 each_ = each; | |
| 794 subject_ = subject; | |
| 795 } | |
| 796 | |
| 797 Expression* each() const { return each_; } | |
| 798 Expression* subject() const { return subject_; } | |
| 799 | |
| 800 void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, | |
| 801 FeedbackVectorSlotCache* cache) override; | |
| 802 FeedbackVectorSlot EachFeedbackSlot() const { return each_slot_; } | |
| 803 | |
| 804 protected: | |
| 805 ForEachStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos) | |
| 806 : IterationStatement(zone, labels, pos), each_(NULL), subject_(NULL) {} | |
| 807 | |
| 808 private: | |
| 809 Expression* each_; | |
| 810 Expression* subject_; | |
| 811 FeedbackVectorSlot each_slot_; | |
| 812 }; | |
| 813 | |
| 814 | |
| 815 class ForInStatement final : public ForEachStatement { | |
| 816 public: | |
| 817 DECLARE_NODE_TYPE(ForInStatement) | |
| 818 | |
| 819 Expression* enumerable() const { | |
| 820 return subject(); | |
| 821 } | |
| 822 | |
| 823 // Type feedback information. | |
| 824 void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, | |
| 825 FeedbackVectorSlotCache* cache) override { | |
| 826 ForEachStatement::AssignFeedbackVectorSlots(isolate, spec, cache); | |
| 827 for_in_feedback_slot_ = spec->AddGeneralSlot(); | |
| 828 } | |
| 829 | |
| 830 FeedbackVectorSlot ForInFeedbackSlot() { | |
| 831 DCHECK(!for_in_feedback_slot_.IsInvalid()); | |
| 832 return for_in_feedback_slot_; | |
| 833 } | |
| 834 | |
| 835 enum ForInType { FAST_FOR_IN, SLOW_FOR_IN }; | |
| 836 ForInType for_in_type() const { return for_in_type_; } | |
| 837 void set_for_in_type(ForInType type) { for_in_type_ = type; } | |
| 838 | |
| 839 static int num_ids() { return parent_num_ids() + 6; } | |
| 840 BailoutId BodyId() const { return BailoutId(local_id(0)); } | |
| 841 BailoutId PrepareId() const { return BailoutId(local_id(1)); } | |
| 842 BailoutId EnumId() const { return BailoutId(local_id(2)); } | |
| 843 BailoutId ToObjectId() const { return BailoutId(local_id(3)); } | |
| 844 BailoutId FilterId() const { return BailoutId(local_id(4)); } | |
| 845 BailoutId AssignmentId() const { return BailoutId(local_id(5)); } | |
| 846 BailoutId ContinueId() const override { return EntryId(); } | |
| 847 BailoutId StackCheckId() const override { return BodyId(); } | |
| 848 | |
| 849 protected: | |
| 850 ForInStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos) | |
| 851 : ForEachStatement(zone, labels, pos), for_in_type_(SLOW_FOR_IN) {} | |
| 852 static int parent_num_ids() { return ForEachStatement::num_ids(); } | |
| 853 | |
| 854 private: | |
| 855 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 856 | |
| 857 ForInType for_in_type_; | |
| 858 FeedbackVectorSlot for_in_feedback_slot_; | |
| 859 }; | |
| 860 | |
| 861 | |
| 862 class ForOfStatement final : public ForEachStatement { | |
| 863 public: | |
| 864 DECLARE_NODE_TYPE(ForOfStatement) | |
| 865 | |
| 866 void Initialize(Expression* each, | |
| 867 Expression* subject, | |
| 868 Statement* body, | |
| 869 Expression* assign_iterator, | |
| 870 Expression* next_result, | |
| 871 Expression* result_done, | |
| 872 Expression* assign_each) { | |
| 873 ForEachStatement::Initialize(each, subject, body); | |
| 874 assign_iterator_ = assign_iterator; | |
| 875 next_result_ = next_result; | |
| 876 result_done_ = result_done; | |
| 877 assign_each_ = assign_each; | |
| 878 } | |
| 879 | |
| 880 Expression* iterable() const { | |
| 881 return subject(); | |
| 882 } | |
| 883 | |
| 884 // iterator = subject[Symbol.iterator]() | |
| 885 Expression* assign_iterator() const { | |
| 886 return assign_iterator_; | |
| 887 } | |
| 888 | |
| 889 // result = iterator.next() // with type check | |
| 890 Expression* next_result() const { | |
| 891 return next_result_; | |
| 892 } | |
| 893 | |
| 894 // result.done | |
| 895 Expression* result_done() const { | |
| 896 return result_done_; | |
| 897 } | |
| 898 | |
| 899 // each = result.value | |
| 900 Expression* assign_each() const { | |
| 901 return assign_each_; | |
| 902 } | |
| 903 | |
| 904 BailoutId ContinueId() const override { return EntryId(); } | |
| 905 BailoutId StackCheckId() const override { return BackEdgeId(); } | |
| 906 | |
| 907 static int num_ids() { return parent_num_ids() + 1; } | |
| 908 BailoutId BackEdgeId() const { return BailoutId(local_id(0)); } | |
| 909 | |
| 910 protected: | |
| 911 ForOfStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos) | |
| 912 : ForEachStatement(zone, labels, pos), | |
| 913 assign_iterator_(NULL), | |
| 914 next_result_(NULL), | |
| 915 result_done_(NULL), | |
| 916 assign_each_(NULL) {} | |
| 917 static int parent_num_ids() { return ForEachStatement::num_ids(); } | |
| 918 | |
| 919 private: | |
| 920 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 921 | |
| 922 Expression* assign_iterator_; | |
| 923 Expression* next_result_; | |
| 924 Expression* result_done_; | |
| 925 Expression* assign_each_; | |
| 926 }; | |
| 927 | |
| 928 | |
| 929 class ExpressionStatement final : public Statement { | |
| 930 public: | |
| 931 DECLARE_NODE_TYPE(ExpressionStatement) | |
| 932 | |
| 933 void set_expression(Expression* e) { expression_ = e; } | |
| 934 Expression* expression() const { return expression_; } | |
| 935 bool IsJump() const override { return expression_->IsThrow(); } | |
| 936 | |
| 937 protected: | |
| 938 ExpressionStatement(Zone* zone, Expression* expression, int pos) | |
| 939 : Statement(zone, pos), expression_(expression) { } | |
| 940 | |
| 941 private: | |
| 942 Expression* expression_; | |
| 943 }; | |
| 944 | |
| 945 | |
| 946 class JumpStatement : public Statement { | |
| 947 public: | |
| 948 bool IsJump() const final { return true; } | |
| 949 | |
| 950 protected: | |
| 951 explicit JumpStatement(Zone* zone, int pos) : Statement(zone, pos) {} | |
| 952 }; | |
| 953 | |
| 954 | |
| 955 class ContinueStatement final : public JumpStatement { | |
| 956 public: | |
| 957 DECLARE_NODE_TYPE(ContinueStatement) | |
| 958 | |
| 959 IterationStatement* target() const { return target_; } | |
| 960 | |
| 961 protected: | |
| 962 explicit ContinueStatement(Zone* zone, IterationStatement* target, int pos) | |
| 963 : JumpStatement(zone, pos), target_(target) { } | |
| 964 | |
| 965 private: | |
| 966 IterationStatement* target_; | |
| 967 }; | |
| 968 | |
| 969 | |
| 970 class BreakStatement final : public JumpStatement { | |
| 971 public: | |
| 972 DECLARE_NODE_TYPE(BreakStatement) | |
| 973 | |
| 974 BreakableStatement* target() const { return target_; } | |
| 975 | |
| 976 protected: | |
| 977 explicit BreakStatement(Zone* zone, BreakableStatement* target, int pos) | |
| 978 : JumpStatement(zone, pos), target_(target) { } | |
| 979 | |
| 980 private: | |
| 981 BreakableStatement* target_; | |
| 982 }; | |
| 983 | |
| 984 | |
| 985 class ReturnStatement final : public JumpStatement { | |
| 986 public: | |
| 987 DECLARE_NODE_TYPE(ReturnStatement) | |
| 988 | |
| 989 Expression* expression() const { return expression_; } | |
| 990 | |
| 991 protected: | |
| 992 explicit ReturnStatement(Zone* zone, Expression* expression, int pos) | |
| 993 : JumpStatement(zone, pos), expression_(expression) { } | |
| 994 | |
| 995 private: | |
| 996 Expression* expression_; | |
| 997 }; | |
| 998 | |
| 999 | |
| 1000 class WithStatement final : public Statement { | |
| 1001 public: | |
| 1002 DECLARE_NODE_TYPE(WithStatement) | |
| 1003 | |
| 1004 Scope* scope() { return scope_; } | |
| 1005 Expression* expression() const { return expression_; } | |
| 1006 Statement* statement() const { return statement_; } | |
| 1007 void set_statement(Statement* s) { statement_ = s; } | |
| 1008 | |
| 1009 void set_base_id(int id) { base_id_ = id; } | |
| 1010 static int num_ids() { return parent_num_ids() + 1; } | |
| 1011 BailoutId EntryId() const { return BailoutId(local_id(0)); } | |
| 1012 | |
| 1013 protected: | |
| 1014 WithStatement(Zone* zone, Scope* scope, Expression* expression, | |
| 1015 Statement* statement, int pos) | |
| 1016 : Statement(zone, pos), | |
| 1017 scope_(scope), | |
| 1018 expression_(expression), | |
| 1019 statement_(statement), | |
| 1020 base_id_(BailoutId::None().ToInt()) {} | |
| 1021 static int parent_num_ids() { return 0; } | |
| 1022 | |
| 1023 int base_id() const { | |
| 1024 DCHECK(!BailoutId(base_id_).IsNone()); | |
| 1025 return base_id_; | |
| 1026 } | |
| 1027 | |
| 1028 private: | |
| 1029 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 1030 | |
| 1031 Scope* scope_; | |
| 1032 Expression* expression_; | |
| 1033 Statement* statement_; | |
| 1034 int base_id_; | |
| 1035 }; | |
| 1036 | |
| 1037 | |
| 1038 class CaseClause final : public Expression { | |
| 1039 public: | |
| 1040 DECLARE_NODE_TYPE(CaseClause) | |
| 1041 | |
| 1042 bool is_default() const { return label_ == NULL; } | |
| 1043 Expression* label() const { | |
| 1044 CHECK(!is_default()); | |
| 1045 return label_; | |
| 1046 } | |
| 1047 Label* body_target() { return &body_target_; } | |
| 1048 ZoneList<Statement*>* statements() const { return statements_; } | |
| 1049 | |
| 1050 static int num_ids() { return parent_num_ids() + 2; } | |
| 1051 BailoutId EntryId() const { return BailoutId(local_id(0)); } | |
| 1052 TypeFeedbackId CompareId() { return TypeFeedbackId(local_id(1)); } | |
| 1053 | |
| 1054 Type* compare_type() { return compare_type_; } | |
| 1055 void set_compare_type(Type* type) { compare_type_ = type; } | |
| 1056 | |
| 1057 protected: | |
| 1058 static int parent_num_ids() { return Expression::num_ids(); } | |
| 1059 | |
| 1060 private: | |
| 1061 CaseClause(Zone* zone, Expression* label, ZoneList<Statement*>* statements, | |
| 1062 int pos); | |
| 1063 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 1064 | |
| 1065 Expression* label_; | |
| 1066 Label body_target_; | |
| 1067 ZoneList<Statement*>* statements_; | |
| 1068 Type* compare_type_; | |
| 1069 }; | |
| 1070 | |
| 1071 | |
| 1072 class SwitchStatement final : public BreakableStatement { | |
| 1073 public: | |
| 1074 DECLARE_NODE_TYPE(SwitchStatement) | |
| 1075 | |
| 1076 void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) { | |
| 1077 tag_ = tag; | |
| 1078 cases_ = cases; | |
| 1079 } | |
| 1080 | |
| 1081 Expression* tag() const { return tag_; } | |
| 1082 ZoneList<CaseClause*>* cases() const { return cases_; } | |
| 1083 | |
| 1084 protected: | |
| 1085 SwitchStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos) | |
| 1086 : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos), | |
| 1087 tag_(NULL), | |
| 1088 cases_(NULL) {} | |
| 1089 | |
| 1090 private: | |
| 1091 Expression* tag_; | |
| 1092 ZoneList<CaseClause*>* cases_; | |
| 1093 }; | |
| 1094 | |
| 1095 | |
| 1096 // If-statements always have non-null references to their then- and | |
| 1097 // else-parts. When parsing if-statements with no explicit else-part, | |
| 1098 // the parser implicitly creates an empty statement. Use the | |
| 1099 // HasThenStatement() and HasElseStatement() functions to check if a | |
| 1100 // given if-statement has a then- or an else-part containing code. | |
| 1101 class IfStatement final : public Statement { | |
| 1102 public: | |
| 1103 DECLARE_NODE_TYPE(IfStatement) | |
| 1104 | |
| 1105 bool HasThenStatement() const { return !then_statement()->IsEmpty(); } | |
| 1106 bool HasElseStatement() const { return !else_statement()->IsEmpty(); } | |
| 1107 | |
| 1108 Expression* condition() const { return condition_; } | |
| 1109 Statement* then_statement() const { return then_statement_; } | |
| 1110 Statement* else_statement() const { return else_statement_; } | |
| 1111 | |
| 1112 void set_then_statement(Statement* s) { then_statement_ = s; } | |
| 1113 void set_else_statement(Statement* s) { else_statement_ = s; } | |
| 1114 | |
| 1115 bool IsJump() const override { | |
| 1116 return HasThenStatement() && then_statement()->IsJump() | |
| 1117 && HasElseStatement() && else_statement()->IsJump(); | |
| 1118 } | |
| 1119 | |
| 1120 void set_base_id(int id) { base_id_ = id; } | |
| 1121 static int num_ids() { return parent_num_ids() + 3; } | |
| 1122 BailoutId IfId() const { return BailoutId(local_id(0)); } | |
| 1123 BailoutId ThenId() const { return BailoutId(local_id(1)); } | |
| 1124 BailoutId ElseId() const { return BailoutId(local_id(2)); } | |
| 1125 | |
| 1126 protected: | |
| 1127 IfStatement(Zone* zone, Expression* condition, Statement* then_statement, | |
| 1128 Statement* else_statement, int pos) | |
| 1129 : Statement(zone, pos), | |
| 1130 condition_(condition), | |
| 1131 then_statement_(then_statement), | |
| 1132 else_statement_(else_statement), | |
| 1133 base_id_(BailoutId::None().ToInt()) {} | |
| 1134 static int parent_num_ids() { return 0; } | |
| 1135 | |
| 1136 int base_id() const { | |
| 1137 DCHECK(!BailoutId(base_id_).IsNone()); | |
| 1138 return base_id_; | |
| 1139 } | |
| 1140 | |
| 1141 private: | |
| 1142 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 1143 | |
| 1144 Expression* condition_; | |
| 1145 Statement* then_statement_; | |
| 1146 Statement* else_statement_; | |
| 1147 int base_id_; | |
| 1148 }; | |
| 1149 | |
| 1150 | |
| 1151 class TryStatement : public Statement { | |
| 1152 public: | |
| 1153 Block* try_block() const { return try_block_; } | |
| 1154 void set_try_block(Block* b) { try_block_ = b; } | |
| 1155 | |
| 1156 void set_base_id(int id) { base_id_ = id; } | |
| 1157 static int num_ids() { return parent_num_ids() + 1; } | |
| 1158 BailoutId HandlerId() const { return BailoutId(local_id(0)); } | |
| 1159 | |
| 1160 protected: | |
| 1161 TryStatement(Zone* zone, Block* try_block, int pos) | |
| 1162 : Statement(zone, pos), | |
| 1163 try_block_(try_block), | |
| 1164 base_id_(BailoutId::None().ToInt()) {} | |
| 1165 static int parent_num_ids() { return 0; } | |
| 1166 | |
| 1167 int base_id() const { | |
| 1168 DCHECK(!BailoutId(base_id_).IsNone()); | |
| 1169 return base_id_; | |
| 1170 } | |
| 1171 | |
| 1172 private: | |
| 1173 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 1174 | |
| 1175 Block* try_block_; | |
| 1176 int base_id_; | |
| 1177 }; | |
| 1178 | |
| 1179 | |
| 1180 class TryCatchStatement final : public TryStatement { | |
| 1181 public: | |
| 1182 DECLARE_NODE_TYPE(TryCatchStatement) | |
| 1183 | |
| 1184 Scope* scope() { return scope_; } | |
| 1185 Variable* variable() { return variable_; } | |
| 1186 Block* catch_block() const { return catch_block_; } | |
| 1187 void set_catch_block(Block* b) { catch_block_ = b; } | |
| 1188 | |
| 1189 protected: | |
| 1190 TryCatchStatement(Zone* zone, Block* try_block, Scope* scope, | |
| 1191 Variable* variable, Block* catch_block, int pos) | |
| 1192 : TryStatement(zone, try_block, pos), | |
| 1193 scope_(scope), | |
| 1194 variable_(variable), | |
| 1195 catch_block_(catch_block) {} | |
| 1196 | |
| 1197 private: | |
| 1198 Scope* scope_; | |
| 1199 Variable* variable_; | |
| 1200 Block* catch_block_; | |
| 1201 }; | |
| 1202 | |
| 1203 | |
| 1204 class TryFinallyStatement final : public TryStatement { | |
| 1205 public: | |
| 1206 DECLARE_NODE_TYPE(TryFinallyStatement) | |
| 1207 | |
| 1208 Block* finally_block() const { return finally_block_; } | |
| 1209 void set_finally_block(Block* b) { finally_block_ = b; } | |
| 1210 | |
| 1211 protected: | |
| 1212 TryFinallyStatement(Zone* zone, Block* try_block, Block* finally_block, | |
| 1213 int pos) | |
| 1214 : TryStatement(zone, try_block, pos), finally_block_(finally_block) {} | |
| 1215 | |
| 1216 private: | |
| 1217 Block* finally_block_; | |
| 1218 }; | |
| 1219 | |
| 1220 | |
| 1221 class DebuggerStatement final : public Statement { | |
| 1222 public: | |
| 1223 DECLARE_NODE_TYPE(DebuggerStatement) | |
| 1224 | |
| 1225 void set_base_id(int id) { base_id_ = id; } | |
| 1226 static int num_ids() { return parent_num_ids() + 1; } | |
| 1227 BailoutId DebugBreakId() const { return BailoutId(local_id(0)); } | |
| 1228 | |
| 1229 protected: | |
| 1230 explicit DebuggerStatement(Zone* zone, int pos) | |
| 1231 : Statement(zone, pos), base_id_(BailoutId::None().ToInt()) {} | |
| 1232 static int parent_num_ids() { return 0; } | |
| 1233 | |
| 1234 int base_id() const { | |
| 1235 DCHECK(!BailoutId(base_id_).IsNone()); | |
| 1236 return base_id_; | |
| 1237 } | |
| 1238 | |
| 1239 private: | |
| 1240 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 1241 | |
| 1242 int base_id_; | |
| 1243 }; | |
| 1244 | |
| 1245 | |
| 1246 class EmptyStatement final : public Statement { | |
| 1247 public: | |
| 1248 DECLARE_NODE_TYPE(EmptyStatement) | |
| 1249 | |
| 1250 protected: | |
| 1251 explicit EmptyStatement(Zone* zone, int pos): Statement(zone, pos) {} | |
| 1252 }; | |
| 1253 | |
| 1254 | |
| 1255 // Delegates to another statement, which may be overwritten. | |
| 1256 // This was introduced to implement ES2015 Annex B3.3 for conditionally making | |
| 1257 // sloppy-mode block-scoped functions have a var binding, which is changed | |
| 1258 // from one statement to another during parsing. | |
| 1259 class SloppyBlockFunctionStatement final : public Statement { | |
| 1260 public: | |
| 1261 DECLARE_NODE_TYPE(SloppyBlockFunctionStatement) | |
| 1262 | |
| 1263 Statement* statement() const { return statement_; } | |
| 1264 void set_statement(Statement* statement) { statement_ = statement; } | |
| 1265 Scope* scope() const { return scope_; } | |
| 1266 | |
| 1267 private: | |
| 1268 SloppyBlockFunctionStatement(Zone* zone, Statement* statement, Scope* scope) | |
| 1269 : Statement(zone, RelocInfo::kNoPosition), | |
| 1270 statement_(statement), | |
| 1271 scope_(scope) {} | |
| 1272 | |
| 1273 Statement* statement_; | |
| 1274 Scope* const scope_; | |
| 1275 }; | |
| 1276 | |
| 1277 | |
| 1278 class Literal final : public Expression { | |
| 1279 public: | |
| 1280 DECLARE_NODE_TYPE(Literal) | |
| 1281 | |
| 1282 bool IsPropertyName() const override { return value_->IsPropertyName(); } | |
| 1283 | |
| 1284 Handle<String> AsPropertyName() { | |
| 1285 DCHECK(IsPropertyName()); | |
| 1286 return Handle<String>::cast(value()); | |
| 1287 } | |
| 1288 | |
| 1289 const AstRawString* AsRawPropertyName() { | |
| 1290 DCHECK(IsPropertyName()); | |
| 1291 return value_->AsString(); | |
| 1292 } | |
| 1293 | |
| 1294 bool ToBooleanIsTrue() const override { return value()->BooleanValue(); } | |
| 1295 bool ToBooleanIsFalse() const override { return !value()->BooleanValue(); } | |
| 1296 | |
| 1297 Handle<Object> value() const { return value_->value(); } | |
| 1298 const AstValue* raw_value() const { return value_; } | |
| 1299 | |
| 1300 // Support for using Literal as a HashMap key. NOTE: Currently, this works | |
| 1301 // only for string and number literals! | |
| 1302 uint32_t Hash(); | |
| 1303 static bool Match(void* literal1, void* literal2); | |
| 1304 | |
| 1305 static int num_ids() { return parent_num_ids() + 1; } | |
| 1306 TypeFeedbackId LiteralFeedbackId() const { | |
| 1307 return TypeFeedbackId(local_id(0)); | |
| 1308 } | |
| 1309 | |
| 1310 protected: | |
| 1311 Literal(Zone* zone, const AstValue* value, int position) | |
| 1312 : Expression(zone, position), value_(value) {} | |
| 1313 static int parent_num_ids() { return Expression::num_ids(); } | |
| 1314 | |
| 1315 private: | |
| 1316 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 1317 | |
| 1318 const AstValue* value_; | |
| 1319 }; | |
| 1320 | |
| 1321 | |
| 1322 class AstLiteralReindexer; | |
| 1323 | |
| 1324 // Base class for literals that needs space in the corresponding JSFunction. | |
| 1325 class MaterializedLiteral : public Expression { | |
| 1326 public: | |
| 1327 MaterializedLiteral* AsMaterializedLiteral() final { return this; } | |
| 1328 | |
| 1329 int literal_index() { return literal_index_; } | |
| 1330 | |
| 1331 int depth() const { | |
| 1332 // only callable after initialization. | |
| 1333 DCHECK(depth_ >= 1); | |
| 1334 return depth_; | |
| 1335 } | |
| 1336 | |
| 1337 bool is_strong() const { return is_strong_; } | |
| 1338 | |
| 1339 protected: | |
| 1340 MaterializedLiteral(Zone* zone, int literal_index, bool is_strong, int pos) | |
| 1341 : Expression(zone, pos), | |
| 1342 literal_index_(literal_index), | |
| 1343 is_simple_(false), | |
| 1344 is_strong_(is_strong), | |
| 1345 depth_(0) {} | |
| 1346 | |
| 1347 // A materialized literal is simple if the values consist of only | |
| 1348 // constants and simple object and array literals. | |
| 1349 bool is_simple() const { return is_simple_; } | |
| 1350 void set_is_simple(bool is_simple) { is_simple_ = is_simple; } | |
| 1351 friend class CompileTimeValue; | |
| 1352 | |
| 1353 void set_depth(int depth) { | |
| 1354 DCHECK(depth >= 1); | |
| 1355 depth_ = depth; | |
| 1356 } | |
| 1357 | |
| 1358 // Populate the constant properties/elements fixed array. | |
| 1359 void BuildConstants(Isolate* isolate); | |
| 1360 friend class ArrayLiteral; | |
| 1361 friend class ObjectLiteral; | |
| 1362 | |
| 1363 // If the expression is a literal, return the literal value; | |
| 1364 // if the expression is a materialized literal and is simple return a | |
| 1365 // compile time value as encoded by CompileTimeValue::GetValue(). | |
| 1366 // Otherwise, return undefined literal as the placeholder | |
| 1367 // in the object literal boilerplate. | |
| 1368 Handle<Object> GetBoilerplateValue(Expression* expression, Isolate* isolate); | |
| 1369 | |
| 1370 private: | |
| 1371 int literal_index_; | |
| 1372 bool is_simple_; | |
| 1373 bool is_strong_; | |
| 1374 int depth_; | |
| 1375 | |
| 1376 friend class AstLiteralReindexer; | |
| 1377 }; | |
| 1378 | |
| 1379 | |
| 1380 // Property is used for passing information | |
| 1381 // about an object literal's properties from the parser | |
| 1382 // to the code generator. | |
| 1383 class ObjectLiteralProperty final : public ZoneObject { | |
| 1384 public: | |
| 1385 enum Kind { | |
| 1386 CONSTANT, // Property with constant value (compile time). | |
| 1387 COMPUTED, // Property with computed value (execution time). | |
| 1388 MATERIALIZED_LITERAL, // Property value is a materialized literal. | |
| 1389 GETTER, SETTER, // Property is an accessor function. | |
| 1390 PROTOTYPE // Property is __proto__. | |
| 1391 }; | |
| 1392 | |
| 1393 Expression* key() { return key_; } | |
| 1394 Expression* value() { return value_; } | |
| 1395 Kind kind() { return kind_; } | |
| 1396 | |
| 1397 // Type feedback information. | |
| 1398 bool IsMonomorphic() { return !receiver_type_.is_null(); } | |
| 1399 Handle<Map> GetReceiverType() { return receiver_type_; } | |
| 1400 | |
| 1401 bool IsCompileTimeValue(); | |
| 1402 | |
| 1403 void set_emit_store(bool emit_store); | |
| 1404 bool emit_store(); | |
| 1405 | |
| 1406 bool is_static() const { return is_static_; } | |
| 1407 bool is_computed_name() const { return is_computed_name_; } | |
| 1408 | |
| 1409 FeedbackVectorSlot GetSlot(int offset = 0) const { | |
| 1410 DCHECK_LT(offset, static_cast<int>(arraysize(slots_))); | |
| 1411 return slots_[offset]; | |
| 1412 } | |
| 1413 void SetSlot(FeedbackVectorSlot slot, int offset = 0) { | |
| 1414 DCHECK_LT(offset, static_cast<int>(arraysize(slots_))); | |
| 1415 slots_[offset] = slot; | |
| 1416 } | |
| 1417 | |
| 1418 void set_receiver_type(Handle<Map> map) { receiver_type_ = map; } | |
| 1419 | |
| 1420 protected: | |
| 1421 friend class AstNodeFactory; | |
| 1422 | |
| 1423 ObjectLiteralProperty(Expression* key, Expression* value, Kind kind, | |
| 1424 bool is_static, bool is_computed_name); | |
| 1425 ObjectLiteralProperty(AstValueFactory* ast_value_factory, Expression* key, | |
| 1426 Expression* value, bool is_static, | |
| 1427 bool is_computed_name); | |
| 1428 | |
| 1429 private: | |
| 1430 Expression* key_; | |
| 1431 Expression* value_; | |
| 1432 FeedbackVectorSlot slots_[2]; | |
| 1433 Kind kind_; | |
| 1434 bool emit_store_; | |
| 1435 bool is_static_; | |
| 1436 bool is_computed_name_; | |
| 1437 Handle<Map> receiver_type_; | |
| 1438 }; | |
| 1439 | |
| 1440 | |
| 1441 // An object literal has a boilerplate object that is used | |
| 1442 // for minimizing the work when constructing it at runtime. | |
| 1443 class ObjectLiteral final : public MaterializedLiteral { | |
| 1444 public: | |
| 1445 typedef ObjectLiteralProperty Property; | |
| 1446 | |
| 1447 DECLARE_NODE_TYPE(ObjectLiteral) | |
| 1448 | |
| 1449 Handle<FixedArray> constant_properties() const { | |
| 1450 return constant_properties_; | |
| 1451 } | |
| 1452 int properties_count() const { return constant_properties_->length() / 2; } | |
| 1453 ZoneList<Property*>* properties() const { return properties_; } | |
| 1454 bool fast_elements() const { return fast_elements_; } | |
| 1455 bool may_store_doubles() const { return may_store_doubles_; } | |
| 1456 bool has_function() const { return has_function_; } | |
| 1457 bool has_elements() const { return has_elements_; } | |
| 1458 | |
| 1459 // Decide if a property should be in the object boilerplate. | |
| 1460 static bool IsBoilerplateProperty(Property* property); | |
| 1461 | |
| 1462 // Populate the constant properties fixed array. | |
| 1463 void BuildConstantProperties(Isolate* isolate); | |
| 1464 | |
| 1465 // Mark all computed expressions that are bound to a key that | |
| 1466 // is shadowed by a later occurrence of the same key. For the | |
| 1467 // marked expressions, no store code is emitted. | |
| 1468 void CalculateEmitStore(Zone* zone); | |
| 1469 | |
| 1470 // Assemble bitfield of flags for the CreateObjectLiteral helper. | |
| 1471 int ComputeFlags(bool disable_mementos = false) const { | |
| 1472 int flags = fast_elements() ? kFastElements : kNoFlags; | |
| 1473 flags |= has_function() ? kHasFunction : kNoFlags; | |
| 1474 if (depth() == 1 && !has_elements() && !may_store_doubles()) { | |
| 1475 flags |= kShallowProperties; | |
| 1476 } | |
| 1477 if (disable_mementos) { | |
| 1478 flags |= kDisableMementos; | |
| 1479 } | |
| 1480 if (is_strong()) { | |
| 1481 flags |= kIsStrong; | |
| 1482 } | |
| 1483 return flags; | |
| 1484 } | |
| 1485 | |
| 1486 enum Flags { | |
| 1487 kNoFlags = 0, | |
| 1488 kFastElements = 1, | |
| 1489 kHasFunction = 1 << 1, | |
| 1490 kShallowProperties = 1 << 2, | |
| 1491 kDisableMementos = 1 << 3, | |
| 1492 kIsStrong = 1 << 4 | |
| 1493 }; | |
| 1494 | |
| 1495 struct Accessors: public ZoneObject { | |
| 1496 Accessors() : getter(NULL), setter(NULL) {} | |
| 1497 ObjectLiteralProperty* getter; | |
| 1498 ObjectLiteralProperty* setter; | |
| 1499 }; | |
| 1500 | |
| 1501 BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); } | |
| 1502 | |
| 1503 // Return an AST id for a property that is used in simulate instructions. | |
| 1504 BailoutId GetIdForProperty(int i) { return BailoutId(local_id(i + 1)); } | |
| 1505 | |
| 1506 // Unlike other AST nodes, this number of bailout IDs allocated for an | |
| 1507 // ObjectLiteral can vary, so num_ids() is not a static method. | |
| 1508 int num_ids() const { return parent_num_ids() + 1 + properties()->length(); } | |
| 1509 | |
| 1510 // Object literals need one feedback slot for each non-trivial value, as well | |
| 1511 // as some slots for home objects. | |
| 1512 void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, | |
| 1513 FeedbackVectorSlotCache* cache) override; | |
| 1514 | |
| 1515 protected: | |
| 1516 ObjectLiteral(Zone* zone, ZoneList<Property*>* properties, int literal_index, | |
| 1517 int boilerplate_properties, bool has_function, bool is_strong, | |
| 1518 int pos) | |
| 1519 : MaterializedLiteral(zone, literal_index, is_strong, pos), | |
| 1520 properties_(properties), | |
| 1521 boilerplate_properties_(boilerplate_properties), | |
| 1522 fast_elements_(false), | |
| 1523 has_elements_(false), | |
| 1524 may_store_doubles_(false), | |
| 1525 has_function_(has_function) {} | |
| 1526 static int parent_num_ids() { return MaterializedLiteral::num_ids(); } | |
| 1527 | |
| 1528 private: | |
| 1529 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 1530 Handle<FixedArray> constant_properties_; | |
| 1531 ZoneList<Property*>* properties_; | |
| 1532 int boilerplate_properties_; | |
| 1533 bool fast_elements_; | |
| 1534 bool has_elements_; | |
| 1535 bool may_store_doubles_; | |
| 1536 bool has_function_; | |
| 1537 FeedbackVectorSlot slot_; | |
| 1538 }; | |
| 1539 | |
| 1540 | |
| 1541 // A map from property names to getter/setter pairs allocated in the zone. | |
| 1542 class AccessorTable : public TemplateHashMap<Literal, ObjectLiteral::Accessors, | |
| 1543 ZoneAllocationPolicy> { | |
| 1544 public: | |
| 1545 explicit AccessorTable(Zone* zone) | |
| 1546 : TemplateHashMap<Literal, ObjectLiteral::Accessors, | |
| 1547 ZoneAllocationPolicy>(Literal::Match, | |
| 1548 ZoneAllocationPolicy(zone)), | |
| 1549 zone_(zone) {} | |
| 1550 | |
| 1551 Iterator lookup(Literal* literal) { | |
| 1552 Iterator it = find(literal, true, ZoneAllocationPolicy(zone_)); | |
| 1553 if (it->second == NULL) it->second = new (zone_) ObjectLiteral::Accessors(); | |
| 1554 return it; | |
| 1555 } | |
| 1556 | |
| 1557 private: | |
| 1558 Zone* zone_; | |
| 1559 }; | |
| 1560 | |
| 1561 | |
| 1562 // Node for capturing a regexp literal. | |
| 1563 class RegExpLiteral final : public MaterializedLiteral { | |
| 1564 public: | |
| 1565 DECLARE_NODE_TYPE(RegExpLiteral) | |
| 1566 | |
| 1567 Handle<String> pattern() const { return pattern_->string(); } | |
| 1568 int flags() const { return flags_; } | |
| 1569 | |
| 1570 protected: | |
| 1571 RegExpLiteral(Zone* zone, const AstRawString* pattern, int flags, | |
| 1572 int literal_index, bool is_strong, int pos) | |
| 1573 : MaterializedLiteral(zone, literal_index, is_strong, pos), | |
| 1574 pattern_(pattern), | |
| 1575 flags_(flags) { | |
| 1576 set_depth(1); | |
| 1577 } | |
| 1578 | |
| 1579 private: | |
| 1580 const AstRawString* const pattern_; | |
| 1581 int const flags_; | |
| 1582 }; | |
| 1583 | |
| 1584 | |
| 1585 // An array literal has a literals object that is used | |
| 1586 // for minimizing the work when constructing it at runtime. | |
| 1587 class ArrayLiteral final : public MaterializedLiteral { | |
| 1588 public: | |
| 1589 DECLARE_NODE_TYPE(ArrayLiteral) | |
| 1590 | |
| 1591 Handle<FixedArray> constant_elements() const { return constant_elements_; } | |
| 1592 ElementsKind constant_elements_kind() const { | |
| 1593 DCHECK_EQ(2, constant_elements_->length()); | |
| 1594 return static_cast<ElementsKind>( | |
| 1595 Smi::cast(constant_elements_->get(0))->value()); | |
| 1596 } | |
| 1597 | |
| 1598 ZoneList<Expression*>* values() const { return values_; } | |
| 1599 | |
| 1600 BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); } | |
| 1601 | |
| 1602 // Return an AST id for an element that is used in simulate instructions. | |
| 1603 BailoutId GetIdForElement(int i) { return BailoutId(local_id(i + 1)); } | |
| 1604 | |
| 1605 // Unlike other AST nodes, this number of bailout IDs allocated for an | |
| 1606 // ArrayLiteral can vary, so num_ids() is not a static method. | |
| 1607 int num_ids() const { return parent_num_ids() + 1 + values()->length(); } | |
| 1608 | |
| 1609 // Populate the constant elements fixed array. | |
| 1610 void BuildConstantElements(Isolate* isolate); | |
| 1611 | |
| 1612 // Assemble bitfield of flags for the CreateArrayLiteral helper. | |
| 1613 int ComputeFlags(bool disable_mementos = false) const { | |
| 1614 int flags = depth() == 1 ? kShallowElements : kNoFlags; | |
| 1615 if (disable_mementos) { | |
| 1616 flags |= kDisableMementos; | |
| 1617 } | |
| 1618 if (is_strong()) { | |
| 1619 flags |= kIsStrong; | |
| 1620 } | |
| 1621 return flags; | |
| 1622 } | |
| 1623 | |
| 1624 enum Flags { | |
| 1625 kNoFlags = 0, | |
| 1626 kShallowElements = 1, | |
| 1627 kDisableMementos = 1 << 1, | |
| 1628 kIsStrong = 1 << 2 | |
| 1629 }; | |
| 1630 | |
| 1631 void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, | |
| 1632 FeedbackVectorSlotCache* cache) override; | |
| 1633 FeedbackVectorSlot LiteralFeedbackSlot() const { return literal_slot_; } | |
| 1634 | |
| 1635 protected: | |
| 1636 ArrayLiteral(Zone* zone, ZoneList<Expression*>* values, | |
| 1637 int first_spread_index, int literal_index, bool is_strong, | |
| 1638 int pos) | |
| 1639 : MaterializedLiteral(zone, literal_index, is_strong, pos), | |
| 1640 values_(values), | |
| 1641 first_spread_index_(first_spread_index) {} | |
| 1642 static int parent_num_ids() { return MaterializedLiteral::num_ids(); } | |
| 1643 | |
| 1644 private: | |
| 1645 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 1646 | |
| 1647 Handle<FixedArray> constant_elements_; | |
| 1648 ZoneList<Expression*>* values_; | |
| 1649 int first_spread_index_; | |
| 1650 FeedbackVectorSlot literal_slot_; | |
| 1651 }; | |
| 1652 | |
| 1653 | |
| 1654 class VariableProxy final : public Expression { | |
| 1655 public: | |
| 1656 DECLARE_NODE_TYPE(VariableProxy) | |
| 1657 | |
| 1658 bool IsValidReferenceExpression() const override { | |
| 1659 return !is_this() && !is_new_target(); | |
| 1660 } | |
| 1661 | |
| 1662 bool IsArguments() const { return is_resolved() && var()->is_arguments(); } | |
| 1663 | |
| 1664 Handle<String> name() const { return raw_name()->string(); } | |
| 1665 const AstRawString* raw_name() const { | |
| 1666 return is_resolved() ? var_->raw_name() : raw_name_; | |
| 1667 } | |
| 1668 | |
| 1669 Variable* var() const { | |
| 1670 DCHECK(is_resolved()); | |
| 1671 return var_; | |
| 1672 } | |
| 1673 void set_var(Variable* v) { | |
| 1674 DCHECK(!is_resolved()); | |
| 1675 DCHECK_NOT_NULL(v); | |
| 1676 var_ = v; | |
| 1677 } | |
| 1678 | |
| 1679 bool is_this() const { return IsThisField::decode(bit_field_); } | |
| 1680 | |
| 1681 bool is_assigned() const { return IsAssignedField::decode(bit_field_); } | |
| 1682 void set_is_assigned() { | |
| 1683 bit_field_ = IsAssignedField::update(bit_field_, true); | |
| 1684 } | |
| 1685 | |
| 1686 bool is_resolved() const { return IsResolvedField::decode(bit_field_); } | |
| 1687 void set_is_resolved() { | |
| 1688 bit_field_ = IsResolvedField::update(bit_field_, true); | |
| 1689 } | |
| 1690 | |
| 1691 bool is_new_target() const { return IsNewTargetField::decode(bit_field_); } | |
| 1692 void set_is_new_target() { | |
| 1693 bit_field_ = IsNewTargetField::update(bit_field_, true); | |
| 1694 } | |
| 1695 | |
| 1696 int end_position() const { return end_position_; } | |
| 1697 | |
| 1698 // Bind this proxy to the variable var. | |
| 1699 void BindTo(Variable* var); | |
| 1700 | |
| 1701 bool UsesVariableFeedbackSlot() const { | |
| 1702 return var()->IsUnallocated() || var()->IsLookupSlot(); | |
| 1703 } | |
| 1704 | |
| 1705 void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, | |
| 1706 FeedbackVectorSlotCache* cache) override; | |
| 1707 | |
| 1708 FeedbackVectorSlot VariableFeedbackSlot() { return variable_feedback_slot_; } | |
| 1709 | |
| 1710 static int num_ids() { return parent_num_ids() + 1; } | |
| 1711 BailoutId BeforeId() const { return BailoutId(local_id(0)); } | |
| 1712 | |
| 1713 protected: | |
| 1714 VariableProxy(Zone* zone, Variable* var, int start_position, | |
| 1715 int end_position); | |
| 1716 | |
| 1717 VariableProxy(Zone* zone, const AstRawString* name, | |
| 1718 Variable::Kind variable_kind, int start_position, | |
| 1719 int end_position); | |
| 1720 static int parent_num_ids() { return Expression::num_ids(); } | |
| 1721 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 1722 | |
| 1723 class IsThisField : public BitField8<bool, 0, 1> {}; | |
| 1724 class IsAssignedField : public BitField8<bool, 1, 1> {}; | |
| 1725 class IsResolvedField : public BitField8<bool, 2, 1> {}; | |
| 1726 class IsNewTargetField : public BitField8<bool, 3, 1> {}; | |
| 1727 | |
| 1728 // Start with 16-bit (or smaller) field, which should get packed together | |
| 1729 // with Expression's trailing 16-bit field. | |
| 1730 uint8_t bit_field_; | |
| 1731 FeedbackVectorSlot variable_feedback_slot_; | |
| 1732 union { | |
| 1733 const AstRawString* raw_name_; // if !is_resolved_ | |
| 1734 Variable* var_; // if is_resolved_ | |
| 1735 }; | |
| 1736 // Position is stored in the AstNode superclass, but VariableProxy needs to | |
| 1737 // know its end position too (for error messages). It cannot be inferred from | |
| 1738 // the variable name length because it can contain escapes. | |
| 1739 int end_position_; | |
| 1740 }; | |
| 1741 | |
| 1742 | |
| 1743 // Left-hand side can only be a property, a global or a (parameter or local) | |
| 1744 // slot. | |
| 1745 enum LhsKind { | |
| 1746 VARIABLE, | |
| 1747 NAMED_PROPERTY, | |
| 1748 KEYED_PROPERTY, | |
| 1749 NAMED_SUPER_PROPERTY, | |
| 1750 KEYED_SUPER_PROPERTY | |
| 1751 }; | |
| 1752 | |
| 1753 | |
| 1754 class Property final : public Expression { | |
| 1755 public: | |
| 1756 DECLARE_NODE_TYPE(Property) | |
| 1757 | |
| 1758 bool IsValidReferenceExpression() const override { return true; } | |
| 1759 | |
| 1760 Expression* obj() const { return obj_; } | |
| 1761 Expression* key() const { return key_; } | |
| 1762 | |
| 1763 static int num_ids() { return parent_num_ids() + 1; } | |
| 1764 BailoutId LoadId() const { return BailoutId(local_id(0)); } | |
| 1765 | |
| 1766 bool IsStringAccess() const { | |
| 1767 return IsStringAccessField::decode(bit_field_); | |
| 1768 } | |
| 1769 | |
| 1770 // Type feedback information. | |
| 1771 bool IsMonomorphic() override { return receiver_types_.length() == 1; } | |
| 1772 SmallMapList* GetReceiverTypes() override { return &receiver_types_; } | |
| 1773 KeyedAccessStoreMode GetStoreMode() const override { return STANDARD_STORE; } | |
| 1774 IcCheckType GetKeyType() const override { | |
| 1775 return KeyTypeField::decode(bit_field_); | |
| 1776 } | |
| 1777 bool IsUninitialized() const { | |
| 1778 return !is_for_call() && HasNoTypeInformation(); | |
| 1779 } | |
| 1780 bool HasNoTypeInformation() const { | |
| 1781 return GetInlineCacheState() == UNINITIALIZED; | |
| 1782 } | |
| 1783 InlineCacheState GetInlineCacheState() const { | |
| 1784 return InlineCacheStateField::decode(bit_field_); | |
| 1785 } | |
| 1786 void set_is_string_access(bool b) { | |
| 1787 bit_field_ = IsStringAccessField::update(bit_field_, b); | |
| 1788 } | |
| 1789 void set_key_type(IcCheckType key_type) { | |
| 1790 bit_field_ = KeyTypeField::update(bit_field_, key_type); | |
| 1791 } | |
| 1792 void set_inline_cache_state(InlineCacheState state) { | |
| 1793 bit_field_ = InlineCacheStateField::update(bit_field_, state); | |
| 1794 } | |
| 1795 void mark_for_call() { | |
| 1796 bit_field_ = IsForCallField::update(bit_field_, true); | |
| 1797 } | |
| 1798 bool is_for_call() const { return IsForCallField::decode(bit_field_); } | |
| 1799 | |
| 1800 bool IsSuperAccess() { return obj()->IsSuperPropertyReference(); } | |
| 1801 | |
| 1802 void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, | |
| 1803 FeedbackVectorSlotCache* cache) override { | |
| 1804 FeedbackVectorSlotKind kind = key()->IsPropertyName() | |
| 1805 ? FeedbackVectorSlotKind::LOAD_IC | |
| 1806 : FeedbackVectorSlotKind::KEYED_LOAD_IC; | |
| 1807 property_feedback_slot_ = spec->AddSlot(kind); | |
| 1808 } | |
| 1809 | |
| 1810 FeedbackVectorSlot PropertyFeedbackSlot() const { | |
| 1811 return property_feedback_slot_; | |
| 1812 } | |
| 1813 | |
| 1814 static LhsKind GetAssignType(Property* property) { | |
| 1815 if (property == NULL) return VARIABLE; | |
| 1816 bool super_access = property->IsSuperAccess(); | |
| 1817 return (property->key()->IsPropertyName()) | |
| 1818 ? (super_access ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY) | |
| 1819 : (super_access ? KEYED_SUPER_PROPERTY : KEYED_PROPERTY); | |
| 1820 } | |
| 1821 | |
| 1822 protected: | |
| 1823 Property(Zone* zone, Expression* obj, Expression* key, int pos) | |
| 1824 : Expression(zone, pos), | |
| 1825 bit_field_(IsForCallField::encode(false) | | |
| 1826 IsStringAccessField::encode(false) | | |
| 1827 InlineCacheStateField::encode(UNINITIALIZED)), | |
| 1828 obj_(obj), | |
| 1829 key_(key) {} | |
| 1830 static int parent_num_ids() { return Expression::num_ids(); } | |
| 1831 | |
| 1832 private: | |
| 1833 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 1834 | |
| 1835 class IsForCallField : public BitField8<bool, 0, 1> {}; | |
| 1836 class IsStringAccessField : public BitField8<bool, 1, 1> {}; | |
| 1837 class KeyTypeField : public BitField8<IcCheckType, 2, 1> {}; | |
| 1838 class InlineCacheStateField : public BitField8<InlineCacheState, 3, 4> {}; | |
| 1839 uint8_t bit_field_; | |
| 1840 FeedbackVectorSlot property_feedback_slot_; | |
| 1841 Expression* obj_; | |
| 1842 Expression* key_; | |
| 1843 SmallMapList receiver_types_; | |
| 1844 }; | |
| 1845 | |
| 1846 | |
| 1847 class Call final : public Expression { | |
| 1848 public: | |
| 1849 DECLARE_NODE_TYPE(Call) | |
| 1850 | |
| 1851 Expression* expression() const { return expression_; } | |
| 1852 ZoneList<Expression*>* arguments() const { return arguments_; } | |
| 1853 | |
| 1854 // Type feedback information. | |
| 1855 void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, | |
| 1856 FeedbackVectorSlotCache* cache) override; | |
| 1857 | |
| 1858 FeedbackVectorSlot CallFeedbackSlot() const { return stub_slot_; } | |
| 1859 | |
| 1860 FeedbackVectorSlot CallFeedbackICSlot() const { return ic_slot_; } | |
| 1861 | |
| 1862 SmallMapList* GetReceiverTypes() override { | |
| 1863 if (expression()->IsProperty()) { | |
| 1864 return expression()->AsProperty()->GetReceiverTypes(); | |
| 1865 } | |
| 1866 return NULL; | |
| 1867 } | |
| 1868 | |
| 1869 bool IsMonomorphic() override { | |
| 1870 if (expression()->IsProperty()) { | |
| 1871 return expression()->AsProperty()->IsMonomorphic(); | |
| 1872 } | |
| 1873 return !target_.is_null(); | |
| 1874 } | |
| 1875 | |
| 1876 bool global_call() const { | |
| 1877 VariableProxy* proxy = expression_->AsVariableProxy(); | |
| 1878 return proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot(); | |
| 1879 } | |
| 1880 | |
| 1881 bool known_global_function() const { | |
| 1882 return global_call() && !target_.is_null(); | |
| 1883 } | |
| 1884 | |
| 1885 Handle<JSFunction> target() { return target_; } | |
| 1886 | |
| 1887 Handle<AllocationSite> allocation_site() { return allocation_site_; } | |
| 1888 | |
| 1889 void SetKnownGlobalTarget(Handle<JSFunction> target) { | |
| 1890 target_ = target; | |
| 1891 set_is_uninitialized(false); | |
| 1892 } | |
| 1893 void set_target(Handle<JSFunction> target) { target_ = target; } | |
| 1894 void set_allocation_site(Handle<AllocationSite> site) { | |
| 1895 allocation_site_ = site; | |
| 1896 } | |
| 1897 | |
| 1898 static int num_ids() { return parent_num_ids() + 4; } | |
| 1899 BailoutId ReturnId() const { return BailoutId(local_id(0)); } | |
| 1900 BailoutId EvalId() const { return BailoutId(local_id(1)); } | |
| 1901 BailoutId LookupId() const { return BailoutId(local_id(2)); } | |
| 1902 BailoutId CallId() const { return BailoutId(local_id(3)); } | |
| 1903 | |
| 1904 bool is_uninitialized() const { | |
| 1905 return IsUninitializedField::decode(bit_field_); | |
| 1906 } | |
| 1907 void set_is_uninitialized(bool b) { | |
| 1908 bit_field_ = IsUninitializedField::update(bit_field_, b); | |
| 1909 } | |
| 1910 | |
| 1911 enum CallType { | |
| 1912 POSSIBLY_EVAL_CALL, | |
| 1913 GLOBAL_CALL, | |
| 1914 LOOKUP_SLOT_CALL, | |
| 1915 NAMED_PROPERTY_CALL, | |
| 1916 KEYED_PROPERTY_CALL, | |
| 1917 NAMED_SUPER_PROPERTY_CALL, | |
| 1918 KEYED_SUPER_PROPERTY_CALL, | |
| 1919 SUPER_CALL, | |
| 1920 OTHER_CALL | |
| 1921 }; | |
| 1922 | |
| 1923 // Helpers to determine how to handle the call. | |
| 1924 CallType GetCallType(Isolate* isolate) const; | |
| 1925 bool IsUsingCallFeedbackSlot(Isolate* isolate) const; | |
| 1926 bool IsUsingCallFeedbackICSlot(Isolate* isolate) const; | |
| 1927 | |
| 1928 #ifdef DEBUG | |
| 1929 // Used to assert that the FullCodeGenerator records the return site. | |
| 1930 bool return_is_recorded_; | |
| 1931 #endif | |
| 1932 | |
| 1933 protected: | |
| 1934 Call(Zone* zone, Expression* expression, ZoneList<Expression*>* arguments, | |
| 1935 int pos) | |
| 1936 : Expression(zone, pos), | |
| 1937 expression_(expression), | |
| 1938 arguments_(arguments), | |
| 1939 bit_field_(IsUninitializedField::encode(false)) { | |
| 1940 if (expression->IsProperty()) { | |
| 1941 expression->AsProperty()->mark_for_call(); | |
| 1942 } | |
| 1943 } | |
| 1944 static int parent_num_ids() { return Expression::num_ids(); } | |
| 1945 | |
| 1946 private: | |
| 1947 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 1948 | |
| 1949 FeedbackVectorSlot ic_slot_; | |
| 1950 FeedbackVectorSlot stub_slot_; | |
| 1951 Expression* expression_; | |
| 1952 ZoneList<Expression*>* arguments_; | |
| 1953 Handle<JSFunction> target_; | |
| 1954 Handle<AllocationSite> allocation_site_; | |
| 1955 class IsUninitializedField : public BitField8<bool, 0, 1> {}; | |
| 1956 uint8_t bit_field_; | |
| 1957 }; | |
| 1958 | |
| 1959 | |
| 1960 class CallNew final : public Expression { | |
| 1961 public: | |
| 1962 DECLARE_NODE_TYPE(CallNew) | |
| 1963 | |
| 1964 Expression* expression() const { return expression_; } | |
| 1965 ZoneList<Expression*>* arguments() const { return arguments_; } | |
| 1966 | |
| 1967 // Type feedback information. | |
| 1968 void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, | |
| 1969 FeedbackVectorSlotCache* cache) override { | |
| 1970 callnew_feedback_slot_ = spec->AddGeneralSlot(); | |
| 1971 } | |
| 1972 | |
| 1973 FeedbackVectorSlot CallNewFeedbackSlot() { | |
| 1974 DCHECK(!callnew_feedback_slot_.IsInvalid()); | |
| 1975 return callnew_feedback_slot_; | |
| 1976 } | |
| 1977 | |
| 1978 bool IsMonomorphic() override { return is_monomorphic_; } | |
| 1979 Handle<JSFunction> target() const { return target_; } | |
| 1980 Handle<AllocationSite> allocation_site() const { | |
| 1981 return allocation_site_; | |
| 1982 } | |
| 1983 | |
| 1984 static int num_ids() { return parent_num_ids() + 1; } | |
| 1985 static int feedback_slots() { return 1; } | |
| 1986 BailoutId ReturnId() const { return BailoutId(local_id(0)); } | |
| 1987 | |
| 1988 void set_allocation_site(Handle<AllocationSite> site) { | |
| 1989 allocation_site_ = site; | |
| 1990 } | |
| 1991 void set_is_monomorphic(bool monomorphic) { is_monomorphic_ = monomorphic; } | |
| 1992 void set_target(Handle<JSFunction> target) { target_ = target; } | |
| 1993 void SetKnownGlobalTarget(Handle<JSFunction> target) { | |
| 1994 target_ = target; | |
| 1995 is_monomorphic_ = true; | |
| 1996 } | |
| 1997 | |
| 1998 protected: | |
| 1999 CallNew(Zone* zone, Expression* expression, ZoneList<Expression*>* arguments, | |
| 2000 int pos) | |
| 2001 : Expression(zone, pos), | |
| 2002 expression_(expression), | |
| 2003 arguments_(arguments), | |
| 2004 is_monomorphic_(false) {} | |
| 2005 | |
| 2006 static int parent_num_ids() { return Expression::num_ids(); } | |
| 2007 | |
| 2008 private: | |
| 2009 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 2010 | |
| 2011 Expression* expression_; | |
| 2012 ZoneList<Expression*>* arguments_; | |
| 2013 bool is_monomorphic_; | |
| 2014 Handle<JSFunction> target_; | |
| 2015 Handle<AllocationSite> allocation_site_; | |
| 2016 FeedbackVectorSlot callnew_feedback_slot_; | |
| 2017 }; | |
| 2018 | |
| 2019 | |
| 2020 // The CallRuntime class does not represent any official JavaScript | |
| 2021 // language construct. Instead it is used to call a C or JS function | |
| 2022 // with a set of arguments. This is used from the builtins that are | |
| 2023 // implemented in JavaScript (see "v8natives.js"). | |
| 2024 class CallRuntime final : public Expression { | |
| 2025 public: | |
| 2026 DECLARE_NODE_TYPE(CallRuntime) | |
| 2027 | |
| 2028 ZoneList<Expression*>* arguments() const { return arguments_; } | |
| 2029 bool is_jsruntime() const { return function_ == NULL; } | |
| 2030 | |
| 2031 int context_index() const { | |
| 2032 DCHECK(is_jsruntime()); | |
| 2033 return context_index_; | |
| 2034 } | |
| 2035 const Runtime::Function* function() const { | |
| 2036 DCHECK(!is_jsruntime()); | |
| 2037 return function_; | |
| 2038 } | |
| 2039 | |
| 2040 static int num_ids() { return parent_num_ids() + 1; } | |
| 2041 BailoutId CallId() { return BailoutId(local_id(0)); } | |
| 2042 | |
| 2043 const char* debug_name() { | |
| 2044 return is_jsruntime() ? "(context function)" : function_->name; | |
| 2045 } | |
| 2046 | |
| 2047 protected: | |
| 2048 CallRuntime(Zone* zone, const Runtime::Function* function, | |
| 2049 ZoneList<Expression*>* arguments, int pos) | |
| 2050 : Expression(zone, pos), function_(function), arguments_(arguments) {} | |
| 2051 | |
| 2052 CallRuntime(Zone* zone, int context_index, ZoneList<Expression*>* arguments, | |
| 2053 int pos) | |
| 2054 : Expression(zone, pos), | |
| 2055 function_(NULL), | |
| 2056 context_index_(context_index), | |
| 2057 arguments_(arguments) {} | |
| 2058 | |
| 2059 static int parent_num_ids() { return Expression::num_ids(); } | |
| 2060 | |
| 2061 private: | |
| 2062 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 2063 | |
| 2064 const Runtime::Function* function_; | |
| 2065 int context_index_; | |
| 2066 ZoneList<Expression*>* arguments_; | |
| 2067 }; | |
| 2068 | |
| 2069 | |
| 2070 class UnaryOperation final : public Expression { | |
| 2071 public: | |
| 2072 DECLARE_NODE_TYPE(UnaryOperation) | |
| 2073 | |
| 2074 Token::Value op() const { return op_; } | |
| 2075 Expression* expression() const { return expression_; } | |
| 2076 | |
| 2077 // For unary not (Token::NOT), the AST ids where true and false will | |
| 2078 // actually be materialized, respectively. | |
| 2079 static int num_ids() { return parent_num_ids() + 2; } | |
| 2080 BailoutId MaterializeTrueId() const { return BailoutId(local_id(0)); } | |
| 2081 BailoutId MaterializeFalseId() const { return BailoutId(local_id(1)); } | |
| 2082 | |
| 2083 void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) override; | |
| 2084 | |
| 2085 protected: | |
| 2086 UnaryOperation(Zone* zone, Token::Value op, Expression* expression, int pos) | |
| 2087 : Expression(zone, pos), op_(op), expression_(expression) { | |
| 2088 DCHECK(Token::IsUnaryOp(op)); | |
| 2089 } | |
| 2090 static int parent_num_ids() { return Expression::num_ids(); } | |
| 2091 | |
| 2092 private: | |
| 2093 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 2094 | |
| 2095 Token::Value op_; | |
| 2096 Expression* expression_; | |
| 2097 }; | |
| 2098 | |
| 2099 | |
| 2100 class BinaryOperation final : public Expression { | |
| 2101 public: | |
| 2102 DECLARE_NODE_TYPE(BinaryOperation) | |
| 2103 | |
| 2104 Token::Value op() const { return static_cast<Token::Value>(op_); } | |
| 2105 Expression* left() const { return left_; } | |
| 2106 Expression* right() const { return right_; } | |
| 2107 Handle<AllocationSite> allocation_site() const { return allocation_site_; } | |
| 2108 void set_allocation_site(Handle<AllocationSite> allocation_site) { | |
| 2109 allocation_site_ = allocation_site; | |
| 2110 } | |
| 2111 | |
| 2112 // The short-circuit logical operations need an AST ID for their | |
| 2113 // right-hand subexpression. | |
| 2114 static int num_ids() { return parent_num_ids() + 2; } | |
| 2115 BailoutId RightId() const { return BailoutId(local_id(0)); } | |
| 2116 | |
| 2117 TypeFeedbackId BinaryOperationFeedbackId() const { | |
| 2118 return TypeFeedbackId(local_id(1)); | |
| 2119 } | |
| 2120 Maybe<int> fixed_right_arg() const { | |
| 2121 return has_fixed_right_arg_ ? Just(fixed_right_arg_value_) : Nothing<int>(); | |
| 2122 } | |
| 2123 void set_fixed_right_arg(Maybe<int> arg) { | |
| 2124 has_fixed_right_arg_ = arg.IsJust(); | |
| 2125 if (arg.IsJust()) fixed_right_arg_value_ = arg.FromJust(); | |
| 2126 } | |
| 2127 | |
| 2128 void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) override; | |
| 2129 | |
| 2130 protected: | |
| 2131 BinaryOperation(Zone* zone, Token::Value op, Expression* left, | |
| 2132 Expression* right, int pos) | |
| 2133 : Expression(zone, pos), | |
| 2134 op_(static_cast<byte>(op)), | |
| 2135 has_fixed_right_arg_(false), | |
| 2136 fixed_right_arg_value_(0), | |
| 2137 left_(left), | |
| 2138 right_(right) { | |
| 2139 DCHECK(Token::IsBinaryOp(op)); | |
| 2140 } | |
| 2141 static int parent_num_ids() { return Expression::num_ids(); } | |
| 2142 | |
| 2143 private: | |
| 2144 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 2145 | |
| 2146 const byte op_; // actually Token::Value | |
| 2147 // TODO(rossberg): the fixed arg should probably be represented as a Constant | |
| 2148 // type for the RHS. Currenty it's actually a Maybe<int> | |
| 2149 bool has_fixed_right_arg_; | |
| 2150 int fixed_right_arg_value_; | |
| 2151 Expression* left_; | |
| 2152 Expression* right_; | |
| 2153 Handle<AllocationSite> allocation_site_; | |
| 2154 }; | |
| 2155 | |
| 2156 | |
| 2157 class CountOperation final : public Expression { | |
| 2158 public: | |
| 2159 DECLARE_NODE_TYPE(CountOperation) | |
| 2160 | |
| 2161 bool is_prefix() const { return IsPrefixField::decode(bit_field_); } | |
| 2162 bool is_postfix() const { return !is_prefix(); } | |
| 2163 | |
| 2164 Token::Value op() const { return TokenField::decode(bit_field_); } | |
| 2165 Token::Value binary_op() { | |
| 2166 return (op() == Token::INC) ? Token::ADD : Token::SUB; | |
| 2167 } | |
| 2168 | |
| 2169 Expression* expression() const { return expression_; } | |
| 2170 | |
| 2171 bool IsMonomorphic() override { return receiver_types_.length() == 1; } | |
| 2172 SmallMapList* GetReceiverTypes() override { return &receiver_types_; } | |
| 2173 IcCheckType GetKeyType() const override { | |
| 2174 return KeyTypeField::decode(bit_field_); | |
| 2175 } | |
| 2176 KeyedAccessStoreMode GetStoreMode() const override { | |
| 2177 return StoreModeField::decode(bit_field_); | |
| 2178 } | |
| 2179 Type* type() const { return type_; } | |
| 2180 void set_key_type(IcCheckType type) { | |
| 2181 bit_field_ = KeyTypeField::update(bit_field_, type); | |
| 2182 } | |
| 2183 void set_store_mode(KeyedAccessStoreMode mode) { | |
| 2184 bit_field_ = StoreModeField::update(bit_field_, mode); | |
| 2185 } | |
| 2186 void set_type(Type* type) { type_ = type; } | |
| 2187 | |
| 2188 static int num_ids() { return parent_num_ids() + 4; } | |
| 2189 BailoutId AssignmentId() const { return BailoutId(local_id(0)); } | |
| 2190 BailoutId ToNumberId() const { return BailoutId(local_id(1)); } | |
| 2191 TypeFeedbackId CountBinOpFeedbackId() const { | |
| 2192 return TypeFeedbackId(local_id(2)); | |
| 2193 } | |
| 2194 TypeFeedbackId CountStoreFeedbackId() const { | |
| 2195 return TypeFeedbackId(local_id(3)); | |
| 2196 } | |
| 2197 | |
| 2198 void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, | |
| 2199 FeedbackVectorSlotCache* cache) override; | |
| 2200 FeedbackVectorSlot CountSlot() const { return slot_; } | |
| 2201 | |
| 2202 protected: | |
| 2203 CountOperation(Zone* zone, Token::Value op, bool is_prefix, Expression* expr, | |
| 2204 int pos) | |
| 2205 : Expression(zone, pos), | |
| 2206 bit_field_( | |
| 2207 IsPrefixField::encode(is_prefix) | KeyTypeField::encode(ELEMENT) | | |
| 2208 StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op)), | |
| 2209 type_(NULL), | |
| 2210 expression_(expr) {} | |
| 2211 static int parent_num_ids() { return Expression::num_ids(); } | |
| 2212 | |
| 2213 private: | |
| 2214 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 2215 | |
| 2216 class IsPrefixField : public BitField16<bool, 0, 1> {}; | |
| 2217 class KeyTypeField : public BitField16<IcCheckType, 1, 1> {}; | |
| 2218 class StoreModeField : public BitField16<KeyedAccessStoreMode, 2, 3> {}; | |
| 2219 class TokenField : public BitField16<Token::Value, 5, 8> {}; | |
| 2220 | |
| 2221 // Starts with 16-bit field, which should get packed together with | |
| 2222 // Expression's trailing 16-bit field. | |
| 2223 uint16_t bit_field_; | |
| 2224 Type* type_; | |
| 2225 Expression* expression_; | |
| 2226 SmallMapList receiver_types_; | |
| 2227 FeedbackVectorSlot slot_; | |
| 2228 }; | |
| 2229 | |
| 2230 | |
| 2231 class CompareOperation final : public Expression { | |
| 2232 public: | |
| 2233 DECLARE_NODE_TYPE(CompareOperation) | |
| 2234 | |
| 2235 Token::Value op() const { return op_; } | |
| 2236 Expression* left() const { return left_; } | |
| 2237 Expression* right() const { return right_; } | |
| 2238 | |
| 2239 // Type feedback information. | |
| 2240 static int num_ids() { return parent_num_ids() + 1; } | |
| 2241 TypeFeedbackId CompareOperationFeedbackId() const { | |
| 2242 return TypeFeedbackId(local_id(0)); | |
| 2243 } | |
| 2244 Type* combined_type() const { return combined_type_; } | |
| 2245 void set_combined_type(Type* type) { combined_type_ = type; } | |
| 2246 | |
| 2247 // Match special cases. | |
| 2248 bool IsLiteralCompareTypeof(Expression** expr, Handle<String>* check); | |
| 2249 bool IsLiteralCompareUndefined(Expression** expr, Isolate* isolate); | |
| 2250 bool IsLiteralCompareNull(Expression** expr); | |
| 2251 | |
| 2252 protected: | |
| 2253 CompareOperation(Zone* zone, Token::Value op, Expression* left, | |
| 2254 Expression* right, int pos) | |
| 2255 : Expression(zone, pos), | |
| 2256 op_(op), | |
| 2257 left_(left), | |
| 2258 right_(right), | |
| 2259 combined_type_(Type::None(zone)) { | |
| 2260 DCHECK(Token::IsCompareOp(op)); | |
| 2261 } | |
| 2262 static int parent_num_ids() { return Expression::num_ids(); } | |
| 2263 | |
| 2264 private: | |
| 2265 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 2266 | |
| 2267 Token::Value op_; | |
| 2268 Expression* left_; | |
| 2269 Expression* right_; | |
| 2270 | |
| 2271 Type* combined_type_; | |
| 2272 }; | |
| 2273 | |
| 2274 | |
| 2275 class Spread final : public Expression { | |
| 2276 public: | |
| 2277 DECLARE_NODE_TYPE(Spread) | |
| 2278 | |
| 2279 Expression* expression() const { return expression_; } | |
| 2280 | |
| 2281 static int num_ids() { return parent_num_ids(); } | |
| 2282 | |
| 2283 protected: | |
| 2284 Spread(Zone* zone, Expression* expression, int pos) | |
| 2285 : Expression(zone, pos), expression_(expression) {} | |
| 2286 static int parent_num_ids() { return Expression::num_ids(); } | |
| 2287 | |
| 2288 private: | |
| 2289 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 2290 | |
| 2291 Expression* expression_; | |
| 2292 }; | |
| 2293 | |
| 2294 | |
| 2295 class Conditional final : public Expression { | |
| 2296 public: | |
| 2297 DECLARE_NODE_TYPE(Conditional) | |
| 2298 | |
| 2299 Expression* condition() const { return condition_; } | |
| 2300 Expression* then_expression() const { return then_expression_; } | |
| 2301 Expression* else_expression() const { return else_expression_; } | |
| 2302 | |
| 2303 static int num_ids() { return parent_num_ids() + 2; } | |
| 2304 BailoutId ThenId() const { return BailoutId(local_id(0)); } | |
| 2305 BailoutId ElseId() const { return BailoutId(local_id(1)); } | |
| 2306 | |
| 2307 protected: | |
| 2308 Conditional(Zone* zone, Expression* condition, Expression* then_expression, | |
| 2309 Expression* else_expression, int position) | |
| 2310 : Expression(zone, position), | |
| 2311 condition_(condition), | |
| 2312 then_expression_(then_expression), | |
| 2313 else_expression_(else_expression) {} | |
| 2314 static int parent_num_ids() { return Expression::num_ids(); } | |
| 2315 | |
| 2316 private: | |
| 2317 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 2318 | |
| 2319 Expression* condition_; | |
| 2320 Expression* then_expression_; | |
| 2321 Expression* else_expression_; | |
| 2322 }; | |
| 2323 | |
| 2324 | |
| 2325 class Assignment final : public Expression { | |
| 2326 public: | |
| 2327 DECLARE_NODE_TYPE(Assignment) | |
| 2328 | |
| 2329 Assignment* AsSimpleAssignment() { return !is_compound() ? this : NULL; } | |
| 2330 | |
| 2331 Token::Value binary_op() const; | |
| 2332 | |
| 2333 Token::Value op() const { return TokenField::decode(bit_field_); } | |
| 2334 Expression* target() const { return target_; } | |
| 2335 Expression* value() const { return value_; } | |
| 2336 BinaryOperation* binary_operation() const { return binary_operation_; } | |
| 2337 | |
| 2338 // This check relies on the definition order of token in token.h. | |
| 2339 bool is_compound() const { return op() > Token::ASSIGN; } | |
| 2340 | |
| 2341 static int num_ids() { return parent_num_ids() + 2; } | |
| 2342 BailoutId AssignmentId() const { return BailoutId(local_id(0)); } | |
| 2343 | |
| 2344 // Type feedback information. | |
| 2345 TypeFeedbackId AssignmentFeedbackId() { return TypeFeedbackId(local_id(1)); } | |
| 2346 bool IsMonomorphic() override { return receiver_types_.length() == 1; } | |
| 2347 bool IsUninitialized() const { | |
| 2348 return IsUninitializedField::decode(bit_field_); | |
| 2349 } | |
| 2350 bool HasNoTypeInformation() { | |
| 2351 return IsUninitializedField::decode(bit_field_); | |
| 2352 } | |
| 2353 SmallMapList* GetReceiverTypes() override { return &receiver_types_; } | |
| 2354 IcCheckType GetKeyType() const override { | |
| 2355 return KeyTypeField::decode(bit_field_); | |
| 2356 } | |
| 2357 KeyedAccessStoreMode GetStoreMode() const override { | |
| 2358 return StoreModeField::decode(bit_field_); | |
| 2359 } | |
| 2360 void set_is_uninitialized(bool b) { | |
| 2361 bit_field_ = IsUninitializedField::update(bit_field_, b); | |
| 2362 } | |
| 2363 void set_key_type(IcCheckType key_type) { | |
| 2364 bit_field_ = KeyTypeField::update(bit_field_, key_type); | |
| 2365 } | |
| 2366 void set_store_mode(KeyedAccessStoreMode mode) { | |
| 2367 bit_field_ = StoreModeField::update(bit_field_, mode); | |
| 2368 } | |
| 2369 | |
| 2370 void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, | |
| 2371 FeedbackVectorSlotCache* cache) override; | |
| 2372 FeedbackVectorSlot AssignmentSlot() const { return slot_; } | |
| 2373 | |
| 2374 protected: | |
| 2375 Assignment(Zone* zone, Token::Value op, Expression* target, Expression* value, | |
| 2376 int pos); | |
| 2377 static int parent_num_ids() { return Expression::num_ids(); } | |
| 2378 | |
| 2379 private: | |
| 2380 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 2381 | |
| 2382 class IsUninitializedField : public BitField16<bool, 0, 1> {}; | |
| 2383 class KeyTypeField : public BitField16<IcCheckType, 1, 1> {}; | |
| 2384 class StoreModeField : public BitField16<KeyedAccessStoreMode, 2, 3> {}; | |
| 2385 class TokenField : public BitField16<Token::Value, 5, 8> {}; | |
| 2386 | |
| 2387 // Starts with 16-bit field, which should get packed together with | |
| 2388 // Expression's trailing 16-bit field. | |
| 2389 uint16_t bit_field_; | |
| 2390 Expression* target_; | |
| 2391 Expression* value_; | |
| 2392 BinaryOperation* binary_operation_; | |
| 2393 SmallMapList receiver_types_; | |
| 2394 FeedbackVectorSlot slot_; | |
| 2395 }; | |
| 2396 | |
| 2397 | |
| 2398 class Yield final : public Expression { | |
| 2399 public: | |
| 2400 DECLARE_NODE_TYPE(Yield) | |
| 2401 | |
| 2402 enum Kind { | |
| 2403 kInitial, // The initial yield that returns the unboxed generator object. | |
| 2404 kSuspend, // A normal yield: { value: EXPRESSION, done: false } | |
| 2405 kDelegating, // A yield*. | |
| 2406 kFinal // A return: { value: EXPRESSION, done: true } | |
| 2407 }; | |
| 2408 | |
| 2409 Expression* generator_object() const { return generator_object_; } | |
| 2410 Expression* expression() const { return expression_; } | |
| 2411 Kind yield_kind() const { return yield_kind_; } | |
| 2412 | |
| 2413 // Type feedback information. | |
| 2414 bool HasFeedbackSlots() const { return yield_kind() == kDelegating; } | |
| 2415 void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, | |
| 2416 FeedbackVectorSlotCache* cache) override { | |
| 2417 if (HasFeedbackSlots()) { | |
| 2418 yield_first_feedback_slot_ = spec->AddKeyedLoadICSlot(); | |
| 2419 keyed_load_feedback_slot_ = spec->AddLoadICSlot(); | |
| 2420 done_feedback_slot_ = spec->AddLoadICSlot(); | |
| 2421 } | |
| 2422 } | |
| 2423 | |
| 2424 FeedbackVectorSlot KeyedLoadFeedbackSlot() { | |
| 2425 DCHECK(!HasFeedbackSlots() || !yield_first_feedback_slot_.IsInvalid()); | |
| 2426 return yield_first_feedback_slot_; | |
| 2427 } | |
| 2428 | |
| 2429 FeedbackVectorSlot DoneFeedbackSlot() { return keyed_load_feedback_slot_; } | |
| 2430 | |
| 2431 FeedbackVectorSlot ValueFeedbackSlot() { return done_feedback_slot_; } | |
| 2432 | |
| 2433 protected: | |
| 2434 Yield(Zone* zone, Expression* generator_object, Expression* expression, | |
| 2435 Kind yield_kind, int pos) | |
| 2436 : Expression(zone, pos), | |
| 2437 generator_object_(generator_object), | |
| 2438 expression_(expression), | |
| 2439 yield_kind_(yield_kind) {} | |
| 2440 | |
| 2441 private: | |
| 2442 Expression* generator_object_; | |
| 2443 Expression* expression_; | |
| 2444 Kind yield_kind_; | |
| 2445 FeedbackVectorSlot yield_first_feedback_slot_; | |
| 2446 FeedbackVectorSlot keyed_load_feedback_slot_; | |
| 2447 FeedbackVectorSlot done_feedback_slot_; | |
| 2448 }; | |
| 2449 | |
| 2450 | |
| 2451 class Throw final : public Expression { | |
| 2452 public: | |
| 2453 DECLARE_NODE_TYPE(Throw) | |
| 2454 | |
| 2455 Expression* exception() const { return exception_; } | |
| 2456 | |
| 2457 protected: | |
| 2458 Throw(Zone* zone, Expression* exception, int pos) | |
| 2459 : Expression(zone, pos), exception_(exception) {} | |
| 2460 | |
| 2461 private: | |
| 2462 Expression* exception_; | |
| 2463 }; | |
| 2464 | |
| 2465 | |
| 2466 class FunctionLiteral final : public Expression { | |
| 2467 public: | |
| 2468 enum FunctionType { | |
| 2469 ANONYMOUS_EXPRESSION, | |
| 2470 NAMED_EXPRESSION, | |
| 2471 DECLARATION | |
| 2472 }; | |
| 2473 | |
| 2474 enum ParameterFlag { | |
| 2475 kNoDuplicateParameters = 0, | |
| 2476 kHasDuplicateParameters = 1 | |
| 2477 }; | |
| 2478 | |
| 2479 enum IsFunctionFlag { | |
| 2480 kGlobalOrEval, | |
| 2481 kIsFunction | |
| 2482 }; | |
| 2483 | |
| 2484 enum EagerCompileHint { kShouldEagerCompile, kShouldLazyCompile }; | |
| 2485 | |
| 2486 enum ShouldBeUsedOnceHint { kShouldBeUsedOnce, kDontKnowIfShouldBeUsedOnce }; | |
| 2487 | |
| 2488 enum ArityRestriction { | |
| 2489 NORMAL_ARITY, | |
| 2490 GETTER_ARITY, | |
| 2491 SETTER_ARITY | |
| 2492 }; | |
| 2493 | |
| 2494 DECLARE_NODE_TYPE(FunctionLiteral) | |
| 2495 | |
| 2496 Handle<String> name() const { return raw_name_->string(); } | |
| 2497 const AstRawString* raw_name() const { return raw_name_; } | |
| 2498 Scope* scope() const { return scope_; } | |
| 2499 ZoneList<Statement*>* body() const { return body_; } | |
| 2500 void set_function_token_position(int pos) { function_token_position_ = pos; } | |
| 2501 int function_token_position() const { return function_token_position_; } | |
| 2502 int start_position() const; | |
| 2503 int end_position() const; | |
| 2504 int SourceSize() const { return end_position() - start_position(); } | |
| 2505 bool is_expression() const { return IsExpression::decode(bitfield_); } | |
| 2506 bool is_anonymous() const { return IsAnonymous::decode(bitfield_); } | |
| 2507 LanguageMode language_mode() const; | |
| 2508 | |
| 2509 static bool NeedsHomeObject(Expression* expr); | |
| 2510 | |
| 2511 int materialized_literal_count() { return materialized_literal_count_; } | |
| 2512 int expected_property_count() { return expected_property_count_; } | |
| 2513 int parameter_count() { return parameter_count_; } | |
| 2514 | |
| 2515 bool AllowsLazyCompilation(); | |
| 2516 bool AllowsLazyCompilationWithoutContext(); | |
| 2517 | |
| 2518 Handle<String> debug_name() const { | |
| 2519 if (raw_name_ != NULL && !raw_name_->IsEmpty()) { | |
| 2520 return raw_name_->string(); | |
| 2521 } | |
| 2522 return inferred_name(); | |
| 2523 } | |
| 2524 | |
| 2525 Handle<String> inferred_name() const { | |
| 2526 if (!inferred_name_.is_null()) { | |
| 2527 DCHECK(raw_inferred_name_ == NULL); | |
| 2528 return inferred_name_; | |
| 2529 } | |
| 2530 if (raw_inferred_name_ != NULL) { | |
| 2531 return raw_inferred_name_->string(); | |
| 2532 } | |
| 2533 UNREACHABLE(); | |
| 2534 return Handle<String>(); | |
| 2535 } | |
| 2536 | |
| 2537 // Only one of {set_inferred_name, set_raw_inferred_name} should be called. | |
| 2538 void set_inferred_name(Handle<String> inferred_name) { | |
| 2539 DCHECK(!inferred_name.is_null()); | |
| 2540 inferred_name_ = inferred_name; | |
| 2541 DCHECK(raw_inferred_name_== NULL || raw_inferred_name_->IsEmpty()); | |
| 2542 raw_inferred_name_ = NULL; | |
| 2543 } | |
| 2544 | |
| 2545 void set_raw_inferred_name(const AstString* raw_inferred_name) { | |
| 2546 DCHECK(raw_inferred_name != NULL); | |
| 2547 raw_inferred_name_ = raw_inferred_name; | |
| 2548 DCHECK(inferred_name_.is_null()); | |
| 2549 inferred_name_ = Handle<String>(); | |
| 2550 } | |
| 2551 | |
| 2552 bool pretenure() { return Pretenure::decode(bitfield_); } | |
| 2553 void set_pretenure() { bitfield_ |= Pretenure::encode(true); } | |
| 2554 | |
| 2555 bool has_duplicate_parameters() { | |
| 2556 return HasDuplicateParameters::decode(bitfield_); | |
| 2557 } | |
| 2558 | |
| 2559 bool is_function() { return IsFunction::decode(bitfield_) == kIsFunction; } | |
| 2560 | |
| 2561 // This is used as a heuristic on when to eagerly compile a function | |
| 2562 // literal. We consider the following constructs as hints that the | |
| 2563 // function will be called immediately: | |
| 2564 // - (function() { ... })(); | |
| 2565 // - var x = function() { ... }(); | |
| 2566 bool should_eager_compile() const { | |
| 2567 return EagerCompileHintBit::decode(bitfield_) == kShouldEagerCompile; | |
| 2568 } | |
| 2569 void set_should_eager_compile() { | |
| 2570 bitfield_ = EagerCompileHintBit::update(bitfield_, kShouldEagerCompile); | |
| 2571 } | |
| 2572 | |
| 2573 // A hint that we expect this function to be called (exactly) once, | |
| 2574 // i.e. we suspect it's an initialization function. | |
| 2575 bool should_be_used_once_hint() const { | |
| 2576 return ShouldBeUsedOnceHintBit::decode(bitfield_) == kShouldBeUsedOnce; | |
| 2577 } | |
| 2578 void set_should_be_used_once_hint() { | |
| 2579 bitfield_ = ShouldBeUsedOnceHintBit::update(bitfield_, kShouldBeUsedOnce); | |
| 2580 } | |
| 2581 | |
| 2582 FunctionKind kind() const { return FunctionKindBits::decode(bitfield_); } | |
| 2583 | |
| 2584 int ast_node_count() { return ast_properties_.node_count(); } | |
| 2585 AstProperties::Flags flags() const { return ast_properties_.flags(); } | |
| 2586 void set_ast_properties(AstProperties* ast_properties) { | |
| 2587 ast_properties_ = *ast_properties; | |
| 2588 } | |
| 2589 const FeedbackVectorSpec* feedback_vector_spec() const { | |
| 2590 return ast_properties_.get_spec(); | |
| 2591 } | |
| 2592 bool dont_optimize() { return dont_optimize_reason_ != kNoReason; } | |
| 2593 BailoutReason dont_optimize_reason() { return dont_optimize_reason_; } | |
| 2594 void set_dont_optimize_reason(BailoutReason reason) { | |
| 2595 dont_optimize_reason_ = reason; | |
| 2596 } | |
| 2597 | |
| 2598 protected: | |
| 2599 FunctionLiteral(Zone* zone, const AstRawString* name, | |
| 2600 AstValueFactory* ast_value_factory, Scope* scope, | |
| 2601 ZoneList<Statement*>* body, int materialized_literal_count, | |
| 2602 int expected_property_count, int parameter_count, | |
| 2603 FunctionType function_type, | |
| 2604 ParameterFlag has_duplicate_parameters, | |
| 2605 IsFunctionFlag is_function, | |
| 2606 EagerCompileHint eager_compile_hint, FunctionKind kind, | |
| 2607 int position) | |
| 2608 : Expression(zone, position), | |
| 2609 raw_name_(name), | |
| 2610 scope_(scope), | |
| 2611 body_(body), | |
| 2612 raw_inferred_name_(ast_value_factory->empty_string()), | |
| 2613 ast_properties_(zone), | |
| 2614 dont_optimize_reason_(kNoReason), | |
| 2615 materialized_literal_count_(materialized_literal_count), | |
| 2616 expected_property_count_(expected_property_count), | |
| 2617 parameter_count_(parameter_count), | |
| 2618 function_token_position_(RelocInfo::kNoPosition) { | |
| 2619 bitfield_ = IsExpression::encode(function_type != DECLARATION) | | |
| 2620 IsAnonymous::encode(function_type == ANONYMOUS_EXPRESSION) | | |
| 2621 Pretenure::encode(false) | | |
| 2622 HasDuplicateParameters::encode(has_duplicate_parameters) | | |
| 2623 IsFunction::encode(is_function) | | |
| 2624 EagerCompileHintBit::encode(eager_compile_hint) | | |
| 2625 FunctionKindBits::encode(kind) | | |
| 2626 ShouldBeUsedOnceHintBit::encode(kDontKnowIfShouldBeUsedOnce); | |
| 2627 DCHECK(IsValidFunctionKind(kind)); | |
| 2628 } | |
| 2629 | |
| 2630 private: | |
| 2631 const AstRawString* raw_name_; | |
| 2632 Handle<String> name_; | |
| 2633 Scope* scope_; | |
| 2634 ZoneList<Statement*>* body_; | |
| 2635 const AstString* raw_inferred_name_; | |
| 2636 Handle<String> inferred_name_; | |
| 2637 AstProperties ast_properties_; | |
| 2638 BailoutReason dont_optimize_reason_; | |
| 2639 | |
| 2640 int materialized_literal_count_; | |
| 2641 int expected_property_count_; | |
| 2642 int parameter_count_; | |
| 2643 int function_token_position_; | |
| 2644 | |
| 2645 unsigned bitfield_; | |
| 2646 class IsExpression : public BitField<bool, 0, 1> {}; | |
| 2647 class IsAnonymous : public BitField<bool, 1, 1> {}; | |
| 2648 class Pretenure : public BitField<bool, 2, 1> {}; | |
| 2649 class HasDuplicateParameters : public BitField<ParameterFlag, 3, 1> {}; | |
| 2650 class IsFunction : public BitField<IsFunctionFlag, 4, 1> {}; | |
| 2651 class EagerCompileHintBit : public BitField<EagerCompileHint, 5, 1> {}; | |
| 2652 class FunctionKindBits : public BitField<FunctionKind, 6, 8> {}; | |
| 2653 class ShouldBeUsedOnceHintBit : public BitField<ShouldBeUsedOnceHint, 15, 1> { | |
| 2654 }; | |
| 2655 }; | |
| 2656 | |
| 2657 | |
| 2658 class ClassLiteral final : public Expression { | |
| 2659 public: | |
| 2660 typedef ObjectLiteralProperty Property; | |
| 2661 | |
| 2662 DECLARE_NODE_TYPE(ClassLiteral) | |
| 2663 | |
| 2664 Handle<String> name() const { return raw_name_->string(); } | |
| 2665 const AstRawString* raw_name() const { return raw_name_; } | |
| 2666 Scope* scope() const { return scope_; } | |
| 2667 VariableProxy* class_variable_proxy() const { return class_variable_proxy_; } | |
| 2668 Expression* extends() const { return extends_; } | |
| 2669 FunctionLiteral* constructor() const { return constructor_; } | |
| 2670 ZoneList<Property*>* properties() const { return properties_; } | |
| 2671 int start_position() const { return position(); } | |
| 2672 int end_position() const { return end_position_; } | |
| 2673 | |
| 2674 BailoutId EntryId() const { return BailoutId(local_id(0)); } | |
| 2675 BailoutId DeclsId() const { return BailoutId(local_id(1)); } | |
| 2676 BailoutId ExitId() { return BailoutId(local_id(2)); } | |
| 2677 BailoutId CreateLiteralId() const { return BailoutId(local_id(3)); } | |
| 2678 | |
| 2679 // Return an AST id for a property that is used in simulate instructions. | |
| 2680 BailoutId GetIdForProperty(int i) { return BailoutId(local_id(i + 4)); } | |
| 2681 | |
| 2682 // Unlike other AST nodes, this number of bailout IDs allocated for an | |
| 2683 // ClassLiteral can vary, so num_ids() is not a static method. | |
| 2684 int num_ids() const { return parent_num_ids() + 4 + properties()->length(); } | |
| 2685 | |
| 2686 // Object literals need one feedback slot for each non-trivial value, as well | |
| 2687 // as some slots for home objects. | |
| 2688 void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, | |
| 2689 FeedbackVectorSlotCache* cache) override; | |
| 2690 | |
| 2691 bool NeedsProxySlot() const { | |
| 2692 return class_variable_proxy() != nullptr && | |
| 2693 class_variable_proxy()->var()->IsUnallocated(); | |
| 2694 } | |
| 2695 | |
| 2696 FeedbackVectorSlot ProxySlot() const { return slot_; } | |
| 2697 | |
| 2698 protected: | |
| 2699 ClassLiteral(Zone* zone, const AstRawString* name, Scope* scope, | |
| 2700 VariableProxy* class_variable_proxy, Expression* extends, | |
| 2701 FunctionLiteral* constructor, ZoneList<Property*>* properties, | |
| 2702 int start_position, int end_position) | |
| 2703 : Expression(zone, start_position), | |
| 2704 raw_name_(name), | |
| 2705 scope_(scope), | |
| 2706 class_variable_proxy_(class_variable_proxy), | |
| 2707 extends_(extends), | |
| 2708 constructor_(constructor), | |
| 2709 properties_(properties), | |
| 2710 end_position_(end_position) {} | |
| 2711 | |
| 2712 static int parent_num_ids() { return Expression::num_ids(); } | |
| 2713 | |
| 2714 private: | |
| 2715 int local_id(int n) const { return base_id() + parent_num_ids() + n; } | |
| 2716 | |
| 2717 const AstRawString* raw_name_; | |
| 2718 Scope* scope_; | |
| 2719 VariableProxy* class_variable_proxy_; | |
| 2720 Expression* extends_; | |
| 2721 FunctionLiteral* constructor_; | |
| 2722 ZoneList<Property*>* properties_; | |
| 2723 int end_position_; | |
| 2724 FeedbackVectorSlot slot_; | |
| 2725 }; | |
| 2726 | |
| 2727 | |
| 2728 class NativeFunctionLiteral final : public Expression { | |
| 2729 public: | |
| 2730 DECLARE_NODE_TYPE(NativeFunctionLiteral) | |
| 2731 | |
| 2732 Handle<String> name() const { return name_->string(); } | |
| 2733 v8::Extension* extension() const { return extension_; } | |
| 2734 | |
| 2735 protected: | |
| 2736 NativeFunctionLiteral(Zone* zone, const AstRawString* name, | |
| 2737 v8::Extension* extension, int pos) | |
| 2738 : Expression(zone, pos), name_(name), extension_(extension) {} | |
| 2739 | |
| 2740 private: | |
| 2741 const AstRawString* name_; | |
| 2742 v8::Extension* extension_; | |
| 2743 }; | |
| 2744 | |
| 2745 | |
| 2746 class ThisFunction final : public Expression { | |
| 2747 public: | |
| 2748 DECLARE_NODE_TYPE(ThisFunction) | |
| 2749 | |
| 2750 protected: | |
| 2751 ThisFunction(Zone* zone, int pos) : Expression(zone, pos) {} | |
| 2752 }; | |
| 2753 | |
| 2754 | |
| 2755 class SuperPropertyReference final : public Expression { | |
| 2756 public: | |
| 2757 DECLARE_NODE_TYPE(SuperPropertyReference) | |
| 2758 | |
| 2759 VariableProxy* this_var() const { return this_var_; } | |
| 2760 Expression* home_object() const { return home_object_; } | |
| 2761 | |
| 2762 protected: | |
| 2763 SuperPropertyReference(Zone* zone, VariableProxy* this_var, | |
| 2764 Expression* home_object, int pos) | |
| 2765 : Expression(zone, pos), this_var_(this_var), home_object_(home_object) { | |
| 2766 DCHECK(this_var->is_this()); | |
| 2767 DCHECK(home_object->IsProperty()); | |
| 2768 } | |
| 2769 | |
| 2770 private: | |
| 2771 VariableProxy* this_var_; | |
| 2772 Expression* home_object_; | |
| 2773 }; | |
| 2774 | |
| 2775 | |
| 2776 class SuperCallReference final : public Expression { | |
| 2777 public: | |
| 2778 DECLARE_NODE_TYPE(SuperCallReference) | |
| 2779 | |
| 2780 VariableProxy* this_var() const { return this_var_; } | |
| 2781 VariableProxy* new_target_var() const { return new_target_var_; } | |
| 2782 VariableProxy* this_function_var() const { return this_function_var_; } | |
| 2783 | |
| 2784 protected: | |
| 2785 SuperCallReference(Zone* zone, VariableProxy* this_var, | |
| 2786 VariableProxy* new_target_var, | |
| 2787 VariableProxy* this_function_var, int pos) | |
| 2788 : Expression(zone, pos), | |
| 2789 this_var_(this_var), | |
| 2790 new_target_var_(new_target_var), | |
| 2791 this_function_var_(this_function_var) { | |
| 2792 DCHECK(this_var->is_this()); | |
| 2793 DCHECK(new_target_var->raw_name()->IsOneByteEqualTo(".new.target")); | |
| 2794 DCHECK(this_function_var->raw_name()->IsOneByteEqualTo(".this_function")); | |
| 2795 } | |
| 2796 | |
| 2797 private: | |
| 2798 VariableProxy* this_var_; | |
| 2799 VariableProxy* new_target_var_; | |
| 2800 VariableProxy* this_function_var_; | |
| 2801 }; | |
| 2802 | |
| 2803 | |
| 2804 // This class is produced when parsing the () in arrow functions without any | |
| 2805 // arguments and is not actually a valid expression. | |
| 2806 class EmptyParentheses final : public Expression { | |
| 2807 public: | |
| 2808 DECLARE_NODE_TYPE(EmptyParentheses) | |
| 2809 | |
| 2810 private: | |
| 2811 EmptyParentheses(Zone* zone, int pos) : Expression(zone, pos) {} | |
| 2812 }; | |
| 2813 | |
| 2814 | |
| 2815 #undef DECLARE_NODE_TYPE | |
| 2816 | |
| 2817 | |
| 2818 // ---------------------------------------------------------------------------- | |
| 2819 // Regular expressions | |
| 2820 | |
| 2821 | |
| 2822 class RegExpVisitor BASE_EMBEDDED { | |
| 2823 public: | |
| 2824 virtual ~RegExpVisitor() { } | |
| 2825 #define MAKE_CASE(Name) \ | |
| 2826 virtual void* Visit##Name(RegExp##Name*, void* data) = 0; | |
| 2827 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE) | |
| 2828 #undef MAKE_CASE | |
| 2829 }; | |
| 2830 | |
| 2831 | |
| 2832 class RegExpTree : public ZoneObject { | |
| 2833 public: | |
| 2834 static const int kInfinity = kMaxInt; | |
| 2835 virtual ~RegExpTree() {} | |
| 2836 virtual void* Accept(RegExpVisitor* visitor, void* data) = 0; | |
| 2837 virtual RegExpNode* ToNode(RegExpCompiler* compiler, | |
| 2838 RegExpNode* on_success) = 0; | |
| 2839 virtual bool IsTextElement() { return false; } | |
| 2840 virtual bool IsAnchoredAtStart() { return false; } | |
| 2841 virtual bool IsAnchoredAtEnd() { return false; } | |
| 2842 virtual int min_match() = 0; | |
| 2843 virtual int max_match() = 0; | |
| 2844 // Returns the interval of registers used for captures within this | |
| 2845 // expression. | |
| 2846 virtual Interval CaptureRegisters() { return Interval::Empty(); } | |
| 2847 virtual void AppendToText(RegExpText* text, Zone* zone); | |
| 2848 std::ostream& Print(std::ostream& os, Zone* zone); // NOLINT | |
| 2849 #define MAKE_ASTYPE(Name) \ | |
| 2850 virtual RegExp##Name* As##Name(); \ | |
| 2851 virtual bool Is##Name(); | |
| 2852 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ASTYPE) | |
| 2853 #undef MAKE_ASTYPE | |
| 2854 }; | |
| 2855 | |
| 2856 | |
| 2857 class RegExpDisjunction final : public RegExpTree { | |
| 2858 public: | |
| 2859 explicit RegExpDisjunction(ZoneList<RegExpTree*>* alternatives); | |
| 2860 void* Accept(RegExpVisitor* visitor, void* data) override; | |
| 2861 RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; | |
| 2862 RegExpDisjunction* AsDisjunction() override; | |
| 2863 Interval CaptureRegisters() override; | |
| 2864 bool IsDisjunction() override; | |
| 2865 bool IsAnchoredAtStart() override; | |
| 2866 bool IsAnchoredAtEnd() override; | |
| 2867 int min_match() override { return min_match_; } | |
| 2868 int max_match() override { return max_match_; } | |
| 2869 ZoneList<RegExpTree*>* alternatives() { return alternatives_; } | |
| 2870 private: | |
| 2871 bool SortConsecutiveAtoms(RegExpCompiler* compiler); | |
| 2872 void RationalizeConsecutiveAtoms(RegExpCompiler* compiler); | |
| 2873 void FixSingleCharacterDisjunctions(RegExpCompiler* compiler); | |
| 2874 ZoneList<RegExpTree*>* alternatives_; | |
| 2875 int min_match_; | |
| 2876 int max_match_; | |
| 2877 }; | |
| 2878 | |
| 2879 | |
| 2880 class RegExpAlternative final : public RegExpTree { | |
| 2881 public: | |
| 2882 explicit RegExpAlternative(ZoneList<RegExpTree*>* nodes); | |
| 2883 void* Accept(RegExpVisitor* visitor, void* data) override; | |
| 2884 RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; | |
| 2885 RegExpAlternative* AsAlternative() override; | |
| 2886 Interval CaptureRegisters() override; | |
| 2887 bool IsAlternative() override; | |
| 2888 bool IsAnchoredAtStart() override; | |
| 2889 bool IsAnchoredAtEnd() override; | |
| 2890 int min_match() override { return min_match_; } | |
| 2891 int max_match() override { return max_match_; } | |
| 2892 ZoneList<RegExpTree*>* nodes() { return nodes_; } | |
| 2893 private: | |
| 2894 ZoneList<RegExpTree*>* nodes_; | |
| 2895 int min_match_; | |
| 2896 int max_match_; | |
| 2897 }; | |
| 2898 | |
| 2899 | |
| 2900 class RegExpAssertion final : public RegExpTree { | |
| 2901 public: | |
| 2902 enum AssertionType { | |
| 2903 START_OF_LINE, | |
| 2904 START_OF_INPUT, | |
| 2905 END_OF_LINE, | |
| 2906 END_OF_INPUT, | |
| 2907 BOUNDARY, | |
| 2908 NON_BOUNDARY | |
| 2909 }; | |
| 2910 explicit RegExpAssertion(AssertionType type) : assertion_type_(type) { } | |
| 2911 void* Accept(RegExpVisitor* visitor, void* data) override; | |
| 2912 RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; | |
| 2913 RegExpAssertion* AsAssertion() override; | |
| 2914 bool IsAssertion() override; | |
| 2915 bool IsAnchoredAtStart() override; | |
| 2916 bool IsAnchoredAtEnd() override; | |
| 2917 int min_match() override { return 0; } | |
| 2918 int max_match() override { return 0; } | |
| 2919 AssertionType assertion_type() { return assertion_type_; } | |
| 2920 private: | |
| 2921 AssertionType assertion_type_; | |
| 2922 }; | |
| 2923 | |
| 2924 | |
| 2925 class CharacterSet final BASE_EMBEDDED { | |
| 2926 public: | |
| 2927 explicit CharacterSet(uc16 standard_set_type) | |
| 2928 : ranges_(NULL), | |
| 2929 standard_set_type_(standard_set_type) {} | |
| 2930 explicit CharacterSet(ZoneList<CharacterRange>* ranges) | |
| 2931 : ranges_(ranges), | |
| 2932 standard_set_type_(0) {} | |
| 2933 ZoneList<CharacterRange>* ranges(Zone* zone); | |
| 2934 uc16 standard_set_type() { return standard_set_type_; } | |
| 2935 void set_standard_set_type(uc16 special_set_type) { | |
| 2936 standard_set_type_ = special_set_type; | |
| 2937 } | |
| 2938 bool is_standard() { return standard_set_type_ != 0; } | |
| 2939 void Canonicalize(); | |
| 2940 private: | |
| 2941 ZoneList<CharacterRange>* ranges_; | |
| 2942 // If non-zero, the value represents a standard set (e.g., all whitespace | |
| 2943 // characters) without having to expand the ranges. | |
| 2944 uc16 standard_set_type_; | |
| 2945 }; | |
| 2946 | |
| 2947 | |
| 2948 class RegExpCharacterClass final : public RegExpTree { | |
| 2949 public: | |
| 2950 RegExpCharacterClass(ZoneList<CharacterRange>* ranges, bool is_negated) | |
| 2951 : set_(ranges), | |
| 2952 is_negated_(is_negated) { } | |
| 2953 explicit RegExpCharacterClass(uc16 type) | |
| 2954 : set_(type), | |
| 2955 is_negated_(false) { } | |
| 2956 void* Accept(RegExpVisitor* visitor, void* data) override; | |
| 2957 RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; | |
| 2958 RegExpCharacterClass* AsCharacterClass() override; | |
| 2959 bool IsCharacterClass() override; | |
| 2960 bool IsTextElement() override { return true; } | |
| 2961 int min_match() override { return 1; } | |
| 2962 int max_match() override { return 1; } | |
| 2963 void AppendToText(RegExpText* text, Zone* zone) override; | |
| 2964 CharacterSet character_set() { return set_; } | |
| 2965 // TODO(lrn): Remove need for complex version if is_standard that | |
| 2966 // recognizes a mangled standard set and just do { return set_.is_special(); } | |
| 2967 bool is_standard(Zone* zone); | |
| 2968 // Returns a value representing the standard character set if is_standard() | |
| 2969 // returns true. | |
| 2970 // Currently used values are: | |
| 2971 // s : unicode whitespace | |
| 2972 // S : unicode non-whitespace | |
| 2973 // w : ASCII word character (digit, letter, underscore) | |
| 2974 // W : non-ASCII word character | |
| 2975 // d : ASCII digit | |
| 2976 // D : non-ASCII digit | |
| 2977 // . : non-unicode non-newline | |
| 2978 // * : All characters | |
| 2979 uc16 standard_type() { return set_.standard_set_type(); } | |
| 2980 ZoneList<CharacterRange>* ranges(Zone* zone) { return set_.ranges(zone); } | |
| 2981 bool is_negated() { return is_negated_; } | |
| 2982 | |
| 2983 private: | |
| 2984 CharacterSet set_; | |
| 2985 bool is_negated_; | |
| 2986 }; | |
| 2987 | |
| 2988 | |
| 2989 class RegExpAtom final : public RegExpTree { | |
| 2990 public: | |
| 2991 explicit RegExpAtom(Vector<const uc16> data) : data_(data) { } | |
| 2992 void* Accept(RegExpVisitor* visitor, void* data) override; | |
| 2993 RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; | |
| 2994 RegExpAtom* AsAtom() override; | |
| 2995 bool IsAtom() override; | |
| 2996 bool IsTextElement() override { return true; } | |
| 2997 int min_match() override { return data_.length(); } | |
| 2998 int max_match() override { return data_.length(); } | |
| 2999 void AppendToText(RegExpText* text, Zone* zone) override; | |
| 3000 Vector<const uc16> data() { return data_; } | |
| 3001 int length() { return data_.length(); } | |
| 3002 private: | |
| 3003 Vector<const uc16> data_; | |
| 3004 }; | |
| 3005 | |
| 3006 | |
| 3007 class RegExpText final : public RegExpTree { | |
| 3008 public: | |
| 3009 explicit RegExpText(Zone* zone) : elements_(2, zone), length_(0) {} | |
| 3010 void* Accept(RegExpVisitor* visitor, void* data) override; | |
| 3011 RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; | |
| 3012 RegExpText* AsText() override; | |
| 3013 bool IsText() override; | |
| 3014 bool IsTextElement() override { return true; } | |
| 3015 int min_match() override { return length_; } | |
| 3016 int max_match() override { return length_; } | |
| 3017 void AppendToText(RegExpText* text, Zone* zone) override; | |
| 3018 void AddElement(TextElement elm, Zone* zone) { | |
| 3019 elements_.Add(elm, zone); | |
| 3020 length_ += elm.length(); | |
| 3021 } | |
| 3022 ZoneList<TextElement>* elements() { return &elements_; } | |
| 3023 private: | |
| 3024 ZoneList<TextElement> elements_; | |
| 3025 int length_; | |
| 3026 }; | |
| 3027 | |
| 3028 | |
| 3029 class RegExpQuantifier final : public RegExpTree { | |
| 3030 public: | |
| 3031 enum QuantifierType { GREEDY, NON_GREEDY, POSSESSIVE }; | |
| 3032 RegExpQuantifier(int min, int max, QuantifierType type, RegExpTree* body) | |
| 3033 : body_(body), | |
| 3034 min_(min), | |
| 3035 max_(max), | |
| 3036 min_match_(min * body->min_match()), | |
| 3037 quantifier_type_(type) { | |
| 3038 if (max > 0 && body->max_match() > kInfinity / max) { | |
| 3039 max_match_ = kInfinity; | |
| 3040 } else { | |
| 3041 max_match_ = max * body->max_match(); | |
| 3042 } | |
| 3043 } | |
| 3044 void* Accept(RegExpVisitor* visitor, void* data) override; | |
| 3045 RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; | |
| 3046 static RegExpNode* ToNode(int min, | |
| 3047 int max, | |
| 3048 bool is_greedy, | |
| 3049 RegExpTree* body, | |
| 3050 RegExpCompiler* compiler, | |
| 3051 RegExpNode* on_success, | |
| 3052 bool not_at_start = false); | |
| 3053 RegExpQuantifier* AsQuantifier() override; | |
| 3054 Interval CaptureRegisters() override; | |
| 3055 bool IsQuantifier() override; | |
| 3056 int min_match() override { return min_match_; } | |
| 3057 int max_match() override { return max_match_; } | |
| 3058 int min() { return min_; } | |
| 3059 int max() { return max_; } | |
| 3060 bool is_possessive() { return quantifier_type_ == POSSESSIVE; } | |
| 3061 bool is_non_greedy() { return quantifier_type_ == NON_GREEDY; } | |
| 3062 bool is_greedy() { return quantifier_type_ == GREEDY; } | |
| 3063 RegExpTree* body() { return body_; } | |
| 3064 | |
| 3065 private: | |
| 3066 RegExpTree* body_; | |
| 3067 int min_; | |
| 3068 int max_; | |
| 3069 int min_match_; | |
| 3070 int max_match_; | |
| 3071 QuantifierType quantifier_type_; | |
| 3072 }; | |
| 3073 | |
| 3074 | |
| 3075 class RegExpCapture final : public RegExpTree { | |
| 3076 public: | |
| 3077 explicit RegExpCapture(int index) : body_(NULL), index_(index) {} | |
| 3078 void* Accept(RegExpVisitor* visitor, void* data) override; | |
| 3079 RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; | |
| 3080 static RegExpNode* ToNode(RegExpTree* body, | |
| 3081 int index, | |
| 3082 RegExpCompiler* compiler, | |
| 3083 RegExpNode* on_success); | |
| 3084 RegExpCapture* AsCapture() override; | |
| 3085 bool IsAnchoredAtStart() override; | |
| 3086 bool IsAnchoredAtEnd() override; | |
| 3087 Interval CaptureRegisters() override; | |
| 3088 bool IsCapture() override; | |
| 3089 int min_match() override { return body_->min_match(); } | |
| 3090 int max_match() override { return body_->max_match(); } | |
| 3091 RegExpTree* body() { return body_; } | |
| 3092 void set_body(RegExpTree* body) { body_ = body; } | |
| 3093 int index() { return index_; } | |
| 3094 static int StartRegister(int index) { return index * 2; } | |
| 3095 static int EndRegister(int index) { return index * 2 + 1; } | |
| 3096 | |
| 3097 private: | |
| 3098 RegExpTree* body_; | |
| 3099 int index_; | |
| 3100 }; | |
| 3101 | |
| 3102 | |
| 3103 class RegExpLookaround final : public RegExpTree { | |
| 3104 public: | |
| 3105 enum Type { LOOKAHEAD, LOOKBEHIND }; | |
| 3106 | |
| 3107 RegExpLookaround(RegExpTree* body, bool is_positive, int capture_count, | |
| 3108 int capture_from, Type type) | |
| 3109 : body_(body), | |
| 3110 is_positive_(is_positive), | |
| 3111 capture_count_(capture_count), | |
| 3112 capture_from_(capture_from), | |
| 3113 type_(type) {} | |
| 3114 | |
| 3115 void* Accept(RegExpVisitor* visitor, void* data) override; | |
| 3116 RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; | |
| 3117 RegExpLookaround* AsLookaround() override; | |
| 3118 Interval CaptureRegisters() override; | |
| 3119 bool IsLookaround() override; | |
| 3120 bool IsAnchoredAtStart() override; | |
| 3121 int min_match() override { return 0; } | |
| 3122 int max_match() override { return 0; } | |
| 3123 RegExpTree* body() { return body_; } | |
| 3124 bool is_positive() { return is_positive_; } | |
| 3125 int capture_count() { return capture_count_; } | |
| 3126 int capture_from() { return capture_from_; } | |
| 3127 Type type() { return type_; } | |
| 3128 | |
| 3129 private: | |
| 3130 RegExpTree* body_; | |
| 3131 bool is_positive_; | |
| 3132 int capture_count_; | |
| 3133 int capture_from_; | |
| 3134 Type type_; | |
| 3135 }; | |
| 3136 | |
| 3137 | |
| 3138 class RegExpBackReference final : public RegExpTree { | |
| 3139 public: | |
| 3140 explicit RegExpBackReference(RegExpCapture* capture) | |
| 3141 : capture_(capture) { } | |
| 3142 void* Accept(RegExpVisitor* visitor, void* data) override; | |
| 3143 RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; | |
| 3144 RegExpBackReference* AsBackReference() override; | |
| 3145 bool IsBackReference() override; | |
| 3146 int min_match() override { return 0; } | |
| 3147 // The capture may not be completely parsed yet, if the reference occurs | |
| 3148 // before the capture. In the ordinary case, nothing has been captured yet, | |
| 3149 // so the back reference must have the length 0. If the back reference is | |
| 3150 // inside a lookbehind, effectively making it a forward reference, we return | |
| 3151 // 0 since lookbehinds have a length of 0. | |
| 3152 int max_match() override { | |
| 3153 return capture_->body() ? capture_->max_match() : 0; | |
| 3154 } | |
| 3155 int index() { return capture_->index(); } | |
| 3156 RegExpCapture* capture() { return capture_; } | |
| 3157 private: | |
| 3158 RegExpCapture* capture_; | |
| 3159 }; | |
| 3160 | |
| 3161 | |
| 3162 class RegExpEmpty final : public RegExpTree { | |
| 3163 public: | |
| 3164 RegExpEmpty() { } | |
| 3165 void* Accept(RegExpVisitor* visitor, void* data) override; | |
| 3166 RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; | |
| 3167 RegExpEmpty* AsEmpty() override; | |
| 3168 bool IsEmpty() override; | |
| 3169 int min_match() override { return 0; } | |
| 3170 int max_match() override { return 0; } | |
| 3171 }; | |
| 3172 | |
| 3173 | |
| 3174 // ---------------------------------------------------------------------------- | |
| 3175 // Basic visitor | |
| 3176 // - leaf node visitors are abstract. | |
| 3177 | |
| 3178 class AstVisitor BASE_EMBEDDED { | |
| 3179 public: | |
| 3180 AstVisitor() {} | |
| 3181 virtual ~AstVisitor() {} | |
| 3182 | |
| 3183 // Stack overflow check and dynamic dispatch. | |
| 3184 virtual void Visit(AstNode* node) = 0; | |
| 3185 | |
| 3186 // Iteration left-to-right. | |
| 3187 virtual void VisitDeclarations(ZoneList<Declaration*>* declarations); | |
| 3188 virtual void VisitStatements(ZoneList<Statement*>* statements); | |
| 3189 virtual void VisitExpressions(ZoneList<Expression*>* expressions); | |
| 3190 | |
| 3191 // Individual AST nodes. | |
| 3192 #define DEF_VISIT(type) \ | |
| 3193 virtual void Visit##type(type* node) = 0; | |
| 3194 AST_NODE_LIST(DEF_VISIT) | |
| 3195 #undef DEF_VISIT | |
| 3196 }; | |
| 3197 | |
| 3198 | |
| 3199 #define DEFINE_AST_VISITOR_SUBCLASS_MEMBERS() \ | |
| 3200 public: \ | |
| 3201 void Visit(AstNode* node) final { \ | |
| 3202 if (!CheckStackOverflow()) node->Accept(this); \ | |
| 3203 } \ | |
| 3204 \ | |
| 3205 void SetStackOverflow() { stack_overflow_ = true; } \ | |
| 3206 void ClearStackOverflow() { stack_overflow_ = false; } \ | |
| 3207 bool HasStackOverflow() const { return stack_overflow_; } \ | |
| 3208 \ | |
| 3209 bool CheckStackOverflow() { \ | |
| 3210 if (stack_overflow_) return true; \ | |
| 3211 if (GetCurrentStackPosition() < stack_limit_) { \ | |
| 3212 stack_overflow_ = true; \ | |
| 3213 return true; \ | |
| 3214 } \ | |
| 3215 return false; \ | |
| 3216 } \ | |
| 3217 \ | |
| 3218 private: \ | |
| 3219 void InitializeAstVisitor(Isolate* isolate) { \ | |
| 3220 stack_limit_ = isolate->stack_guard()->real_climit(); \ | |
| 3221 stack_overflow_ = false; \ | |
| 3222 } \ | |
| 3223 \ | |
| 3224 void InitializeAstVisitor(uintptr_t stack_limit) { \ | |
| 3225 stack_limit_ = stack_limit; \ | |
| 3226 stack_overflow_ = false; \ | |
| 3227 } \ | |
| 3228 \ | |
| 3229 uintptr_t stack_limit_; \ | |
| 3230 bool stack_overflow_ | |
| 3231 | |
| 3232 | |
| 3233 // ---------------------------------------------------------------------------- | |
| 3234 // AstNode factory | |
| 3235 | |
| 3236 class AstNodeFactory final BASE_EMBEDDED { | |
| 3237 public: | |
| 3238 explicit AstNodeFactory(AstValueFactory* ast_value_factory) | |
| 3239 : local_zone_(ast_value_factory->zone()), | |
| 3240 parser_zone_(ast_value_factory->zone()), | |
| 3241 ast_value_factory_(ast_value_factory) {} | |
| 3242 | |
| 3243 AstValueFactory* ast_value_factory() const { return ast_value_factory_; } | |
| 3244 | |
| 3245 VariableDeclaration* NewVariableDeclaration( | |
| 3246 VariableProxy* proxy, VariableMode mode, Scope* scope, int pos, | |
| 3247 bool is_class_declaration = false, int declaration_group_start = -1) { | |
| 3248 return new (parser_zone_) | |
| 3249 VariableDeclaration(parser_zone_, proxy, mode, scope, pos, | |
| 3250 is_class_declaration, declaration_group_start); | |
| 3251 } | |
| 3252 | |
| 3253 FunctionDeclaration* NewFunctionDeclaration(VariableProxy* proxy, | |
| 3254 VariableMode mode, | |
| 3255 FunctionLiteral* fun, | |
| 3256 Scope* scope, | |
| 3257 int pos) { | |
| 3258 return new (parser_zone_) | |
| 3259 FunctionDeclaration(parser_zone_, proxy, mode, fun, scope, pos); | |
| 3260 } | |
| 3261 | |
| 3262 ImportDeclaration* NewImportDeclaration(VariableProxy* proxy, | |
| 3263 const AstRawString* import_name, | |
| 3264 const AstRawString* module_specifier, | |
| 3265 Scope* scope, int pos) { | |
| 3266 return new (parser_zone_) ImportDeclaration( | |
| 3267 parser_zone_, proxy, import_name, module_specifier, scope, pos); | |
| 3268 } | |
| 3269 | |
| 3270 ExportDeclaration* NewExportDeclaration(VariableProxy* proxy, | |
| 3271 Scope* scope, | |
| 3272 int pos) { | |
| 3273 return new (parser_zone_) | |
| 3274 ExportDeclaration(parser_zone_, proxy, scope, pos); | |
| 3275 } | |
| 3276 | |
| 3277 Block* NewBlock(ZoneList<const AstRawString*>* labels, int capacity, | |
| 3278 bool ignore_completion_value, int pos) { | |
| 3279 return new (local_zone_) | |
| 3280 Block(local_zone_, labels, capacity, ignore_completion_value, pos); | |
| 3281 } | |
| 3282 | |
| 3283 #define STATEMENT_WITH_LABELS(NodeType) \ | |
| 3284 NodeType* New##NodeType(ZoneList<const AstRawString*>* labels, int pos) { \ | |
| 3285 return new (local_zone_) NodeType(local_zone_, labels, pos); \ | |
| 3286 } | |
| 3287 STATEMENT_WITH_LABELS(DoWhileStatement) | |
| 3288 STATEMENT_WITH_LABELS(WhileStatement) | |
| 3289 STATEMENT_WITH_LABELS(ForStatement) | |
| 3290 STATEMENT_WITH_LABELS(SwitchStatement) | |
| 3291 #undef STATEMENT_WITH_LABELS | |
| 3292 | |
| 3293 ForEachStatement* NewForEachStatement(ForEachStatement::VisitMode visit_mode, | |
| 3294 ZoneList<const AstRawString*>* labels, | |
| 3295 int pos) { | |
| 3296 switch (visit_mode) { | |
| 3297 case ForEachStatement::ENUMERATE: { | |
| 3298 return new (local_zone_) ForInStatement(local_zone_, labels, pos); | |
| 3299 } | |
| 3300 case ForEachStatement::ITERATE: { | |
| 3301 return new (local_zone_) ForOfStatement(local_zone_, labels, pos); | |
| 3302 } | |
| 3303 } | |
| 3304 UNREACHABLE(); | |
| 3305 return NULL; | |
| 3306 } | |
| 3307 | |
| 3308 ExpressionStatement* NewExpressionStatement(Expression* expression, int pos) { | |
| 3309 return new (local_zone_) ExpressionStatement(local_zone_, expression, pos); | |
| 3310 } | |
| 3311 | |
| 3312 ContinueStatement* NewContinueStatement(IterationStatement* target, int pos) { | |
| 3313 return new (local_zone_) ContinueStatement(local_zone_, target, pos); | |
| 3314 } | |
| 3315 | |
| 3316 BreakStatement* NewBreakStatement(BreakableStatement* target, int pos) { | |
| 3317 return new (local_zone_) BreakStatement(local_zone_, target, pos); | |
| 3318 } | |
| 3319 | |
| 3320 ReturnStatement* NewReturnStatement(Expression* expression, int pos) { | |
| 3321 return new (local_zone_) ReturnStatement(local_zone_, expression, pos); | |
| 3322 } | |
| 3323 | |
| 3324 WithStatement* NewWithStatement(Scope* scope, | |
| 3325 Expression* expression, | |
| 3326 Statement* statement, | |
| 3327 int pos) { | |
| 3328 return new (local_zone_) | |
| 3329 WithStatement(local_zone_, scope, expression, statement, pos); | |
| 3330 } | |
| 3331 | |
| 3332 IfStatement* NewIfStatement(Expression* condition, | |
| 3333 Statement* then_statement, | |
| 3334 Statement* else_statement, | |
| 3335 int pos) { | |
| 3336 return new (local_zone_) IfStatement(local_zone_, condition, then_statement, | |
| 3337 else_statement, pos); | |
| 3338 } | |
| 3339 | |
| 3340 TryCatchStatement* NewTryCatchStatement(Block* try_block, Scope* scope, | |
| 3341 Variable* variable, | |
| 3342 Block* catch_block, int pos) { | |
| 3343 return new (local_zone_) TryCatchStatement(local_zone_, try_block, scope, | |
| 3344 variable, catch_block, pos); | |
| 3345 } | |
| 3346 | |
| 3347 TryFinallyStatement* NewTryFinallyStatement(Block* try_block, | |
| 3348 Block* finally_block, int pos) { | |
| 3349 return new (local_zone_) | |
| 3350 TryFinallyStatement(local_zone_, try_block, finally_block, pos); | |
| 3351 } | |
| 3352 | |
| 3353 DebuggerStatement* NewDebuggerStatement(int pos) { | |
| 3354 return new (local_zone_) DebuggerStatement(local_zone_, pos); | |
| 3355 } | |
| 3356 | |
| 3357 EmptyStatement* NewEmptyStatement(int pos) { | |
| 3358 return new (local_zone_) EmptyStatement(local_zone_, pos); | |
| 3359 } | |
| 3360 | |
| 3361 SloppyBlockFunctionStatement* NewSloppyBlockFunctionStatement( | |
| 3362 Statement* statement, Scope* scope) { | |
| 3363 return new (local_zone_) | |
| 3364 SloppyBlockFunctionStatement(local_zone_, statement, scope); | |
| 3365 } | |
| 3366 | |
| 3367 CaseClause* NewCaseClause( | |
| 3368 Expression* label, ZoneList<Statement*>* statements, int pos) { | |
| 3369 return new (local_zone_) CaseClause(local_zone_, label, statements, pos); | |
| 3370 } | |
| 3371 | |
| 3372 Literal* NewStringLiteral(const AstRawString* string, int pos) { | |
| 3373 return new (local_zone_) | |
| 3374 Literal(local_zone_, ast_value_factory_->NewString(string), pos); | |
| 3375 } | |
| 3376 | |
| 3377 // A JavaScript symbol (ECMA-262 edition 6). | |
| 3378 Literal* NewSymbolLiteral(const char* name, int pos) { | |
| 3379 return new (local_zone_) | |
| 3380 Literal(local_zone_, ast_value_factory_->NewSymbol(name), pos); | |
| 3381 } | |
| 3382 | |
| 3383 Literal* NewNumberLiteral(double number, int pos, bool with_dot = false) { | |
| 3384 return new (local_zone_) Literal( | |
| 3385 local_zone_, ast_value_factory_->NewNumber(number, with_dot), pos); | |
| 3386 } | |
| 3387 | |
| 3388 Literal* NewSmiLiteral(int number, int pos) { | |
| 3389 return new (local_zone_) | |
| 3390 Literal(local_zone_, ast_value_factory_->NewSmi(number), pos); | |
| 3391 } | |
| 3392 | |
| 3393 Literal* NewBooleanLiteral(bool b, int pos) { | |
| 3394 return new (local_zone_) | |
| 3395 Literal(local_zone_, ast_value_factory_->NewBoolean(b), pos); | |
| 3396 } | |
| 3397 | |
| 3398 Literal* NewNullLiteral(int pos) { | |
| 3399 return new (local_zone_) | |
| 3400 Literal(local_zone_, ast_value_factory_->NewNull(), pos); | |
| 3401 } | |
| 3402 | |
| 3403 Literal* NewUndefinedLiteral(int pos) { | |
| 3404 return new (local_zone_) | |
| 3405 Literal(local_zone_, ast_value_factory_->NewUndefined(), pos); | |
| 3406 } | |
| 3407 | |
| 3408 Literal* NewTheHoleLiteral(int pos) { | |
| 3409 return new (local_zone_) | |
| 3410 Literal(local_zone_, ast_value_factory_->NewTheHole(), pos); | |
| 3411 } | |
| 3412 | |
| 3413 ObjectLiteral* NewObjectLiteral( | |
| 3414 ZoneList<ObjectLiteral::Property*>* properties, | |
| 3415 int literal_index, | |
| 3416 int boilerplate_properties, | |
| 3417 bool has_function, | |
| 3418 bool is_strong, | |
| 3419 int pos) { | |
| 3420 return new (local_zone_) | |
| 3421 ObjectLiteral(local_zone_, properties, literal_index, | |
| 3422 boilerplate_properties, has_function, is_strong, pos); | |
| 3423 } | |
| 3424 | |
| 3425 ObjectLiteral::Property* NewObjectLiteralProperty( | |
| 3426 Expression* key, Expression* value, ObjectLiteralProperty::Kind kind, | |
| 3427 bool is_static, bool is_computed_name) { | |
| 3428 return new (local_zone_) | |
| 3429 ObjectLiteral::Property(key, value, kind, is_static, is_computed_name); | |
| 3430 } | |
| 3431 | |
| 3432 ObjectLiteral::Property* NewObjectLiteralProperty(Expression* key, | |
| 3433 Expression* value, | |
| 3434 bool is_static, | |
| 3435 bool is_computed_name) { | |
| 3436 return new (local_zone_) ObjectLiteral::Property( | |
| 3437 ast_value_factory_, key, value, is_static, is_computed_name); | |
| 3438 } | |
| 3439 | |
| 3440 RegExpLiteral* NewRegExpLiteral(const AstRawString* pattern, int flags, | |
| 3441 int literal_index, bool is_strong, int pos) { | |
| 3442 return new (local_zone_) RegExpLiteral(local_zone_, pattern, flags, | |
| 3443 literal_index, is_strong, pos); | |
| 3444 } | |
| 3445 | |
| 3446 ArrayLiteral* NewArrayLiteral(ZoneList<Expression*>* values, | |
| 3447 int literal_index, | |
| 3448 bool is_strong, | |
| 3449 int pos) { | |
| 3450 return new (local_zone_) | |
| 3451 ArrayLiteral(local_zone_, values, -1, literal_index, is_strong, pos); | |
| 3452 } | |
| 3453 | |
| 3454 ArrayLiteral* NewArrayLiteral(ZoneList<Expression*>* values, | |
| 3455 int first_spread_index, int literal_index, | |
| 3456 bool is_strong, int pos) { | |
| 3457 return new (local_zone_) ArrayLiteral( | |
| 3458 local_zone_, values, first_spread_index, literal_index, is_strong, pos); | |
| 3459 } | |
| 3460 | |
| 3461 VariableProxy* NewVariableProxy(Variable* var, | |
| 3462 int start_position = RelocInfo::kNoPosition, | |
| 3463 int end_position = RelocInfo::kNoPosition) { | |
| 3464 return new (parser_zone_) | |
| 3465 VariableProxy(parser_zone_, var, start_position, end_position); | |
| 3466 } | |
| 3467 | |
| 3468 VariableProxy* NewVariableProxy(const AstRawString* name, | |
| 3469 Variable::Kind variable_kind, | |
| 3470 int start_position = RelocInfo::kNoPosition, | |
| 3471 int end_position = RelocInfo::kNoPosition) { | |
| 3472 DCHECK_NOT_NULL(name); | |
| 3473 return new (parser_zone_) VariableProxy(parser_zone_, name, variable_kind, | |
| 3474 start_position, end_position); | |
| 3475 } | |
| 3476 | |
| 3477 Property* NewProperty(Expression* obj, Expression* key, int pos) { | |
| 3478 return new (local_zone_) Property(local_zone_, obj, key, pos); | |
| 3479 } | |
| 3480 | |
| 3481 Call* NewCall(Expression* expression, | |
| 3482 ZoneList<Expression*>* arguments, | |
| 3483 int pos) { | |
| 3484 return new (local_zone_) Call(local_zone_, expression, arguments, pos); | |
| 3485 } | |
| 3486 | |
| 3487 CallNew* NewCallNew(Expression* expression, | |
| 3488 ZoneList<Expression*>* arguments, | |
| 3489 int pos) { | |
| 3490 return new (local_zone_) CallNew(local_zone_, expression, arguments, pos); | |
| 3491 } | |
| 3492 | |
| 3493 CallRuntime* NewCallRuntime(Runtime::FunctionId id, | |
| 3494 ZoneList<Expression*>* arguments, int pos) { | |
| 3495 return new (local_zone_) | |
| 3496 CallRuntime(local_zone_, Runtime::FunctionForId(id), arguments, pos); | |
| 3497 } | |
| 3498 | |
| 3499 CallRuntime* NewCallRuntime(const Runtime::Function* function, | |
| 3500 ZoneList<Expression*>* arguments, int pos) { | |
| 3501 return new (local_zone_) CallRuntime(local_zone_, function, arguments, pos); | |
| 3502 } | |
| 3503 | |
| 3504 CallRuntime* NewCallRuntime(int context_index, | |
| 3505 ZoneList<Expression*>* arguments, int pos) { | |
| 3506 return new (local_zone_) | |
| 3507 CallRuntime(local_zone_, context_index, arguments, pos); | |
| 3508 } | |
| 3509 | |
| 3510 UnaryOperation* NewUnaryOperation(Token::Value op, | |
| 3511 Expression* expression, | |
| 3512 int pos) { | |
| 3513 return new (local_zone_) UnaryOperation(local_zone_, op, expression, pos); | |
| 3514 } | |
| 3515 | |
| 3516 BinaryOperation* NewBinaryOperation(Token::Value op, | |
| 3517 Expression* left, | |
| 3518 Expression* right, | |
| 3519 int pos) { | |
| 3520 return new (local_zone_) BinaryOperation(local_zone_, op, left, right, pos); | |
| 3521 } | |
| 3522 | |
| 3523 CountOperation* NewCountOperation(Token::Value op, | |
| 3524 bool is_prefix, | |
| 3525 Expression* expr, | |
| 3526 int pos) { | |
| 3527 return new (local_zone_) | |
| 3528 CountOperation(local_zone_, op, is_prefix, expr, pos); | |
| 3529 } | |
| 3530 | |
| 3531 CompareOperation* NewCompareOperation(Token::Value op, | |
| 3532 Expression* left, | |
| 3533 Expression* right, | |
| 3534 int pos) { | |
| 3535 return new (local_zone_) | |
| 3536 CompareOperation(local_zone_, op, left, right, pos); | |
| 3537 } | |
| 3538 | |
| 3539 Spread* NewSpread(Expression* expression, int pos) { | |
| 3540 return new (local_zone_) Spread(local_zone_, expression, pos); | |
| 3541 } | |
| 3542 | |
| 3543 Conditional* NewConditional(Expression* condition, | |
| 3544 Expression* then_expression, | |
| 3545 Expression* else_expression, | |
| 3546 int position) { | |
| 3547 return new (local_zone_) Conditional( | |
| 3548 local_zone_, condition, then_expression, else_expression, position); | |
| 3549 } | |
| 3550 | |
| 3551 Assignment* NewAssignment(Token::Value op, | |
| 3552 Expression* target, | |
| 3553 Expression* value, | |
| 3554 int pos) { | |
| 3555 DCHECK(Token::IsAssignmentOp(op)); | |
| 3556 Assignment* assign = | |
| 3557 new (local_zone_) Assignment(local_zone_, op, target, value, pos); | |
| 3558 if (assign->is_compound()) { | |
| 3559 DCHECK(Token::IsAssignmentOp(op)); | |
| 3560 assign->binary_operation_ = | |
| 3561 NewBinaryOperation(assign->binary_op(), target, value, pos + 1); | |
| 3562 } | |
| 3563 return assign; | |
| 3564 } | |
| 3565 | |
| 3566 Yield* NewYield(Expression *generator_object, | |
| 3567 Expression* expression, | |
| 3568 Yield::Kind yield_kind, | |
| 3569 int pos) { | |
| 3570 if (!expression) expression = NewUndefinedLiteral(pos); | |
| 3571 return new (local_zone_) | |
| 3572 Yield(local_zone_, generator_object, expression, yield_kind, pos); | |
| 3573 } | |
| 3574 | |
| 3575 Throw* NewThrow(Expression* exception, int pos) { | |
| 3576 return new (local_zone_) Throw(local_zone_, exception, pos); | |
| 3577 } | |
| 3578 | |
| 3579 FunctionLiteral* NewFunctionLiteral( | |
| 3580 const AstRawString* name, AstValueFactory* ast_value_factory, | |
| 3581 Scope* scope, ZoneList<Statement*>* body, int materialized_literal_count, | |
| 3582 int expected_property_count, int parameter_count, | |
| 3583 FunctionLiteral::ParameterFlag has_duplicate_parameters, | |
| 3584 FunctionLiteral::FunctionType function_type, | |
| 3585 FunctionLiteral::IsFunctionFlag is_function, | |
| 3586 FunctionLiteral::EagerCompileHint eager_compile_hint, FunctionKind kind, | |
| 3587 int position) { | |
| 3588 return new (parser_zone_) FunctionLiteral( | |
| 3589 parser_zone_, name, ast_value_factory, scope, body, | |
| 3590 materialized_literal_count, expected_property_count, parameter_count, | |
| 3591 function_type, has_duplicate_parameters, is_function, | |
| 3592 eager_compile_hint, kind, position); | |
| 3593 } | |
| 3594 | |
| 3595 ClassLiteral* NewClassLiteral(const AstRawString* name, Scope* scope, | |
| 3596 VariableProxy* proxy, Expression* extends, | |
| 3597 FunctionLiteral* constructor, | |
| 3598 ZoneList<ObjectLiteral::Property*>* properties, | |
| 3599 int start_position, int end_position) { | |
| 3600 return new (parser_zone_) | |
| 3601 ClassLiteral(parser_zone_, name, scope, proxy, extends, constructor, | |
| 3602 properties, start_position, end_position); | |
| 3603 } | |
| 3604 | |
| 3605 NativeFunctionLiteral* NewNativeFunctionLiteral(const AstRawString* name, | |
| 3606 v8::Extension* extension, | |
| 3607 int pos) { | |
| 3608 return new (parser_zone_) | |
| 3609 NativeFunctionLiteral(parser_zone_, name, extension, pos); | |
| 3610 } | |
| 3611 | |
| 3612 DoExpression* NewDoExpression(Block* block, Variable* result_var, int pos) { | |
| 3613 VariableProxy* result = NewVariableProxy(result_var, pos); | |
| 3614 return new (parser_zone_) DoExpression(parser_zone_, block, result, pos); | |
| 3615 } | |
| 3616 | |
| 3617 ThisFunction* NewThisFunction(int pos) { | |
| 3618 return new (local_zone_) ThisFunction(local_zone_, pos); | |
| 3619 } | |
| 3620 | |
| 3621 SuperPropertyReference* NewSuperPropertyReference(VariableProxy* this_var, | |
| 3622 Expression* home_object, | |
| 3623 int pos) { | |
| 3624 return new (parser_zone_) | |
| 3625 SuperPropertyReference(parser_zone_, this_var, home_object, pos); | |
| 3626 } | |
| 3627 | |
| 3628 SuperCallReference* NewSuperCallReference(VariableProxy* this_var, | |
| 3629 VariableProxy* new_target_var, | |
| 3630 VariableProxy* this_function_var, | |
| 3631 int pos) { | |
| 3632 return new (parser_zone_) SuperCallReference( | |
| 3633 parser_zone_, this_var, new_target_var, this_function_var, pos); | |
| 3634 } | |
| 3635 | |
| 3636 EmptyParentheses* NewEmptyParentheses(int pos) { | |
| 3637 return new (local_zone_) EmptyParentheses(local_zone_, pos); | |
| 3638 } | |
| 3639 | |
| 3640 Zone* zone() const { return local_zone_; } | |
| 3641 | |
| 3642 // Handles use of temporary zones when parsing inner function bodies. | |
| 3643 class BodyScope { | |
| 3644 public: | |
| 3645 BodyScope(AstNodeFactory* factory, Zone* temp_zone, bool use_temp_zone) | |
| 3646 : factory_(factory), prev_zone_(factory->local_zone_) { | |
| 3647 if (use_temp_zone) { | |
| 3648 factory->local_zone_ = temp_zone; | |
| 3649 } | |
| 3650 } | |
| 3651 | |
| 3652 ~BodyScope() { factory_->local_zone_ = prev_zone_; } | |
| 3653 | |
| 3654 private: | |
| 3655 AstNodeFactory* factory_; | |
| 3656 Zone* prev_zone_; | |
| 3657 }; | |
| 3658 | |
| 3659 private: | |
| 3660 // This zone may be deallocated upon returning from parsing a function body | |
| 3661 // which we can guarantee is not going to be compiled or have its AST | |
| 3662 // inspected. | |
| 3663 // See ParseFunctionLiteral in parser.cc for preconditions. | |
| 3664 Zone* local_zone_; | |
| 3665 // ZoneObjects which need to persist until scope analysis must be allocated in | |
| 3666 // the parser-level zone. | |
| 3667 Zone* parser_zone_; | |
| 3668 AstValueFactory* ast_value_factory_; | |
| 3669 }; | |
| 3670 | |
| 3671 | |
| 3672 } // namespace internal | |
| 3673 } // namespace v8 | |
| 3674 | |
| 3675 #endif // V8_AST_H_ | |
| OLD | NEW |