1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_AST_H_ 29 #define V8_AST_H_ 30 31 #include "execution.h" 32 #include "factory.h" 33 #include "jsregexp.h" 34 #include "runtime.h" 35 #include "token.h" 36 #include "variables.h" 37 38 namespace v8 { 39 namespace internal { 40 41 // The abstract syntax tree is an intermediate, light-weight 42 // representation of the parsed JavaScript code suitable for 43 // compilation to native code. 44 45 // Nodes are allocated in a separate zone, which allows faster 46 // allocation and constant-time deallocation of the entire syntax 47 // tree. 48 49 50 // ---------------------------------------------------------------------------- 51 // Nodes of the abstract syntax tree. Only concrete classes are 52 // enumerated here. 53 54 #define STATEMENT_NODE_LIST(V) \ 55 V(Block) \ 56 V(ExpressionStatement) \ 57 V(EmptyStatement) \ 58 V(IfStatement) \ 59 V(ContinueStatement) \ 60 V(BreakStatement) \ 61 V(ReturnStatement) \ 62 V(WithEnterStatement) \ 63 V(WithExitStatement) \ 64 V(SwitchStatement) \ 65 V(DoWhileStatement) \ 66 V(WhileStatement) \ 67 V(ForStatement) \ 68 V(ForInStatement) \ 69 V(TryCatchStatement) \ 70 V(TryFinallyStatement) \ 71 V(DebuggerStatement) 72 73 #define EXPRESSION_NODE_LIST(V) \ 74 V(FunctionLiteral) \ 75 V(SharedFunctionInfoLiteral) \ 76 V(Conditional) \ 77 V(VariableProxy) \ 78 V(Literal) \ 79 V(RegExpLiteral) \ 80 V(ObjectLiteral) \ 81 V(ArrayLiteral) \ 82 V(CatchExtensionObject) \ 83 V(Assignment) \ 84 V(Throw) \ 85 V(Property) \ 86 V(Call) \ 87 V(CallNew) \ 88 V(CallRuntime) \ 89 V(UnaryOperation) \ 90 V(CountOperation) \ 91 V(BinaryOperation) \ 92 V(CompareOperation) \ 93 V(CompareToNull) \ 94 V(ThisFunction) 95 96 #define AST_NODE_LIST(V) \ 97 V(Declaration) \ 98 STATEMENT_NODE_LIST(V) \ 99 EXPRESSION_NODE_LIST(V) 100 101 // Forward declarations 102 class BitVector; 103 class DefinitionInfo; 104 class MaterializedLiteral; 105 class TargetCollector; 106 class TypeFeedbackOracle; 107 108 #define DEF_FORWARD_DECLARATION(type) class type; 109 AST_NODE_LIST(DEF_FORWARD_DECLARATION) 110 #undef DEF_FORWARD_DECLARATION 111 112 113 // Typedef only introduced to avoid unreadable code. 114 // Please do appreciate the required space in "> >". 115 typedef ZoneList<Handle<String> > ZoneStringList; 116 typedef ZoneList<Handle<Object> > ZoneObjectList; 117 118 119 #define DECLARE_NODE_TYPE(type) \ 120 virtual void Accept(AstVisitor* v); \ 121 virtual AstNode::Type node_type() const { return AstNode::k##type; } \ 122 virtual type* As##type() { return this; } 123 124 125 class AstNode: public ZoneObject { 126 public: 127 #define DECLARE_TYPE_ENUM(type) k##type, 128 enum Type { 129 AST_NODE_LIST(DECLARE_TYPE_ENUM) 130 kInvalid = -1 131 }; 132 #undef DECLARE_TYPE_ENUM 133 134 static const int kNoNumber = -1; 135 static const int kFunctionEntryId = 2; // Using 0 could disguise errors. 136 AstNode()137 AstNode() : id_(GetNextId()) { 138 Isolate* isolate = Isolate::Current(); 139 isolate->set_ast_node_count(isolate->ast_node_count() + 1); 140 } 141 ~AstNode()142 virtual ~AstNode() { } 143 144 virtual void Accept(AstVisitor* v) = 0; node_type()145 virtual Type node_type() const { return kInvalid; } 146 147 // Type testing & conversion functions overridden by concrete subclasses. 148 #define DECLARE_NODE_FUNCTIONS(type) \ 149 virtual type* As##type() { return NULL; } AST_NODE_LIST(DECLARE_NODE_FUNCTIONS)150 AST_NODE_LIST(DECLARE_NODE_FUNCTIONS) 151 #undef DECLARE_NODE_FUNCTIONS 152 153 virtual Statement* AsStatement() { return NULL; } AsExpression()154 virtual Expression* AsExpression() { return NULL; } AsTargetCollector()155 virtual TargetCollector* AsTargetCollector() { return NULL; } AsBreakableStatement()156 virtual BreakableStatement* AsBreakableStatement() { return NULL; } AsIterationStatement()157 virtual IterationStatement* AsIterationStatement() { return NULL; } AsMaterializedLiteral()158 virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; } AsSlot()159 virtual Slot* AsSlot() { return NULL; } 160 161 // True if the node is simple enough for us to inline calls containing it. 162 virtual bool IsInlineable() const = 0; 163 Count()164 static int Count() { return Isolate::Current()->ast_node_count(); } ResetIds()165 static void ResetIds() { Isolate::Current()->set_ast_node_id(0); } id()166 unsigned id() const { return id_; } 167 168 protected: GetNextId()169 static unsigned GetNextId() { 170 Isolate* isolate = Isolate::Current(); 171 unsigned tmp = isolate->ast_node_id(); 172 isolate->set_ast_node_id(tmp + 1); 173 return tmp; 174 } ReserveIdRange(int n)175 static unsigned ReserveIdRange(int n) { 176 Isolate* isolate = Isolate::Current(); 177 unsigned tmp = isolate->ast_node_id(); 178 isolate->set_ast_node_id(tmp + n); 179 return tmp; 180 } 181 182 private: 183 unsigned id_; 184 185 friend class CaseClause; // Generates AST IDs. 186 }; 187 188 189 class Statement: public AstNode { 190 public: Statement()191 Statement() : statement_pos_(RelocInfo::kNoPosition) {} 192 AsStatement()193 virtual Statement* AsStatement() { return this; } 194 StatementAsSimpleAssignment()195 virtual Assignment* StatementAsSimpleAssignment() { return NULL; } StatementAsCountOperation()196 virtual CountOperation* StatementAsCountOperation() { return NULL; } 197 IsEmpty()198 bool IsEmpty() { return AsEmptyStatement() != NULL; } 199 set_statement_pos(int statement_pos)200 void set_statement_pos(int statement_pos) { statement_pos_ = statement_pos; } statement_pos()201 int statement_pos() const { return statement_pos_; } 202 203 private: 204 int statement_pos_; 205 }; 206 207 208 class Expression: public AstNode { 209 public: 210 enum Context { 211 // Not assigned a context yet, or else will not be visited during 212 // code generation. 213 kUninitialized, 214 // Evaluated for its side effects. 215 kEffect, 216 // Evaluated for its value (and side effects). 217 kValue, 218 // Evaluated for control flow (and side effects). 219 kTest 220 }; 221 Expression()222 Expression() {} 223 position()224 virtual int position() const { 225 UNREACHABLE(); 226 return 0; 227 } 228 AsExpression()229 virtual Expression* AsExpression() { return this; } 230 IsTrivial()231 virtual bool IsTrivial() { return false; } IsValidLeftHandSide()232 virtual bool IsValidLeftHandSide() { return false; } 233 234 // Helpers for ToBoolean conversion. ToBooleanIsTrue()235 virtual bool ToBooleanIsTrue() { return false; } ToBooleanIsFalse()236 virtual bool ToBooleanIsFalse() { return false; } 237 238 // Symbols that cannot be parsed as array indices are considered property 239 // names. We do not treat symbols that can be array indexes as property 240 // names because [] for string objects is handled only by keyed ICs. IsPropertyName()241 virtual bool IsPropertyName() { return false; } 242 243 // Mark the expression as being compiled as an expression 244 // statement. This is used to transform postfix increments to 245 // (faster) prefix increments. MarkAsStatement()246 virtual void MarkAsStatement() { /* do nothing */ } 247 248 // True iff the result can be safely overwritten (to avoid allocation). 249 // False for operations that can return one of their operands. ResultOverwriteAllowed()250 virtual bool ResultOverwriteAllowed() { return false; } 251 252 // True iff the expression is a literal represented as a smi. IsSmiLiteral()253 virtual bool IsSmiLiteral() { return false; } 254 255 // Type feedback information for assignments and properties. IsMonomorphic()256 virtual bool IsMonomorphic() { 257 UNREACHABLE(); 258 return false; 259 } IsArrayLength()260 virtual bool IsArrayLength() { 261 UNREACHABLE(); 262 return false; 263 } GetReceiverTypes()264 virtual ZoneMapList* GetReceiverTypes() { 265 UNREACHABLE(); 266 return NULL; 267 } GetMonomorphicReceiverType()268 virtual Handle<Map> GetMonomorphicReceiverType() { 269 UNREACHABLE(); 270 return Handle<Map>(); 271 } 272 external_array_type()273 ExternalArrayType external_array_type() const { 274 return external_array_type_; 275 } set_external_array_type(ExternalArrayType array_type)276 void set_external_array_type(ExternalArrayType array_type) { 277 external_array_type_ = array_type; 278 } 279 280 private: 281 ExternalArrayType external_array_type_; 282 }; 283 284 285 /** 286 * A sentinel used during pre parsing that represents some expression 287 * that is a valid left hand side without having to actually build 288 * the expression. 289 */ 290 class ValidLeftHandSideSentinel: public Expression { 291 public: IsValidLeftHandSide()292 virtual bool IsValidLeftHandSide() { return true; } Accept(AstVisitor * v)293 virtual void Accept(AstVisitor* v) { UNREACHABLE(); } 294 virtual bool IsInlineable() const; 295 }; 296 297 298 class BreakableStatement: public Statement { 299 public: 300 enum Type { 301 TARGET_FOR_ANONYMOUS, 302 TARGET_FOR_NAMED_ONLY 303 }; 304 305 // The labels associated with this statement. May be NULL; 306 // if it is != NULL, guaranteed to contain at least one entry. labels()307 ZoneStringList* labels() const { return labels_; } 308 309 // Type testing & conversion. AsBreakableStatement()310 virtual BreakableStatement* AsBreakableStatement() { return this; } 311 312 // Code generation break_target()313 Label* break_target() { return &break_target_; } 314 315 // Testers. is_target_for_anonymous()316 bool is_target_for_anonymous() const { return type_ == TARGET_FOR_ANONYMOUS; } 317 318 // Bailout support. EntryId()319 int EntryId() const { return entry_id_; } ExitId()320 int ExitId() const { return exit_id_; } 321 322 protected: 323 inline BreakableStatement(ZoneStringList* labels, Type type); 324 325 private: 326 ZoneStringList* labels_; 327 Type type_; 328 Label break_target_; 329 int entry_id_; 330 int exit_id_; 331 }; 332 333 334 class Block: public BreakableStatement { 335 public: 336 inline Block(ZoneStringList* labels, int capacity, bool is_initializer_block); 337 DECLARE_NODE_TYPE(Block)338 DECLARE_NODE_TYPE(Block) 339 340 virtual Assignment* StatementAsSimpleAssignment() { 341 if (statements_.length() != 1) return NULL; 342 return statements_[0]->StatementAsSimpleAssignment(); 343 } 344 StatementAsCountOperation()345 virtual CountOperation* StatementAsCountOperation() { 346 if (statements_.length() != 1) return NULL; 347 return statements_[0]->StatementAsCountOperation(); 348 } 349 350 virtual bool IsInlineable() const; 351 AddStatement(Statement * statement)352 void AddStatement(Statement* statement) { statements_.Add(statement); } 353 statements()354 ZoneList<Statement*>* statements() { return &statements_; } is_initializer_block()355 bool is_initializer_block() const { return is_initializer_block_; } 356 357 private: 358 ZoneList<Statement*> statements_; 359 bool is_initializer_block_; 360 }; 361 362 363 class Declaration: public AstNode { 364 public: Declaration(VariableProxy * proxy,Variable::Mode mode,FunctionLiteral * fun)365 Declaration(VariableProxy* proxy, Variable::Mode mode, FunctionLiteral* fun) 366 : proxy_(proxy), 367 mode_(mode), 368 fun_(fun) { 369 ASSERT(mode == Variable::VAR || mode == Variable::CONST); 370 // At the moment there are no "const functions"'s in JavaScript... 371 ASSERT(fun == NULL || mode == Variable::VAR); 372 } 373 DECLARE_NODE_TYPE(Declaration)374 DECLARE_NODE_TYPE(Declaration) 375 376 VariableProxy* proxy() const { return proxy_; } mode()377 Variable::Mode mode() const { return mode_; } fun()378 FunctionLiteral* fun() const { return fun_; } // may be NULL 379 virtual bool IsInlineable() const; 380 381 private: 382 VariableProxy* proxy_; 383 Variable::Mode mode_; 384 FunctionLiteral* fun_; 385 }; 386 387 388 class IterationStatement: public BreakableStatement { 389 public: 390 // Type testing & conversion. AsIterationStatement()391 virtual IterationStatement* AsIterationStatement() { return this; } 392 body()393 Statement* body() const { return body_; } 394 395 // Bailout support. OsrEntryId()396 int OsrEntryId() const { return osr_entry_id_; } 397 virtual int ContinueId() const = 0; 398 399 // Code generation continue_target()400 Label* continue_target() { return &continue_target_; } 401 402 protected: 403 explicit inline IterationStatement(ZoneStringList* labels); 404 Initialize(Statement * body)405 void Initialize(Statement* body) { 406 body_ = body; 407 } 408 409 private: 410 Statement* body_; 411 Label continue_target_; 412 int osr_entry_id_; 413 }; 414 415 416 class DoWhileStatement: public IterationStatement { 417 public: 418 explicit inline DoWhileStatement(ZoneStringList* labels); 419 DECLARE_NODE_TYPE(DoWhileStatement)420 DECLARE_NODE_TYPE(DoWhileStatement) 421 422 void Initialize(Expression* cond, Statement* body) { 423 IterationStatement::Initialize(body); 424 cond_ = cond; 425 } 426 cond()427 Expression* cond() const { return cond_; } 428 429 // Position where condition expression starts. We need it to make 430 // the loop's condition a breakable location. condition_position()431 int condition_position() { return condition_position_; } set_condition_position(int pos)432 void set_condition_position(int pos) { condition_position_ = pos; } 433 434 // Bailout support. ContinueId()435 virtual int ContinueId() const { return continue_id_; } BackEdgeId()436 int BackEdgeId() const { return back_edge_id_; } 437 438 virtual bool IsInlineable() const; 439 440 private: 441 Expression* cond_; 442 int condition_position_; 443 int continue_id_; 444 int back_edge_id_; 445 }; 446 447 448 class WhileStatement: public IterationStatement { 449 public: 450 explicit inline WhileStatement(ZoneStringList* labels); 451 DECLARE_NODE_TYPE(WhileStatement)452 DECLARE_NODE_TYPE(WhileStatement) 453 454 void Initialize(Expression* cond, Statement* body) { 455 IterationStatement::Initialize(body); 456 cond_ = cond; 457 } 458 cond()459 Expression* cond() const { return cond_; } may_have_function_literal()460 bool may_have_function_literal() const { 461 return may_have_function_literal_; 462 } set_may_have_function_literal(bool value)463 void set_may_have_function_literal(bool value) { 464 may_have_function_literal_ = value; 465 } 466 virtual bool IsInlineable() const; 467 468 // Bailout support. ContinueId()469 virtual int ContinueId() const { return EntryId(); } BodyId()470 int BodyId() const { return body_id_; } 471 472 private: 473 Expression* cond_; 474 // True if there is a function literal subexpression in the condition. 475 bool may_have_function_literal_; 476 int body_id_; 477 }; 478 479 480 class ForStatement: public IterationStatement { 481 public: 482 explicit inline ForStatement(ZoneStringList* labels); 483 DECLARE_NODE_TYPE(ForStatement)484 DECLARE_NODE_TYPE(ForStatement) 485 486 void Initialize(Statement* init, 487 Expression* cond, 488 Statement* next, 489 Statement* body) { 490 IterationStatement::Initialize(body); 491 init_ = init; 492 cond_ = cond; 493 next_ = next; 494 } 495 init()496 Statement* init() const { return init_; } cond()497 Expression* cond() const { return cond_; } next()498 Statement* next() const { return next_; } 499 may_have_function_literal()500 bool may_have_function_literal() const { 501 return may_have_function_literal_; 502 } set_may_have_function_literal(bool value)503 void set_may_have_function_literal(bool value) { 504 may_have_function_literal_ = value; 505 } 506 507 // Bailout support. ContinueId()508 virtual int ContinueId() const { return continue_id_; } BodyId()509 int BodyId() const { return body_id_; } 510 is_fast_smi_loop()511 bool is_fast_smi_loop() { return loop_variable_ != NULL; } loop_variable()512 Variable* loop_variable() { return loop_variable_; } set_loop_variable(Variable * var)513 void set_loop_variable(Variable* var) { loop_variable_ = var; } 514 virtual bool IsInlineable() const; 515 516 private: 517 Statement* init_; 518 Expression* cond_; 519 Statement* next_; 520 // True if there is a function literal subexpression in the condition. 521 bool may_have_function_literal_; 522 Variable* loop_variable_; 523 int continue_id_; 524 int body_id_; 525 }; 526 527 528 class ForInStatement: public IterationStatement { 529 public: 530 explicit inline ForInStatement(ZoneStringList* labels); 531 DECLARE_NODE_TYPE(ForInStatement)532 DECLARE_NODE_TYPE(ForInStatement) 533 534 void Initialize(Expression* each, Expression* enumerable, Statement* body) { 535 IterationStatement::Initialize(body); 536 each_ = each; 537 enumerable_ = enumerable; 538 } 539 each()540 Expression* each() const { return each_; } enumerable()541 Expression* enumerable() const { return enumerable_; } 542 virtual bool IsInlineable() const; 543 544 // Bailout support. AssignmentId()545 int AssignmentId() const { return assignment_id_; } ContinueId()546 virtual int ContinueId() const { return EntryId(); } 547 548 private: 549 Expression* each_; 550 Expression* enumerable_; 551 int assignment_id_; 552 }; 553 554 555 class ExpressionStatement: public Statement { 556 public: ExpressionStatement(Expression * expression)557 explicit ExpressionStatement(Expression* expression) 558 : expression_(expression) { } 559 560 DECLARE_NODE_TYPE(ExpressionStatement) 561 562 virtual bool IsInlineable() const; 563 564 virtual Assignment* StatementAsSimpleAssignment(); 565 virtual CountOperation* StatementAsCountOperation(); 566 set_expression(Expression * e)567 void set_expression(Expression* e) { expression_ = e; } expression()568 Expression* expression() const { return expression_; } 569 570 private: 571 Expression* expression_; 572 }; 573 574 575 class ContinueStatement: public Statement { 576 public: ContinueStatement(IterationStatement * target)577 explicit ContinueStatement(IterationStatement* target) 578 : target_(target) { } 579 DECLARE_NODE_TYPE(ContinueStatement)580 DECLARE_NODE_TYPE(ContinueStatement) 581 582 IterationStatement* target() const { return target_; } 583 virtual bool IsInlineable() const; 584 585 private: 586 IterationStatement* target_; 587 }; 588 589 590 class BreakStatement: public Statement { 591 public: BreakStatement(BreakableStatement * target)592 explicit BreakStatement(BreakableStatement* target) 593 : target_(target) { } 594 DECLARE_NODE_TYPE(BreakStatement)595 DECLARE_NODE_TYPE(BreakStatement) 596 597 BreakableStatement* target() const { return target_; } 598 virtual bool IsInlineable() const; 599 600 private: 601 BreakableStatement* target_; 602 }; 603 604 605 class ReturnStatement: public Statement { 606 public: ReturnStatement(Expression * expression)607 explicit ReturnStatement(Expression* expression) 608 : expression_(expression) { } 609 DECLARE_NODE_TYPE(ReturnStatement)610 DECLARE_NODE_TYPE(ReturnStatement) 611 612 Expression* expression() const { return expression_; } 613 virtual bool IsInlineable() const; 614 615 private: 616 Expression* expression_; 617 }; 618 619 620 class WithEnterStatement: public Statement { 621 public: WithEnterStatement(Expression * expression,bool is_catch_block)622 explicit WithEnterStatement(Expression* expression, bool is_catch_block) 623 : expression_(expression), is_catch_block_(is_catch_block) { } 624 DECLARE_NODE_TYPE(WithEnterStatement)625 DECLARE_NODE_TYPE(WithEnterStatement) 626 627 Expression* expression() const { return expression_; } 628 is_catch_block()629 bool is_catch_block() const { return is_catch_block_; } 630 virtual bool IsInlineable() const; 631 632 private: 633 Expression* expression_; 634 bool is_catch_block_; 635 }; 636 637 638 class WithExitStatement: public Statement { 639 public: WithExitStatement()640 WithExitStatement() { } 641 642 virtual bool IsInlineable() const; 643 644 DECLARE_NODE_TYPE(WithExitStatement) 645 }; 646 647 648 class CaseClause: public ZoneObject { 649 public: 650 CaseClause(Expression* label, ZoneList<Statement*>* statements, int pos); 651 is_default()652 bool is_default() const { return label_ == NULL; } label()653 Expression* label() const { 654 CHECK(!is_default()); 655 return label_; 656 } body_target()657 Label* body_target() { return &body_target_; } statements()658 ZoneList<Statement*>* statements() const { return statements_; } 659 position()660 int position() const { return position_; } set_position(int pos)661 void set_position(int pos) { position_ = pos; } 662 EntryId()663 int EntryId() { return entry_id_; } 664 665 // Type feedback information. 666 void RecordTypeFeedback(TypeFeedbackOracle* oracle); IsSmiCompare()667 bool IsSmiCompare() { return compare_type_ == SMI_ONLY; } IsObjectCompare()668 bool IsObjectCompare() { return compare_type_ == OBJECT_ONLY; } 669 670 private: 671 Expression* label_; 672 Label body_target_; 673 ZoneList<Statement*>* statements_; 674 int position_; 675 enum CompareTypeFeedback { NONE, SMI_ONLY, OBJECT_ONLY }; 676 CompareTypeFeedback compare_type_; 677 int entry_id_; 678 }; 679 680 681 class SwitchStatement: public BreakableStatement { 682 public: 683 explicit inline SwitchStatement(ZoneStringList* labels); 684 DECLARE_NODE_TYPE(SwitchStatement)685 DECLARE_NODE_TYPE(SwitchStatement) 686 687 void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) { 688 tag_ = tag; 689 cases_ = cases; 690 } 691 tag()692 Expression* tag() const { return tag_; } cases()693 ZoneList<CaseClause*>* cases() const { return cases_; } 694 virtual bool IsInlineable() const; 695 696 private: 697 Expression* tag_; 698 ZoneList<CaseClause*>* cases_; 699 }; 700 701 702 // If-statements always have non-null references to their then- and 703 // else-parts. When parsing if-statements with no explicit else-part, 704 // the parser implicitly creates an empty statement. Use the 705 // HasThenStatement() and HasElseStatement() functions to check if a 706 // given if-statement has a then- or an else-part containing code. 707 class IfStatement: public Statement { 708 public: IfStatement(Expression * condition,Statement * then_statement,Statement * else_statement)709 IfStatement(Expression* condition, 710 Statement* then_statement, 711 Statement* else_statement) 712 : condition_(condition), 713 then_statement_(then_statement), 714 else_statement_(else_statement), 715 then_id_(GetNextId()), 716 else_id_(GetNextId()) { 717 } 718 719 DECLARE_NODE_TYPE(IfStatement) 720 721 virtual bool IsInlineable() const; 722 HasThenStatement()723 bool HasThenStatement() const { return !then_statement()->IsEmpty(); } HasElseStatement()724 bool HasElseStatement() const { return !else_statement()->IsEmpty(); } 725 condition()726 Expression* condition() const { return condition_; } then_statement()727 Statement* then_statement() const { return then_statement_; } else_statement()728 Statement* else_statement() const { return else_statement_; } 729 ThenId()730 int ThenId() const { return then_id_; } ElseId()731 int ElseId() const { return else_id_; } 732 733 private: 734 Expression* condition_; 735 Statement* then_statement_; 736 Statement* else_statement_; 737 int then_id_; 738 int else_id_; 739 }; 740 741 742 // NOTE: TargetCollectors are represented as nodes to fit in the target 743 // stack in the compiler; this should probably be reworked. 744 class TargetCollector: public AstNode { 745 public: TargetCollector(ZoneList<Label * > * targets)746 explicit TargetCollector(ZoneList<Label*>* targets) 747 : targets_(targets) { 748 } 749 750 // Adds a jump target to the collector. The collector stores a pointer not 751 // a copy of the target to make binding work, so make sure not to pass in 752 // references to something on the stack. 753 void AddTarget(Label* target); 754 755 // Virtual behaviour. TargetCollectors are never part of the AST. Accept(AstVisitor * v)756 virtual void Accept(AstVisitor* v) { UNREACHABLE(); } AsTargetCollector()757 virtual TargetCollector* AsTargetCollector() { return this; } 758 targets()759 ZoneList<Label*>* targets() { return targets_; } 760 virtual bool IsInlineable() const; 761 762 private: 763 ZoneList<Label*>* targets_; 764 }; 765 766 767 class TryStatement: public Statement { 768 public: TryStatement(Block * try_block)769 explicit TryStatement(Block* try_block) 770 : try_block_(try_block), escaping_targets_(NULL) { } 771 set_escaping_targets(ZoneList<Label * > * targets)772 void set_escaping_targets(ZoneList<Label*>* targets) { 773 escaping_targets_ = targets; 774 } 775 try_block()776 Block* try_block() const { return try_block_; } escaping_targets()777 ZoneList<Label*>* escaping_targets() const { return escaping_targets_; } 778 virtual bool IsInlineable() const; 779 780 private: 781 Block* try_block_; 782 ZoneList<Label*>* escaping_targets_; 783 }; 784 785 786 class TryCatchStatement: public TryStatement { 787 public: TryCatchStatement(Block * try_block,VariableProxy * catch_var,Block * catch_block)788 TryCatchStatement(Block* try_block, 789 VariableProxy* catch_var, 790 Block* catch_block) 791 : TryStatement(try_block), 792 catch_var_(catch_var), 793 catch_block_(catch_block) { 794 } 795 DECLARE_NODE_TYPE(TryCatchStatement)796 DECLARE_NODE_TYPE(TryCatchStatement) 797 798 VariableProxy* catch_var() const { return catch_var_; } catch_block()799 Block* catch_block() const { return catch_block_; } 800 virtual bool IsInlineable() const; 801 802 private: 803 VariableProxy* catch_var_; 804 Block* catch_block_; 805 }; 806 807 808 class TryFinallyStatement: public TryStatement { 809 public: TryFinallyStatement(Block * try_block,Block * finally_block)810 TryFinallyStatement(Block* try_block, Block* finally_block) 811 : TryStatement(try_block), 812 finally_block_(finally_block) { } 813 DECLARE_NODE_TYPE(TryFinallyStatement)814 DECLARE_NODE_TYPE(TryFinallyStatement) 815 816 Block* finally_block() const { return finally_block_; } 817 virtual bool IsInlineable() const; 818 819 private: 820 Block* finally_block_; 821 }; 822 823 824 class DebuggerStatement: public Statement { 825 public: 826 DECLARE_NODE_TYPE(DebuggerStatement) 827 virtual bool IsInlineable() const; 828 }; 829 830 831 class EmptyStatement: public Statement { 832 public: 833 DECLARE_NODE_TYPE(EmptyStatement) 834 835 virtual bool IsInlineable() const; 836 }; 837 838 839 class Literal: public Expression { 840 public: Literal(Handle<Object> handle)841 explicit Literal(Handle<Object> handle) : handle_(handle) { } 842 DECLARE_NODE_TYPE(Literal)843 DECLARE_NODE_TYPE(Literal) 844 845 virtual bool IsTrivial() { return true; } IsSmiLiteral()846 virtual bool IsSmiLiteral() { return handle_->IsSmi(); } 847 848 // Check if this literal is identical to the other literal. IsIdenticalTo(const Literal * other)849 bool IsIdenticalTo(const Literal* other) const { 850 return handle_.is_identical_to(other->handle_); 851 } 852 IsPropertyName()853 virtual bool IsPropertyName() { 854 if (handle_->IsSymbol()) { 855 uint32_t ignored; 856 return !String::cast(*handle_)->AsArrayIndex(&ignored); 857 } 858 return false; 859 } 860 AsPropertyName()861 Handle<String> AsPropertyName() { 862 ASSERT(IsPropertyName()); 863 return Handle<String>::cast(handle_); 864 } 865 ToBooleanIsTrue()866 virtual bool ToBooleanIsTrue() { return handle_->ToBoolean()->IsTrue(); } ToBooleanIsFalse()867 virtual bool ToBooleanIsFalse() { return handle_->ToBoolean()->IsFalse(); } 868 869 // Identity testers. IsNull()870 bool IsNull() const { 871 ASSERT(!handle_.is_null()); 872 return handle_->IsNull(); 873 } IsTrue()874 bool IsTrue() const { 875 ASSERT(!handle_.is_null()); 876 return handle_->IsTrue(); 877 } IsFalse()878 bool IsFalse() const { 879 ASSERT(!handle_.is_null()); 880 return handle_->IsFalse(); 881 } 882 handle()883 Handle<Object> handle() const { return handle_; } 884 virtual bool IsInlineable() const; 885 886 private: 887 Handle<Object> handle_; 888 }; 889 890 891 // Base class for literals that needs space in the corresponding JSFunction. 892 class MaterializedLiteral: public Expression { 893 public: MaterializedLiteral(int literal_index,bool is_simple,int depth)894 explicit MaterializedLiteral(int literal_index, bool is_simple, int depth) 895 : literal_index_(literal_index), is_simple_(is_simple), depth_(depth) {} 896 AsMaterializedLiteral()897 virtual MaterializedLiteral* AsMaterializedLiteral() { return this; } 898 literal_index()899 int literal_index() { return literal_index_; } 900 901 // A materialized literal is simple if the values consist of only 902 // constants and simple object and array literals. is_simple()903 bool is_simple() const { return is_simple_; } 904 depth()905 int depth() const { return depth_; } 906 virtual bool IsInlineable() const; 907 908 private: 909 int literal_index_; 910 bool is_simple_; 911 int depth_; 912 }; 913 914 915 // An object literal has a boilerplate object that is used 916 // for minimizing the work when constructing it at runtime. 917 class ObjectLiteral: public MaterializedLiteral { 918 public: 919 // Property is used for passing information 920 // about an object literal's properties from the parser 921 // to the code generator. 922 class Property: public ZoneObject { 923 public: 924 enum Kind { 925 CONSTANT, // Property with constant value (compile time). 926 COMPUTED, // Property with computed value (execution time). 927 MATERIALIZED_LITERAL, // Property value is a materialized literal. 928 GETTER, SETTER, // Property is an accessor function. 929 PROTOTYPE // Property is __proto__. 930 }; 931 932 Property(Literal* key, Expression* value); 933 Property(bool is_getter, FunctionLiteral* value); 934 key()935 Literal* key() { return key_; } value()936 Expression* value() { return value_; } kind()937 Kind kind() { return kind_; } 938 939 bool IsCompileTimeValue(); 940 941 void set_emit_store(bool emit_store); 942 bool emit_store(); 943 944 private: 945 Literal* key_; 946 Expression* value_; 947 Kind kind_; 948 bool emit_store_; 949 }; 950 ObjectLiteral(Handle<FixedArray> constant_properties,ZoneList<Property * > * properties,int literal_index,bool is_simple,bool fast_elements,int depth,bool has_function)951 ObjectLiteral(Handle<FixedArray> constant_properties, 952 ZoneList<Property*>* properties, 953 int literal_index, 954 bool is_simple, 955 bool fast_elements, 956 int depth, 957 bool has_function) 958 : MaterializedLiteral(literal_index, is_simple, depth), 959 constant_properties_(constant_properties), 960 properties_(properties), 961 fast_elements_(fast_elements), 962 has_function_(has_function) {} 963 DECLARE_NODE_TYPE(ObjectLiteral)964 DECLARE_NODE_TYPE(ObjectLiteral) 965 966 Handle<FixedArray> constant_properties() const { 967 return constant_properties_; 968 } properties()969 ZoneList<Property*>* properties() const { return properties_; } 970 fast_elements()971 bool fast_elements() const { return fast_elements_; } 972 has_function()973 bool has_function() { return has_function_; } 974 975 // Mark all computed expressions that are bound to a key that 976 // is shadowed by a later occurrence of the same key. For the 977 // marked expressions, no store code is emitted. 978 void CalculateEmitStore(); 979 980 enum Flags { 981 kNoFlags = 0, 982 kFastElements = 1, 983 kHasFunction = 1 << 1 984 }; 985 986 private: 987 Handle<FixedArray> constant_properties_; 988 ZoneList<Property*>* properties_; 989 bool fast_elements_; 990 bool has_function_; 991 }; 992 993 994 // Node for capturing a regexp literal. 995 class RegExpLiteral: public MaterializedLiteral { 996 public: RegExpLiteral(Handle<String> pattern,Handle<String> flags,int literal_index)997 RegExpLiteral(Handle<String> pattern, 998 Handle<String> flags, 999 int literal_index) 1000 : MaterializedLiteral(literal_index, false, 1), 1001 pattern_(pattern), 1002 flags_(flags) {} 1003 DECLARE_NODE_TYPE(RegExpLiteral)1004 DECLARE_NODE_TYPE(RegExpLiteral) 1005 1006 Handle<String> pattern() const { return pattern_; } flags()1007 Handle<String> flags() const { return flags_; } 1008 1009 private: 1010 Handle<String> pattern_; 1011 Handle<String> flags_; 1012 }; 1013 1014 // An array literal has a literals object that is used 1015 // for minimizing the work when constructing it at runtime. 1016 class ArrayLiteral: public MaterializedLiteral { 1017 public: ArrayLiteral(Handle<FixedArray> constant_elements,ZoneList<Expression * > * values,int literal_index,bool is_simple,int depth)1018 ArrayLiteral(Handle<FixedArray> constant_elements, 1019 ZoneList<Expression*>* values, 1020 int literal_index, 1021 bool is_simple, 1022 int depth) 1023 : MaterializedLiteral(literal_index, is_simple, depth), 1024 constant_elements_(constant_elements), 1025 values_(values), 1026 first_element_id_(ReserveIdRange(values->length())) {} 1027 DECLARE_NODE_TYPE(ArrayLiteral)1028 DECLARE_NODE_TYPE(ArrayLiteral) 1029 1030 Handle<FixedArray> constant_elements() const { return constant_elements_; } values()1031 ZoneList<Expression*>* values() const { return values_; } 1032 1033 // Return an AST id for an element that is used in simulate instructions. GetIdForElement(int i)1034 int GetIdForElement(int i) { return first_element_id_ + i; } 1035 1036 private: 1037 Handle<FixedArray> constant_elements_; 1038 ZoneList<Expression*>* values_; 1039 int first_element_id_; 1040 }; 1041 1042 1043 // Node for constructing a context extension object for a catch block. 1044 // The catch context extension object has one property, the catch 1045 // variable, which should be DontDelete. 1046 class CatchExtensionObject: public Expression { 1047 public: CatchExtensionObject(Literal * key,VariableProxy * value)1048 CatchExtensionObject(Literal* key, VariableProxy* value) 1049 : key_(key), value_(value) { 1050 } 1051 DECLARE_NODE_TYPE(CatchExtensionObject)1052 DECLARE_NODE_TYPE(CatchExtensionObject) 1053 1054 Literal* key() const { return key_; } value()1055 VariableProxy* value() const { return value_; } 1056 virtual bool IsInlineable() const; 1057 1058 private: 1059 Literal* key_; 1060 VariableProxy* value_; 1061 }; 1062 1063 1064 class VariableProxy: public Expression { 1065 public: 1066 explicit VariableProxy(Variable* var); 1067 DECLARE_NODE_TYPE(VariableProxy)1068 DECLARE_NODE_TYPE(VariableProxy) 1069 1070 // Type testing & conversion 1071 virtual Property* AsProperty() { 1072 return var_ == NULL ? NULL : var_->AsProperty(); 1073 } 1074 AsVariable()1075 Variable* AsVariable() { 1076 if (this == NULL || var_ == NULL) return NULL; 1077 Expression* rewrite = var_->rewrite(); 1078 if (rewrite == NULL || rewrite->AsSlot() != NULL) return var_; 1079 return NULL; 1080 } 1081 IsValidLeftHandSide()1082 virtual bool IsValidLeftHandSide() { 1083 return var_ == NULL ? true : var_->IsValidLeftHandSide(); 1084 } 1085 IsTrivial()1086 virtual bool IsTrivial() { 1087 // Reading from a mutable variable is a side effect, but the 1088 // variable for 'this' is immutable. 1089 return is_this_ || is_trivial_; 1090 } 1091 1092 virtual bool IsInlineable() const; 1093 IsVariable(Handle<String> n)1094 bool IsVariable(Handle<String> n) { 1095 return !is_this() && name().is_identical_to(n); 1096 } 1097 IsArguments()1098 bool IsArguments() { 1099 Variable* variable = AsVariable(); 1100 return (variable == NULL) ? false : variable->is_arguments(); 1101 } 1102 name()1103 Handle<String> name() const { return name_; } var()1104 Variable* var() const { return var_; } is_this()1105 bool is_this() const { return is_this_; } inside_with()1106 bool inside_with() const { return inside_with_; } position()1107 int position() const { return position_; } 1108 MarkAsTrivial()1109 void MarkAsTrivial() { is_trivial_ = true; } 1110 1111 // Bind this proxy to the variable var. 1112 void BindTo(Variable* var); 1113 1114 protected: 1115 Handle<String> name_; 1116 Variable* var_; // resolved variable, or NULL 1117 bool is_this_; 1118 bool inside_with_; 1119 bool is_trivial_; 1120 int position_; 1121 1122 VariableProxy(Handle<String> name, 1123 bool is_this, 1124 bool inside_with, 1125 int position = RelocInfo::kNoPosition); 1126 explicit VariableProxy(bool is_this); 1127 1128 friend class Scope; 1129 }; 1130 1131 1132 class VariableProxySentinel: public VariableProxy { 1133 public: IsValidLeftHandSide()1134 virtual bool IsValidLeftHandSide() { return !is_this(); } 1135 1136 private: VariableProxySentinel(bool is_this)1137 explicit VariableProxySentinel(bool is_this) : VariableProxy(is_this) { } 1138 1139 friend class AstSentinels; 1140 }; 1141 1142 1143 class Slot: public Expression { 1144 public: 1145 enum Type { 1146 // A slot in the parameter section on the stack. index() is 1147 // the parameter index, counting left-to-right, starting at 0. 1148 PARAMETER, 1149 1150 // A slot in the local section on the stack. index() is 1151 // the variable index in the stack frame, starting at 0. 1152 LOCAL, 1153 1154 // An indexed slot in a heap context. index() is the 1155 // variable index in the context object on the heap, 1156 // starting at 0. var()->scope() is the corresponding 1157 // scope. 1158 CONTEXT, 1159 1160 // A named slot in a heap context. var()->name() is the 1161 // variable name in the context object on the heap, 1162 // with lookup starting at the current context. index() 1163 // is invalid. 1164 LOOKUP 1165 }; 1166 Slot(Variable * var,Type type,int index)1167 Slot(Variable* var, Type type, int index) 1168 : var_(var), type_(type), index_(index) { 1169 ASSERT(var != NULL); 1170 } 1171 1172 virtual void Accept(AstVisitor* v); 1173 AsSlot()1174 virtual Slot* AsSlot() { return this; } 1175 IsStackAllocated()1176 bool IsStackAllocated() { return type_ == PARAMETER || type_ == LOCAL; } 1177 1178 // Accessors var()1179 Variable* var() const { return var_; } type()1180 Type type() const { return type_; } index()1181 int index() const { return index_; } is_arguments()1182 bool is_arguments() const { return var_->is_arguments(); } 1183 virtual bool IsInlineable() const; 1184 1185 private: 1186 Variable* var_; 1187 Type type_; 1188 int index_; 1189 }; 1190 1191 1192 class Property: public Expression { 1193 public: 1194 // Synthetic properties are property lookups introduced by the system, 1195 // to objects that aren't visible to the user. Function calls to synthetic 1196 // properties should use the global object as receiver, not the base object 1197 // of the resolved Reference. 1198 enum Type { NORMAL, SYNTHETIC }; 1199 Property(Expression* obj, Expression* key, int pos, Type type = NORMAL) obj_(obj)1200 : obj_(obj), 1201 key_(key), 1202 pos_(pos), 1203 type_(type), 1204 receiver_types_(NULL), 1205 is_monomorphic_(false), 1206 is_array_length_(false), 1207 is_string_length_(false), 1208 is_string_access_(false), 1209 is_function_prototype_(false), 1210 is_arguments_access_(false) { } 1211 DECLARE_NODE_TYPE(Property)1212 DECLARE_NODE_TYPE(Property) 1213 1214 virtual bool IsValidLeftHandSide() { return true; } 1215 virtual bool IsInlineable() const; 1216 obj()1217 Expression* obj() const { return obj_; } key()1218 Expression* key() const { return key_; } position()1219 virtual int position() const { return pos_; } is_synthetic()1220 bool is_synthetic() const { return type_ == SYNTHETIC; } 1221 IsStringLength()1222 bool IsStringLength() const { return is_string_length_; } IsStringAccess()1223 bool IsStringAccess() const { return is_string_access_; } IsFunctionPrototype()1224 bool IsFunctionPrototype() const { return is_function_prototype_; } 1225 1226 // Marks that this is actually an argument rewritten to a keyed property 1227 // accessing the argument through the arguments shadow object. set_is_arguments_access(bool is_arguments_access)1228 void set_is_arguments_access(bool is_arguments_access) { 1229 is_arguments_access_ = is_arguments_access; 1230 } is_arguments_access()1231 bool is_arguments_access() const { return is_arguments_access_; } 1232 1233 // Type feedback information. 1234 void RecordTypeFeedback(TypeFeedbackOracle* oracle); IsMonomorphic()1235 virtual bool IsMonomorphic() { return is_monomorphic_; } GetReceiverTypes()1236 virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; } IsArrayLength()1237 virtual bool IsArrayLength() { return is_array_length_; } GetMonomorphicReceiverType()1238 virtual Handle<Map> GetMonomorphicReceiverType() { 1239 return monomorphic_receiver_type_; 1240 } 1241 1242 private: 1243 Expression* obj_; 1244 Expression* key_; 1245 int pos_; 1246 Type type_; 1247 1248 ZoneMapList* receiver_types_; 1249 bool is_monomorphic_ : 1; 1250 bool is_array_length_ : 1; 1251 bool is_string_length_ : 1; 1252 bool is_string_access_ : 1; 1253 bool is_function_prototype_ : 1; 1254 bool is_arguments_access_ : 1; 1255 Handle<Map> monomorphic_receiver_type_; 1256 }; 1257 1258 1259 class Call: public Expression { 1260 public: Call(Expression * expression,ZoneList<Expression * > * arguments,int pos)1261 Call(Expression* expression, ZoneList<Expression*>* arguments, int pos) 1262 : expression_(expression), 1263 arguments_(arguments), 1264 pos_(pos), 1265 is_monomorphic_(false), 1266 check_type_(RECEIVER_MAP_CHECK), 1267 receiver_types_(NULL), 1268 return_id_(GetNextId()) { 1269 } 1270 1271 DECLARE_NODE_TYPE(Call) 1272 1273 virtual bool IsInlineable() const; 1274 expression()1275 Expression* expression() const { return expression_; } arguments()1276 ZoneList<Expression*>* arguments() const { return arguments_; } position()1277 virtual int position() const { return pos_; } 1278 1279 void RecordTypeFeedback(TypeFeedbackOracle* oracle); GetReceiverTypes()1280 virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; } IsMonomorphic()1281 virtual bool IsMonomorphic() { return is_monomorphic_; } check_type()1282 CheckType check_type() const { return check_type_; } target()1283 Handle<JSFunction> target() { return target_; } holder()1284 Handle<JSObject> holder() { return holder_; } cell()1285 Handle<JSGlobalPropertyCell> cell() { return cell_; } 1286 1287 bool ComputeTarget(Handle<Map> type, Handle<String> name); 1288 bool ComputeGlobalTarget(Handle<GlobalObject> global, LookupResult* lookup); 1289 1290 // Bailout support. ReturnId()1291 int ReturnId() const { return return_id_; } 1292 1293 #ifdef DEBUG 1294 // Used to assert that the FullCodeGenerator records the return site. 1295 bool return_is_recorded_; 1296 #endif 1297 1298 private: 1299 Expression* expression_; 1300 ZoneList<Expression*>* arguments_; 1301 int pos_; 1302 1303 bool is_monomorphic_; 1304 CheckType check_type_; 1305 ZoneMapList* receiver_types_; 1306 Handle<JSFunction> target_; 1307 Handle<JSObject> holder_; 1308 Handle<JSGlobalPropertyCell> cell_; 1309 1310 int return_id_; 1311 }; 1312 1313 1314 class AstSentinels { 1315 public: ~AstSentinels()1316 ~AstSentinels() { } 1317 1318 // Returns a property singleton property access on 'this'. Used 1319 // during preparsing. this_property()1320 Property* this_property() { return &this_property_; } this_proxy()1321 VariableProxySentinel* this_proxy() { return &this_proxy_; } identifier_proxy()1322 VariableProxySentinel* identifier_proxy() { return &identifier_proxy_; } valid_left_hand_side_sentinel()1323 ValidLeftHandSideSentinel* valid_left_hand_side_sentinel() { 1324 return &valid_left_hand_side_sentinel_; 1325 } call_sentinel()1326 Call* call_sentinel() { return &call_sentinel_; } empty_statement()1327 EmptyStatement* empty_statement() { return &empty_statement_; } 1328 1329 private: 1330 AstSentinels(); 1331 VariableProxySentinel this_proxy_; 1332 VariableProxySentinel identifier_proxy_; 1333 ValidLeftHandSideSentinel valid_left_hand_side_sentinel_; 1334 Property this_property_; 1335 Call call_sentinel_; 1336 EmptyStatement empty_statement_; 1337 1338 friend class Isolate; 1339 1340 DISALLOW_COPY_AND_ASSIGN(AstSentinels); 1341 }; 1342 1343 1344 class CallNew: public Expression { 1345 public: CallNew(Expression * expression,ZoneList<Expression * > * arguments,int pos)1346 CallNew(Expression* expression, ZoneList<Expression*>* arguments, int pos) 1347 : expression_(expression), arguments_(arguments), pos_(pos) { } 1348 1349 DECLARE_NODE_TYPE(CallNew) 1350 1351 virtual bool IsInlineable() const; 1352 expression()1353 Expression* expression() const { return expression_; } arguments()1354 ZoneList<Expression*>* arguments() const { return arguments_; } position()1355 virtual int position() const { return pos_; } 1356 1357 private: 1358 Expression* expression_; 1359 ZoneList<Expression*>* arguments_; 1360 int pos_; 1361 }; 1362 1363 1364 // The CallRuntime class does not represent any official JavaScript 1365 // language construct. Instead it is used to call a C or JS function 1366 // with a set of arguments. This is used from the builtins that are 1367 // implemented in JavaScript (see "v8natives.js"). 1368 class CallRuntime: public Expression { 1369 public: CallRuntime(Handle<String> name,const Runtime::Function * function,ZoneList<Expression * > * arguments)1370 CallRuntime(Handle<String> name, 1371 const Runtime::Function* function, 1372 ZoneList<Expression*>* arguments) 1373 : name_(name), function_(function), arguments_(arguments) { } 1374 1375 DECLARE_NODE_TYPE(CallRuntime) 1376 1377 virtual bool IsInlineable() const; 1378 name()1379 Handle<String> name() const { return name_; } function()1380 const Runtime::Function* function() const { return function_; } arguments()1381 ZoneList<Expression*>* arguments() const { return arguments_; } is_jsruntime()1382 bool is_jsruntime() const { return function_ == NULL; } 1383 1384 private: 1385 Handle<String> name_; 1386 const Runtime::Function* function_; 1387 ZoneList<Expression*>* arguments_; 1388 }; 1389 1390 1391 class UnaryOperation: public Expression { 1392 public: UnaryOperation(Token::Value op,Expression * expression)1393 UnaryOperation(Token::Value op, Expression* expression) 1394 : op_(op), expression_(expression) { 1395 ASSERT(Token::IsUnaryOp(op)); 1396 } 1397 1398 DECLARE_NODE_TYPE(UnaryOperation) 1399 1400 virtual bool IsInlineable() const; 1401 1402 virtual bool ResultOverwriteAllowed(); 1403 op()1404 Token::Value op() const { return op_; } expression()1405 Expression* expression() const { return expression_; } 1406 1407 private: 1408 Token::Value op_; 1409 Expression* expression_; 1410 }; 1411 1412 1413 class BinaryOperation: public Expression { 1414 public: BinaryOperation(Token::Value op,Expression * left,Expression * right,int pos)1415 BinaryOperation(Token::Value op, 1416 Expression* left, 1417 Expression* right, 1418 int pos) 1419 : op_(op), left_(left), right_(right), pos_(pos) { 1420 ASSERT(Token::IsBinaryOp(op)); 1421 right_id_ = (op == Token::AND || op == Token::OR) 1422 ? static_cast<int>(GetNextId()) 1423 : AstNode::kNoNumber; 1424 } 1425 1426 // Create the binary operation corresponding to a compound assignment. 1427 explicit BinaryOperation(Assignment* assignment); 1428 1429 DECLARE_NODE_TYPE(BinaryOperation) 1430 1431 virtual bool IsInlineable() const; 1432 1433 virtual bool ResultOverwriteAllowed(); 1434 op()1435 Token::Value op() const { return op_; } left()1436 Expression* left() const { return left_; } right()1437 Expression* right() const { return right_; } position()1438 virtual int position() const { return pos_; } 1439 1440 // Bailout support. RightId()1441 int RightId() const { return right_id_; } 1442 1443 private: 1444 Token::Value op_; 1445 Expression* left_; 1446 Expression* right_; 1447 int pos_; 1448 // The short-circuit logical operations have an AST ID for their 1449 // right-hand subexpression. 1450 int right_id_; 1451 }; 1452 1453 1454 class CountOperation: public Expression { 1455 public: CountOperation(Token::Value op,bool is_prefix,Expression * expr,int pos)1456 CountOperation(Token::Value op, bool is_prefix, Expression* expr, int pos) 1457 : op_(op), 1458 is_prefix_(is_prefix), 1459 expression_(expr), 1460 pos_(pos), 1461 assignment_id_(GetNextId()), 1462 count_id_(GetNextId()) { } 1463 DECLARE_NODE_TYPE(CountOperation)1464 DECLARE_NODE_TYPE(CountOperation) 1465 1466 bool is_prefix() const { return is_prefix_; } is_postfix()1467 bool is_postfix() const { return !is_prefix_; } 1468 op()1469 Token::Value op() const { return op_; } binary_op()1470 Token::Value binary_op() { 1471 return (op() == Token::INC) ? Token::ADD : Token::SUB; 1472 } 1473 expression()1474 Expression* expression() const { return expression_; } position()1475 virtual int position() const { return pos_; } 1476 MarkAsStatement()1477 virtual void MarkAsStatement() { is_prefix_ = true; } 1478 1479 virtual bool IsInlineable() const; 1480 1481 void RecordTypeFeedback(TypeFeedbackOracle* oracle); IsMonomorphic()1482 virtual bool IsMonomorphic() { return is_monomorphic_; } GetMonomorphicReceiverType()1483 virtual Handle<Map> GetMonomorphicReceiverType() { 1484 return monomorphic_receiver_type_; 1485 } 1486 1487 // Bailout support. AssignmentId()1488 int AssignmentId() const { return assignment_id_; } CountId()1489 int CountId() const { return count_id_; } 1490 1491 private: 1492 Token::Value op_; 1493 bool is_prefix_; 1494 bool is_monomorphic_; 1495 Expression* expression_; 1496 int pos_; 1497 int assignment_id_; 1498 int count_id_; 1499 Handle<Map> monomorphic_receiver_type_; 1500 }; 1501 1502 1503 class CompareOperation: public Expression { 1504 public: CompareOperation(Token::Value op,Expression * left,Expression * right,int pos)1505 CompareOperation(Token::Value op, 1506 Expression* left, 1507 Expression* right, 1508 int pos) 1509 : op_(op), left_(left), right_(right), pos_(pos), compare_type_(NONE) { 1510 ASSERT(Token::IsCompareOp(op)); 1511 } 1512 DECLARE_NODE_TYPE(CompareOperation)1513 DECLARE_NODE_TYPE(CompareOperation) 1514 1515 Token::Value op() const { return op_; } left()1516 Expression* left() const { return left_; } right()1517 Expression* right() const { return right_; } position()1518 virtual int position() const { return pos_; } 1519 1520 virtual bool IsInlineable() const; 1521 1522 // Type feedback information. 1523 void RecordTypeFeedback(TypeFeedbackOracle* oracle); IsSmiCompare()1524 bool IsSmiCompare() { return compare_type_ == SMI_ONLY; } IsObjectCompare()1525 bool IsObjectCompare() { return compare_type_ == OBJECT_ONLY; } 1526 1527 private: 1528 Token::Value op_; 1529 Expression* left_; 1530 Expression* right_; 1531 int pos_; 1532 1533 enum CompareTypeFeedback { NONE, SMI_ONLY, OBJECT_ONLY }; 1534 CompareTypeFeedback compare_type_; 1535 }; 1536 1537 1538 class CompareToNull: public Expression { 1539 public: CompareToNull(bool is_strict,Expression * expression)1540 CompareToNull(bool is_strict, Expression* expression) 1541 : is_strict_(is_strict), expression_(expression) { } 1542 1543 DECLARE_NODE_TYPE(CompareToNull) 1544 1545 virtual bool IsInlineable() const; 1546 is_strict()1547 bool is_strict() const { return is_strict_; } op()1548 Token::Value op() const { return is_strict_ ? Token::EQ_STRICT : Token::EQ; } expression()1549 Expression* expression() const { return expression_; } 1550 1551 private: 1552 bool is_strict_; 1553 Expression* expression_; 1554 }; 1555 1556 1557 class Conditional: public Expression { 1558 public: Conditional(Expression * condition,Expression * then_expression,Expression * else_expression,int then_expression_position,int else_expression_position)1559 Conditional(Expression* condition, 1560 Expression* then_expression, 1561 Expression* else_expression, 1562 int then_expression_position, 1563 int else_expression_position) 1564 : condition_(condition), 1565 then_expression_(then_expression), 1566 else_expression_(else_expression), 1567 then_expression_position_(then_expression_position), 1568 else_expression_position_(else_expression_position), 1569 then_id_(GetNextId()), 1570 else_id_(GetNextId()) { 1571 } 1572 1573 DECLARE_NODE_TYPE(Conditional) 1574 1575 virtual bool IsInlineable() const; 1576 condition()1577 Expression* condition() const { return condition_; } then_expression()1578 Expression* then_expression() const { return then_expression_; } else_expression()1579 Expression* else_expression() const { return else_expression_; } 1580 then_expression_position()1581 int then_expression_position() const { return then_expression_position_; } else_expression_position()1582 int else_expression_position() const { return else_expression_position_; } 1583 ThenId()1584 int ThenId() const { return then_id_; } ElseId()1585 int ElseId() const { return else_id_; } 1586 1587 private: 1588 Expression* condition_; 1589 Expression* then_expression_; 1590 Expression* else_expression_; 1591 int then_expression_position_; 1592 int else_expression_position_; 1593 int then_id_; 1594 int else_id_; 1595 }; 1596 1597 1598 class Assignment: public Expression { 1599 public: 1600 Assignment(Token::Value op, Expression* target, Expression* value, int pos); 1601 1602 DECLARE_NODE_TYPE(Assignment) 1603 1604 virtual bool IsInlineable() const; 1605 AsSimpleAssignment()1606 Assignment* AsSimpleAssignment() { return !is_compound() ? this : NULL; } 1607 1608 Token::Value binary_op() const; 1609 op()1610 Token::Value op() const { return op_; } target()1611 Expression* target() const { return target_; } value()1612 Expression* value() const { return value_; } position()1613 virtual int position() const { return pos_; } binary_operation()1614 BinaryOperation* binary_operation() const { return binary_operation_; } 1615 1616 // This check relies on the definition order of token in token.h. is_compound()1617 bool is_compound() const { return op() > Token::ASSIGN; } 1618 1619 // An initialization block is a series of statments of the form 1620 // x.y.z.a = ...; x.y.z.b = ...; etc. The parser marks the beginning and 1621 // ending of these blocks to allow for optimizations of initialization 1622 // blocks. starts_initialization_block()1623 bool starts_initialization_block() { return block_start_; } ends_initialization_block()1624 bool ends_initialization_block() { return block_end_; } mark_block_start()1625 void mark_block_start() { block_start_ = true; } mark_block_end()1626 void mark_block_end() { block_end_ = true; } 1627 1628 // Type feedback information. 1629 void RecordTypeFeedback(TypeFeedbackOracle* oracle); IsMonomorphic()1630 virtual bool IsMonomorphic() { return is_monomorphic_; } GetReceiverTypes()1631 virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; } GetMonomorphicReceiverType()1632 virtual Handle<Map> GetMonomorphicReceiverType() { 1633 return monomorphic_receiver_type_; 1634 } 1635 1636 // Bailout support. CompoundLoadId()1637 int CompoundLoadId() const { return compound_load_id_; } AssignmentId()1638 int AssignmentId() const { return assignment_id_; } 1639 1640 private: 1641 Token::Value op_; 1642 Expression* target_; 1643 Expression* value_; 1644 int pos_; 1645 BinaryOperation* binary_operation_; 1646 int compound_load_id_; 1647 int assignment_id_; 1648 1649 bool block_start_; 1650 bool block_end_; 1651 1652 bool is_monomorphic_; 1653 ZoneMapList* receiver_types_; 1654 Handle<Map> monomorphic_receiver_type_; 1655 }; 1656 1657 1658 class Throw: public Expression { 1659 public: Throw(Expression * exception,int pos)1660 Throw(Expression* exception, int pos) 1661 : exception_(exception), pos_(pos) {} 1662 DECLARE_NODE_TYPE(Throw)1663 DECLARE_NODE_TYPE(Throw) 1664 1665 Expression* exception() const { return exception_; } position()1666 virtual int position() const { return pos_; } 1667 virtual bool IsInlineable() const; 1668 1669 private: 1670 Expression* exception_; 1671 int pos_; 1672 }; 1673 1674 1675 class FunctionLiteral: public Expression { 1676 public: FunctionLiteral(Handle<String> name,Scope * scope,ZoneList<Statement * > * body,int materialized_literal_count,int expected_property_count,bool has_only_simple_this_property_assignments,Handle<FixedArray> this_property_assignments,int num_parameters,int start_position,int end_position,bool is_expression)1677 FunctionLiteral(Handle<String> name, 1678 Scope* scope, 1679 ZoneList<Statement*>* body, 1680 int materialized_literal_count, 1681 int expected_property_count, 1682 bool has_only_simple_this_property_assignments, 1683 Handle<FixedArray> this_property_assignments, 1684 int num_parameters, 1685 int start_position, 1686 int end_position, 1687 bool is_expression) 1688 : name_(name), 1689 scope_(scope), 1690 body_(body), 1691 materialized_literal_count_(materialized_literal_count), 1692 expected_property_count_(expected_property_count), 1693 has_only_simple_this_property_assignments_( 1694 has_only_simple_this_property_assignments), 1695 this_property_assignments_(this_property_assignments), 1696 num_parameters_(num_parameters), 1697 start_position_(start_position), 1698 end_position_(end_position), 1699 is_expression_(is_expression), 1700 function_token_position_(RelocInfo::kNoPosition), 1701 inferred_name_(HEAP->empty_string()), 1702 pretenure_(false) { } 1703 DECLARE_NODE_TYPE(FunctionLiteral)1704 DECLARE_NODE_TYPE(FunctionLiteral) 1705 1706 Handle<String> name() const { return name_; } scope()1707 Scope* scope() const { return scope_; } body()1708 ZoneList<Statement*>* body() const { return body_; } set_function_token_position(int pos)1709 void set_function_token_position(int pos) { function_token_position_ = pos; } function_token_position()1710 int function_token_position() const { return function_token_position_; } start_position()1711 int start_position() const { return start_position_; } end_position()1712 int end_position() const { return end_position_; } is_expression()1713 bool is_expression() const { return is_expression_; } 1714 bool strict_mode() const; 1715 materialized_literal_count()1716 int materialized_literal_count() { return materialized_literal_count_; } expected_property_count()1717 int expected_property_count() { return expected_property_count_; } has_only_simple_this_property_assignments()1718 bool has_only_simple_this_property_assignments() { 1719 return has_only_simple_this_property_assignments_; 1720 } this_property_assignments()1721 Handle<FixedArray> this_property_assignments() { 1722 return this_property_assignments_; 1723 } num_parameters()1724 int num_parameters() { return num_parameters_; } 1725 1726 bool AllowsLazyCompilation(); 1727 debug_name()1728 Handle<String> debug_name() const { 1729 if (name_->length() > 0) return name_; 1730 return inferred_name(); 1731 } 1732 inferred_name()1733 Handle<String> inferred_name() const { return inferred_name_; } set_inferred_name(Handle<String> inferred_name)1734 void set_inferred_name(Handle<String> inferred_name) { 1735 inferred_name_ = inferred_name; 1736 } 1737 pretenure()1738 bool pretenure() { return pretenure_; } set_pretenure(bool value)1739 void set_pretenure(bool value) { pretenure_ = value; } 1740 virtual bool IsInlineable() const; 1741 1742 private: 1743 Handle<String> name_; 1744 Scope* scope_; 1745 ZoneList<Statement*>* body_; 1746 int materialized_literal_count_; 1747 int expected_property_count_; 1748 bool has_only_simple_this_property_assignments_; 1749 Handle<FixedArray> this_property_assignments_; 1750 int num_parameters_; 1751 int start_position_; 1752 int end_position_; 1753 bool is_expression_; 1754 int function_token_position_; 1755 Handle<String> inferred_name_; 1756 bool pretenure_; 1757 }; 1758 1759 1760 class SharedFunctionInfoLiteral: public Expression { 1761 public: SharedFunctionInfoLiteral(Handle<SharedFunctionInfo> shared_function_info)1762 explicit SharedFunctionInfoLiteral( 1763 Handle<SharedFunctionInfo> shared_function_info) 1764 : shared_function_info_(shared_function_info) { } 1765 DECLARE_NODE_TYPE(SharedFunctionInfoLiteral)1766 DECLARE_NODE_TYPE(SharedFunctionInfoLiteral) 1767 1768 Handle<SharedFunctionInfo> shared_function_info() const { 1769 return shared_function_info_; 1770 } 1771 virtual bool IsInlineable() const; 1772 1773 private: 1774 Handle<SharedFunctionInfo> shared_function_info_; 1775 }; 1776 1777 1778 class ThisFunction: public Expression { 1779 public: 1780 DECLARE_NODE_TYPE(ThisFunction) 1781 virtual bool IsInlineable() const; 1782 }; 1783 1784 1785 // ---------------------------------------------------------------------------- 1786 // Regular expressions 1787 1788 1789 class RegExpVisitor BASE_EMBEDDED { 1790 public: ~RegExpVisitor()1791 virtual ~RegExpVisitor() { } 1792 #define MAKE_CASE(Name) \ 1793 virtual void* Visit##Name(RegExp##Name*, void* data) = 0; 1794 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE) 1795 #undef MAKE_CASE 1796 }; 1797 1798 1799 class RegExpTree: public ZoneObject { 1800 public: 1801 static const int kInfinity = kMaxInt; ~RegExpTree()1802 virtual ~RegExpTree() { } 1803 virtual void* Accept(RegExpVisitor* visitor, void* data) = 0; 1804 virtual RegExpNode* ToNode(RegExpCompiler* compiler, 1805 RegExpNode* on_success) = 0; IsTextElement()1806 virtual bool IsTextElement() { return false; } IsAnchoredAtStart()1807 virtual bool IsAnchoredAtStart() { return false; } IsAnchoredAtEnd()1808 virtual bool IsAnchoredAtEnd() { return false; } 1809 virtual int min_match() = 0; 1810 virtual int max_match() = 0; 1811 // Returns the interval of registers used for captures within this 1812 // expression. CaptureRegisters()1813 virtual Interval CaptureRegisters() { return Interval::Empty(); } 1814 virtual void AppendToText(RegExpText* text); 1815 SmartPointer<const char> ToString(); 1816 #define MAKE_ASTYPE(Name) \ 1817 virtual RegExp##Name* As##Name(); \ 1818 virtual bool Is##Name(); 1819 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ASTYPE) 1820 #undef MAKE_ASTYPE 1821 }; 1822 1823 1824 class RegExpDisjunction: public RegExpTree { 1825 public: 1826 explicit RegExpDisjunction(ZoneList<RegExpTree*>* alternatives); 1827 virtual void* Accept(RegExpVisitor* visitor, void* data); 1828 virtual RegExpNode* ToNode(RegExpCompiler* compiler, 1829 RegExpNode* on_success); 1830 virtual RegExpDisjunction* AsDisjunction(); 1831 virtual Interval CaptureRegisters(); 1832 virtual bool IsDisjunction(); 1833 virtual bool IsAnchoredAtStart(); 1834 virtual bool IsAnchoredAtEnd(); min_match()1835 virtual int min_match() { return min_match_; } max_match()1836 virtual int max_match() { return max_match_; } alternatives()1837 ZoneList<RegExpTree*>* alternatives() { return alternatives_; } 1838 private: 1839 ZoneList<RegExpTree*>* alternatives_; 1840 int min_match_; 1841 int max_match_; 1842 }; 1843 1844 1845 class RegExpAlternative: public RegExpTree { 1846 public: 1847 explicit RegExpAlternative(ZoneList<RegExpTree*>* nodes); 1848 virtual void* Accept(RegExpVisitor* visitor, void* data); 1849 virtual RegExpNode* ToNode(RegExpCompiler* compiler, 1850 RegExpNode* on_success); 1851 virtual RegExpAlternative* AsAlternative(); 1852 virtual Interval CaptureRegisters(); 1853 virtual bool IsAlternative(); 1854 virtual bool IsAnchoredAtStart(); 1855 virtual bool IsAnchoredAtEnd(); min_match()1856 virtual int min_match() { return min_match_; } max_match()1857 virtual int max_match() { return max_match_; } nodes()1858 ZoneList<RegExpTree*>* nodes() { return nodes_; } 1859 private: 1860 ZoneList<RegExpTree*>* nodes_; 1861 int min_match_; 1862 int max_match_; 1863 }; 1864 1865 1866 class RegExpAssertion: public RegExpTree { 1867 public: 1868 enum Type { 1869 START_OF_LINE, 1870 START_OF_INPUT, 1871 END_OF_LINE, 1872 END_OF_INPUT, 1873 BOUNDARY, 1874 NON_BOUNDARY 1875 }; RegExpAssertion(Type type)1876 explicit RegExpAssertion(Type type) : type_(type) { } 1877 virtual void* Accept(RegExpVisitor* visitor, void* data); 1878 virtual RegExpNode* ToNode(RegExpCompiler* compiler, 1879 RegExpNode* on_success); 1880 virtual RegExpAssertion* AsAssertion(); 1881 virtual bool IsAssertion(); 1882 virtual bool IsAnchoredAtStart(); 1883 virtual bool IsAnchoredAtEnd(); min_match()1884 virtual int min_match() { return 0; } max_match()1885 virtual int max_match() { return 0; } type()1886 Type type() { return type_; } 1887 private: 1888 Type type_; 1889 }; 1890 1891 1892 class CharacterSet BASE_EMBEDDED { 1893 public: CharacterSet(uc16 standard_set_type)1894 explicit CharacterSet(uc16 standard_set_type) 1895 : ranges_(NULL), 1896 standard_set_type_(standard_set_type) {} CharacterSet(ZoneList<CharacterRange> * ranges)1897 explicit CharacterSet(ZoneList<CharacterRange>* ranges) 1898 : ranges_(ranges), 1899 standard_set_type_(0) {} 1900 ZoneList<CharacterRange>* ranges(); standard_set_type()1901 uc16 standard_set_type() { return standard_set_type_; } set_standard_set_type(uc16 special_set_type)1902 void set_standard_set_type(uc16 special_set_type) { 1903 standard_set_type_ = special_set_type; 1904 } is_standard()1905 bool is_standard() { return standard_set_type_ != 0; } 1906 void Canonicalize(); 1907 private: 1908 ZoneList<CharacterRange>* ranges_; 1909 // If non-zero, the value represents a standard set (e.g., all whitespace 1910 // characters) without having to expand the ranges. 1911 uc16 standard_set_type_; 1912 }; 1913 1914 1915 class RegExpCharacterClass: public RegExpTree { 1916 public: RegExpCharacterClass(ZoneList<CharacterRange> * ranges,bool is_negated)1917 RegExpCharacterClass(ZoneList<CharacterRange>* ranges, bool is_negated) 1918 : set_(ranges), 1919 is_negated_(is_negated) { } RegExpCharacterClass(uc16 type)1920 explicit RegExpCharacterClass(uc16 type) 1921 : set_(type), 1922 is_negated_(false) { } 1923 virtual void* Accept(RegExpVisitor* visitor, void* data); 1924 virtual RegExpNode* ToNode(RegExpCompiler* compiler, 1925 RegExpNode* on_success); 1926 virtual RegExpCharacterClass* AsCharacterClass(); 1927 virtual bool IsCharacterClass(); IsTextElement()1928 virtual bool IsTextElement() { return true; } min_match()1929 virtual int min_match() { return 1; } max_match()1930 virtual int max_match() { return 1; } 1931 virtual void AppendToText(RegExpText* text); character_set()1932 CharacterSet character_set() { return set_; } 1933 // TODO(lrn): Remove need for complex version if is_standard that 1934 // recognizes a mangled standard set and just do { return set_.is_special(); } 1935 bool is_standard(); 1936 // Returns a value representing the standard character set if is_standard() 1937 // returns true. 1938 // Currently used values are: 1939 // s : unicode whitespace 1940 // S : unicode non-whitespace 1941 // w : ASCII word character (digit, letter, underscore) 1942 // W : non-ASCII word character 1943 // d : ASCII digit 1944 // D : non-ASCII digit 1945 // . : non-unicode non-newline 1946 // * : All characters standard_type()1947 uc16 standard_type() { return set_.standard_set_type(); } ranges()1948 ZoneList<CharacterRange>* ranges() { return set_.ranges(); } is_negated()1949 bool is_negated() { return is_negated_; } 1950 private: 1951 CharacterSet set_; 1952 bool is_negated_; 1953 }; 1954 1955 1956 class RegExpAtom: public RegExpTree { 1957 public: RegExpAtom(Vector<const uc16> data)1958 explicit RegExpAtom(Vector<const uc16> data) : data_(data) { } 1959 virtual void* Accept(RegExpVisitor* visitor, void* data); 1960 virtual RegExpNode* ToNode(RegExpCompiler* compiler, 1961 RegExpNode* on_success); 1962 virtual RegExpAtom* AsAtom(); 1963 virtual bool IsAtom(); IsTextElement()1964 virtual bool IsTextElement() { return true; } min_match()1965 virtual int min_match() { return data_.length(); } max_match()1966 virtual int max_match() { return data_.length(); } 1967 virtual void AppendToText(RegExpText* text); data()1968 Vector<const uc16> data() { return data_; } length()1969 int length() { return data_.length(); } 1970 private: 1971 Vector<const uc16> data_; 1972 }; 1973 1974 1975 class RegExpText: public RegExpTree { 1976 public: RegExpText()1977 RegExpText() : elements_(2), length_(0) {} 1978 virtual void* Accept(RegExpVisitor* visitor, void* data); 1979 virtual RegExpNode* ToNode(RegExpCompiler* compiler, 1980 RegExpNode* on_success); 1981 virtual RegExpText* AsText(); 1982 virtual bool IsText(); IsTextElement()1983 virtual bool IsTextElement() { return true; } min_match()1984 virtual int min_match() { return length_; } max_match()1985 virtual int max_match() { return length_; } 1986 virtual void AppendToText(RegExpText* text); AddElement(TextElement elm)1987 void AddElement(TextElement elm) { 1988 elements_.Add(elm); 1989 length_ += elm.length(); 1990 } elements()1991 ZoneList<TextElement>* elements() { return &elements_; } 1992 private: 1993 ZoneList<TextElement> elements_; 1994 int length_; 1995 }; 1996 1997 1998 class RegExpQuantifier: public RegExpTree { 1999 public: 2000 enum Type { GREEDY, NON_GREEDY, POSSESSIVE }; RegExpQuantifier(int min,int max,Type type,RegExpTree * body)2001 RegExpQuantifier(int min, int max, Type type, RegExpTree* body) 2002 : body_(body), 2003 min_(min), 2004 max_(max), 2005 min_match_(min * body->min_match()), 2006 type_(type) { 2007 if (max > 0 && body->max_match() > kInfinity / max) { 2008 max_match_ = kInfinity; 2009 } else { 2010 max_match_ = max * body->max_match(); 2011 } 2012 } 2013 virtual void* Accept(RegExpVisitor* visitor, void* data); 2014 virtual RegExpNode* ToNode(RegExpCompiler* compiler, 2015 RegExpNode* on_success); 2016 static RegExpNode* ToNode(int min, 2017 int max, 2018 bool is_greedy, 2019 RegExpTree* body, 2020 RegExpCompiler* compiler, 2021 RegExpNode* on_success, 2022 bool not_at_start = false); 2023 virtual RegExpQuantifier* AsQuantifier(); 2024 virtual Interval CaptureRegisters(); 2025 virtual bool IsQuantifier(); min_match()2026 virtual int min_match() { return min_match_; } max_match()2027 virtual int max_match() { return max_match_; } min()2028 int min() { return min_; } max()2029 int max() { return max_; } is_possessive()2030 bool is_possessive() { return type_ == POSSESSIVE; } is_non_greedy()2031 bool is_non_greedy() { return type_ == NON_GREEDY; } is_greedy()2032 bool is_greedy() { return type_ == GREEDY; } body()2033 RegExpTree* body() { return body_; } 2034 private: 2035 RegExpTree* body_; 2036 int min_; 2037 int max_; 2038 int min_match_; 2039 int max_match_; 2040 Type type_; 2041 }; 2042 2043 2044 class RegExpCapture: public RegExpTree { 2045 public: RegExpCapture(RegExpTree * body,int index)2046 explicit RegExpCapture(RegExpTree* body, int index) 2047 : body_(body), index_(index) { } 2048 virtual void* Accept(RegExpVisitor* visitor, void* data); 2049 virtual RegExpNode* ToNode(RegExpCompiler* compiler, 2050 RegExpNode* on_success); 2051 static RegExpNode* ToNode(RegExpTree* body, 2052 int index, 2053 RegExpCompiler* compiler, 2054 RegExpNode* on_success); 2055 virtual RegExpCapture* AsCapture(); 2056 virtual bool IsAnchoredAtStart(); 2057 virtual bool IsAnchoredAtEnd(); 2058 virtual Interval CaptureRegisters(); 2059 virtual bool IsCapture(); min_match()2060 virtual int min_match() { return body_->min_match(); } max_match()2061 virtual int max_match() { return body_->max_match(); } body()2062 RegExpTree* body() { return body_; } index()2063 int index() { return index_; } StartRegister(int index)2064 static int StartRegister(int index) { return index * 2; } EndRegister(int index)2065 static int EndRegister(int index) { return index * 2 + 1; } 2066 private: 2067 RegExpTree* body_; 2068 int index_; 2069 }; 2070 2071 2072 class RegExpLookahead: public RegExpTree { 2073 public: RegExpLookahead(RegExpTree * body,bool is_positive,int capture_count,int capture_from)2074 RegExpLookahead(RegExpTree* body, 2075 bool is_positive, 2076 int capture_count, 2077 int capture_from) 2078 : body_(body), 2079 is_positive_(is_positive), 2080 capture_count_(capture_count), 2081 capture_from_(capture_from) { } 2082 2083 virtual void* Accept(RegExpVisitor* visitor, void* data); 2084 virtual RegExpNode* ToNode(RegExpCompiler* compiler, 2085 RegExpNode* on_success); 2086 virtual RegExpLookahead* AsLookahead(); 2087 virtual Interval CaptureRegisters(); 2088 virtual bool IsLookahead(); 2089 virtual bool IsAnchoredAtStart(); min_match()2090 virtual int min_match() { return 0; } max_match()2091 virtual int max_match() { return 0; } body()2092 RegExpTree* body() { return body_; } is_positive()2093 bool is_positive() { return is_positive_; } capture_count()2094 int capture_count() { return capture_count_; } capture_from()2095 int capture_from() { return capture_from_; } 2096 private: 2097 RegExpTree* body_; 2098 bool is_positive_; 2099 int capture_count_; 2100 int capture_from_; 2101 }; 2102 2103 2104 class RegExpBackReference: public RegExpTree { 2105 public: RegExpBackReference(RegExpCapture * capture)2106 explicit RegExpBackReference(RegExpCapture* capture) 2107 : capture_(capture) { } 2108 virtual void* Accept(RegExpVisitor* visitor, void* data); 2109 virtual RegExpNode* ToNode(RegExpCompiler* compiler, 2110 RegExpNode* on_success); 2111 virtual RegExpBackReference* AsBackReference(); 2112 virtual bool IsBackReference(); min_match()2113 virtual int min_match() { return 0; } max_match()2114 virtual int max_match() { return capture_->max_match(); } index()2115 int index() { return capture_->index(); } capture()2116 RegExpCapture* capture() { return capture_; } 2117 private: 2118 RegExpCapture* capture_; 2119 }; 2120 2121 2122 class RegExpEmpty: public RegExpTree { 2123 public: RegExpEmpty()2124 RegExpEmpty() { } 2125 virtual void* Accept(RegExpVisitor* visitor, void* data); 2126 virtual RegExpNode* ToNode(RegExpCompiler* compiler, 2127 RegExpNode* on_success); 2128 virtual RegExpEmpty* AsEmpty(); 2129 virtual bool IsEmpty(); min_match()2130 virtual int min_match() { return 0; } max_match()2131 virtual int max_match() { return 0; } GetInstance()2132 static RegExpEmpty* GetInstance() { return &kInstance; } 2133 private: 2134 static RegExpEmpty kInstance; 2135 }; 2136 2137 2138 // ---------------------------------------------------------------------------- 2139 // Basic visitor 2140 // - leaf node visitors are abstract. 2141 2142 class AstVisitor BASE_EMBEDDED { 2143 public: AstVisitor()2144 AstVisitor() : isolate_(Isolate::Current()), stack_overflow_(false) { } ~AstVisitor()2145 virtual ~AstVisitor() { } 2146 2147 // Stack overflow check and dynamic dispatch. Visit(AstNode * node)2148 void Visit(AstNode* node) { if (!CheckStackOverflow()) node->Accept(this); } 2149 2150 // Iteration left-to-right. 2151 virtual void VisitDeclarations(ZoneList<Declaration*>* declarations); 2152 virtual void VisitStatements(ZoneList<Statement*>* statements); 2153 virtual void VisitExpressions(ZoneList<Expression*>* expressions); 2154 2155 // Stack overflow tracking support. HasStackOverflow()2156 bool HasStackOverflow() const { return stack_overflow_; } 2157 bool CheckStackOverflow(); 2158 2159 // If a stack-overflow exception is encountered when visiting a 2160 // node, calling SetStackOverflow will make sure that the visitor 2161 // bails out without visiting more nodes. SetStackOverflow()2162 void SetStackOverflow() { stack_overflow_ = true; } ClearStackOverflow()2163 void ClearStackOverflow() { stack_overflow_ = false; } 2164 2165 // Nodes not appearing in the AST, including slots. VisitSlot(Slot * node)2166 virtual void VisitSlot(Slot* node) { UNREACHABLE(); } 2167 2168 // Individual AST nodes. 2169 #define DEF_VISIT(type) \ 2170 virtual void Visit##type(type* node) = 0; AST_NODE_LIST(DEF_VISIT)2171 AST_NODE_LIST(DEF_VISIT) 2172 #undef DEF_VISIT 2173 2174 protected: 2175 Isolate* isolate() { return isolate_; } 2176 2177 private: 2178 Isolate* isolate_; 2179 bool stack_overflow_; 2180 }; 2181 2182 2183 } } // namespace v8::internal 2184 2185 #endif // V8_AST_H_ 2186