• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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