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
38namespace v8 {
39namespace 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
102class BitVector;
103class DefinitionInfo;
104class MaterializedLiteral;
105class TargetCollector;
106class TypeFeedbackOracle;
107
108#define DEF_FORWARD_DECLARATION(type) class type;
109AST_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 "> >".
115typedef ZoneList<Handle<String> > ZoneStringList;
116typedef 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
125class 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
137  AstNode() : id_(GetNextId()) {
138    Isolate* isolate = Isolate::Current();
139    isolate->set_ast_node_count(isolate->ast_node_count() + 1);
140  }
141
142  virtual ~AstNode() { }
143
144  virtual void Accept(AstVisitor* v) = 0;
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; }
150  AST_NODE_LIST(DECLARE_NODE_FUNCTIONS)
151#undef DECLARE_NODE_FUNCTIONS
152
153  virtual Statement* AsStatement() { return NULL; }
154  virtual Expression* AsExpression() { return NULL; }
155  virtual TargetCollector* AsTargetCollector() { return NULL; }
156  virtual BreakableStatement* AsBreakableStatement() { return NULL; }
157  virtual IterationStatement* AsIterationStatement() { return NULL; }
158  virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; }
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
164  static int Count() { return Isolate::Current()->ast_node_count(); }
165  static void ResetIds() { Isolate::Current()->set_ast_node_id(0); }
166  unsigned id() const { return id_; }
167
168 protected:
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  }
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
189class Statement: public AstNode {
190 public:
191  Statement() : statement_pos_(RelocInfo::kNoPosition) {}
192
193  virtual Statement* AsStatement()  { return this; }
194
195  virtual Assignment* StatementAsSimpleAssignment() { return NULL; }
196  virtual CountOperation* StatementAsCountOperation() { return NULL; }
197
198  bool IsEmpty() { return AsEmptyStatement() != NULL; }
199
200  void set_statement_pos(int statement_pos) { statement_pos_ = statement_pos; }
201  int statement_pos() const { return statement_pos_; }
202
203 private:
204  int statement_pos_;
205};
206
207
208class 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
222  Expression() {}
223
224  virtual int position() const {
225    UNREACHABLE();
226    return 0;
227  }
228
229  virtual Expression* AsExpression()  { return this; }
230
231  virtual bool IsTrivial() { return false; }
232  virtual bool IsValidLeftHandSide() { return false; }
233
234  // Helpers for ToBoolean conversion.
235  virtual bool ToBooleanIsTrue() { return false; }
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.
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.
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.
250  virtual bool ResultOverwriteAllowed() { return false; }
251
252  // True iff the expression is a literal represented as a smi.
253  virtual bool IsSmiLiteral() { return false; }
254
255  // Type feedback information for assignments and properties.
256  virtual bool IsMonomorphic() {
257    UNREACHABLE();
258    return false;
259  }
260  virtual bool IsArrayLength() {
261    UNREACHABLE();
262    return false;
263  }
264  virtual ZoneMapList* GetReceiverTypes() {
265    UNREACHABLE();
266    return NULL;
267  }
268  virtual Handle<Map> GetMonomorphicReceiverType() {
269    UNREACHABLE();
270    return Handle<Map>();
271  }
272
273  ExternalArrayType external_array_type() const {
274    return external_array_type_;
275  }
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 */
290class ValidLeftHandSideSentinel: public Expression {
291 public:
292  virtual bool IsValidLeftHandSide() { return true; }
293  virtual void Accept(AstVisitor* v) { UNREACHABLE(); }
294  virtual bool IsInlineable() const;
295};
296
297
298class 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.
307  ZoneStringList* labels() const { return labels_; }
308
309  // Type testing & conversion.
310  virtual BreakableStatement* AsBreakableStatement() { return this; }
311
312  // Code generation
313  Label* break_target() { return &break_target_; }
314
315  // Testers.
316  bool is_target_for_anonymous() const { return type_ == TARGET_FOR_ANONYMOUS; }
317
318  // Bailout support.
319  int EntryId() const { return entry_id_; }
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
334class Block: public BreakableStatement {
335 public:
336  inline Block(ZoneStringList* labels, int capacity, bool is_initializer_block);
337
338  DECLARE_NODE_TYPE(Block)
339
340  virtual Assignment* StatementAsSimpleAssignment() {
341    if (statements_.length() != 1) return NULL;
342    return statements_[0]->StatementAsSimpleAssignment();
343  }
344
345  virtual CountOperation* StatementAsCountOperation() {
346    if (statements_.length() != 1) return NULL;
347    return statements_[0]->StatementAsCountOperation();
348  }
349
350  virtual bool IsInlineable() const;
351
352  void AddStatement(Statement* statement) { statements_.Add(statement); }
353
354  ZoneList<Statement*>* statements() { return &statements_; }
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
363class Declaration: public AstNode {
364 public:
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
374  DECLARE_NODE_TYPE(Declaration)
375
376  VariableProxy* proxy() const { return proxy_; }
377  Variable::Mode mode() const { return mode_; }
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
388class IterationStatement: public BreakableStatement {
389 public:
390  // Type testing & conversion.
391  virtual IterationStatement* AsIterationStatement() { return this; }
392
393  Statement* body() const { return body_; }
394
395  // Bailout support.
396  int OsrEntryId() const { return osr_entry_id_; }
397  virtual int ContinueId() const = 0;
398
399  // Code generation
400  Label* continue_target()  { return &continue_target_; }
401
402 protected:
403  explicit inline IterationStatement(ZoneStringList* labels);
404
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
416class DoWhileStatement: public IterationStatement {
417 public:
418  explicit inline DoWhileStatement(ZoneStringList* labels);
419
420  DECLARE_NODE_TYPE(DoWhileStatement)
421
422  void Initialize(Expression* cond, Statement* body) {
423    IterationStatement::Initialize(body);
424    cond_ = cond;
425  }
426
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.
431  int condition_position() { return condition_position_; }
432  void set_condition_position(int pos) { condition_position_ = pos; }
433
434  // Bailout support.
435  virtual int ContinueId() const { return continue_id_; }
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
448class WhileStatement: public IterationStatement {
449 public:
450  explicit inline WhileStatement(ZoneStringList* labels);
451
452  DECLARE_NODE_TYPE(WhileStatement)
453
454  void Initialize(Expression* cond, Statement* body) {
455    IterationStatement::Initialize(body);
456    cond_ = cond;
457  }
458
459  Expression* cond() const { return cond_; }
460  bool may_have_function_literal() const {
461    return may_have_function_literal_;
462  }
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.
469  virtual int ContinueId() const { return EntryId(); }
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
480class ForStatement: public IterationStatement {
481 public:
482  explicit inline ForStatement(ZoneStringList* labels);
483
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
496  Statement* init() const { return init_; }
497  Expression* cond() const { return cond_; }
498  Statement* next() const { return next_; }
499
500  bool may_have_function_literal() const {
501    return may_have_function_literal_;
502  }
503  void set_may_have_function_literal(bool value) {
504    may_have_function_literal_ = value;
505  }
506
507  // Bailout support.
508  virtual int ContinueId() const { return continue_id_; }
509  int BodyId() const { return body_id_; }
510
511  bool is_fast_smi_loop() { return loop_variable_ != NULL; }
512  Variable* loop_variable() { return loop_variable_; }
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
528class ForInStatement: public IterationStatement {
529 public:
530  explicit inline ForInStatement(ZoneStringList* labels);
531
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
540  Expression* each() const { return each_; }
541  Expression* enumerable() const { return enumerable_; }
542  virtual bool IsInlineable() const;
543
544  // Bailout support.
545  int AssignmentId() const { return assignment_id_; }
546  virtual int ContinueId() const { return EntryId(); }
547
548 private:
549  Expression* each_;
550  Expression* enumerable_;
551  int assignment_id_;
552};
553
554
555class ExpressionStatement: public Statement {
556 public:
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
567  void set_expression(Expression* e) { expression_ = e; }
568  Expression* expression() const { return expression_; }
569
570 private:
571  Expression* expression_;
572};
573
574
575class ContinueStatement: public Statement {
576 public:
577  explicit ContinueStatement(IterationStatement* target)
578      : target_(target) { }
579
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
590class BreakStatement: public Statement {
591 public:
592  explicit BreakStatement(BreakableStatement* target)
593      : target_(target) { }
594
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
605class ReturnStatement: public Statement {
606 public:
607  explicit ReturnStatement(Expression* expression)
608      : expression_(expression) { }
609
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
620class WithEnterStatement: public Statement {
621 public:
622  explicit WithEnterStatement(Expression* expression, bool is_catch_block)
623      : expression_(expression), is_catch_block_(is_catch_block) { }
624
625  DECLARE_NODE_TYPE(WithEnterStatement)
626
627  Expression* expression() const { return expression_; }
628
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
638class WithExitStatement: public Statement {
639 public:
640  WithExitStatement() { }
641
642  virtual bool IsInlineable() const;
643
644  DECLARE_NODE_TYPE(WithExitStatement)
645};
646
647
648class CaseClause: public ZoneObject {
649 public:
650  CaseClause(Expression* label, ZoneList<Statement*>* statements, int pos);
651
652  bool is_default() const { return label_ == NULL; }
653  Expression* label() const {
654    CHECK(!is_default());
655    return label_;
656  }
657  Label* body_target() { return &body_target_; }
658  ZoneList<Statement*>* statements() const { return statements_; }
659
660  int position() const { return position_; }
661  void set_position(int pos) { position_ = pos; }
662
663  int EntryId() { return entry_id_; }
664
665  // Type feedback information.
666  void RecordTypeFeedback(TypeFeedbackOracle* oracle);
667  bool IsSmiCompare() { return compare_type_ == SMI_ONLY; }
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
681class SwitchStatement: public BreakableStatement {
682 public:
683  explicit inline SwitchStatement(ZoneStringList* labels);
684
685  DECLARE_NODE_TYPE(SwitchStatement)
686
687  void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) {
688    tag_ = tag;
689    cases_ = cases;
690  }
691
692  Expression* tag() const { return tag_; }
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.
707class IfStatement: public Statement {
708 public:
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
723  bool HasThenStatement() const { return !then_statement()->IsEmpty(); }
724  bool HasElseStatement() const { return !else_statement()->IsEmpty(); }
725
726  Expression* condition() const { return condition_; }
727  Statement* then_statement() const { return then_statement_; }
728  Statement* else_statement() const { return else_statement_; }
729
730  int ThenId() const { return then_id_; }
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.
744class TargetCollector: public AstNode {
745 public:
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.
756  virtual void Accept(AstVisitor* v) { UNREACHABLE(); }
757  virtual TargetCollector* AsTargetCollector() { return this; }
758
759  ZoneList<Label*>* targets() { return targets_; }
760  virtual bool IsInlineable() const;
761
762 private:
763  ZoneList<Label*>* targets_;
764};
765
766
767class TryStatement: public Statement {
768 public:
769  explicit TryStatement(Block* try_block)
770      : try_block_(try_block), escaping_targets_(NULL) { }
771
772  void set_escaping_targets(ZoneList<Label*>* targets) {
773    escaping_targets_ = targets;
774  }
775
776  Block* try_block() const { return try_block_; }
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
786class TryCatchStatement: public TryStatement {
787 public:
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
796  DECLARE_NODE_TYPE(TryCatchStatement)
797
798  VariableProxy* catch_var() const { return catch_var_; }
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
808class TryFinallyStatement: public TryStatement {
809 public:
810  TryFinallyStatement(Block* try_block, Block* finally_block)
811      : TryStatement(try_block),
812        finally_block_(finally_block) { }
813
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
824class DebuggerStatement: public Statement {
825 public:
826  DECLARE_NODE_TYPE(DebuggerStatement)
827  virtual bool IsInlineable() const;
828};
829
830
831class EmptyStatement: public Statement {
832 public:
833  DECLARE_NODE_TYPE(EmptyStatement)
834
835  virtual bool IsInlineable() const;
836};
837
838
839class Literal: public Expression {
840 public:
841  explicit Literal(Handle<Object> handle) : handle_(handle) { }
842
843  DECLARE_NODE_TYPE(Literal)
844
845  virtual bool IsTrivial() { return true; }
846  virtual bool IsSmiLiteral() { return handle_->IsSmi(); }
847
848  // Check if this literal is identical to the other literal.
849  bool IsIdenticalTo(const Literal* other) const {
850    return handle_.is_identical_to(other->handle_);
851  }
852
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
861  Handle<String> AsPropertyName() {
862    ASSERT(IsPropertyName());
863    return Handle<String>::cast(handle_);
864  }
865
866  virtual bool ToBooleanIsTrue() { return handle_->ToBoolean()->IsTrue(); }
867  virtual bool ToBooleanIsFalse() { return handle_->ToBoolean()->IsFalse(); }
868
869  // Identity testers.
870  bool IsNull() const {
871    ASSERT(!handle_.is_null());
872    return handle_->IsNull();
873  }
874  bool IsTrue() const {
875    ASSERT(!handle_.is_null());
876    return handle_->IsTrue();
877  }
878  bool IsFalse() const {
879    ASSERT(!handle_.is_null());
880    return handle_->IsFalse();
881  }
882
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.
892class MaterializedLiteral: public Expression {
893 public:
894  explicit MaterializedLiteral(int literal_index, bool is_simple, int depth)
895      : literal_index_(literal_index), is_simple_(is_simple), depth_(depth) {}
896
897  virtual MaterializedLiteral* AsMaterializedLiteral() { return this; }
898
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.
903  bool is_simple() const { return is_simple_; }
904
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.
917class 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
935    Literal* key() { return key_; }
936    Expression* value() { return value_; }
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
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
964  DECLARE_NODE_TYPE(ObjectLiteral)
965
966  Handle<FixedArray> constant_properties() const {
967    return constant_properties_;
968  }
969  ZoneList<Property*>* properties() const { return properties_; }
970
971  bool fast_elements() const { return fast_elements_; }
972
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.
995class RegExpLiteral: public MaterializedLiteral {
996 public:
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
1004  DECLARE_NODE_TYPE(RegExpLiteral)
1005
1006  Handle<String> pattern() const { return pattern_; }
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.
1016class ArrayLiteral: public MaterializedLiteral {
1017 public:
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
1028  DECLARE_NODE_TYPE(ArrayLiteral)
1029
1030  Handle<FixedArray> constant_elements() const { return constant_elements_; }
1031  ZoneList<Expression*>* values() const { return values_; }
1032
1033  // Return an AST id for an element that is used in simulate instructions.
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.
1046class CatchExtensionObject: public Expression {
1047 public:
1048  CatchExtensionObject(Literal* key, VariableProxy* value)
1049      : key_(key), value_(value) {
1050  }
1051
1052  DECLARE_NODE_TYPE(CatchExtensionObject)
1053
1054  Literal* key() const { return key_; }
1055  VariableProxy* value() const { return value_; }
1056  virtual bool IsInlineable() const;
1057
1058 private:
1059  Literal* key_;
1060  VariableProxy* value_;
1061};
1062
1063
1064class VariableProxy: public Expression {
1065 public:
1066  explicit VariableProxy(Variable* var);
1067
1068  DECLARE_NODE_TYPE(VariableProxy)
1069
1070  // Type testing & conversion
1071  virtual Property* AsProperty() {
1072    return var_ == NULL ? NULL : var_->AsProperty();
1073  }
1074
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
1082  virtual bool IsValidLeftHandSide() {
1083    return var_ == NULL ? true : var_->IsValidLeftHandSide();
1084  }
1085
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
1094  bool IsVariable(Handle<String> n) {
1095    return !is_this() && name().is_identical_to(n);
1096  }
1097
1098  bool IsArguments() {
1099    Variable* variable = AsVariable();
1100    return (variable == NULL) ? false : variable->is_arguments();
1101  }
1102
1103  Handle<String> name() const { return name_; }
1104  Variable* var() const { return var_; }
1105  bool is_this() const { return is_this_; }
1106  bool inside_with() const { return inside_with_; }
1107  int position() const { return position_; }
1108
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
1132class VariableProxySentinel: public VariableProxy {
1133 public:
1134  virtual bool IsValidLeftHandSide() { return !is_this(); }
1135
1136 private:
1137  explicit VariableProxySentinel(bool is_this) : VariableProxy(is_this) { }
1138
1139  friend class AstSentinels;
1140};
1141
1142
1143class 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
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
1174  virtual Slot* AsSlot() { return this; }
1175
1176  bool IsStackAllocated() { return type_ == PARAMETER || type_ == LOCAL; }
1177
1178  // Accessors
1179  Variable* var() const { return var_; }
1180  Type type() const { return type_; }
1181  int index() const { return index_; }
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
1192class 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)
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
1212  DECLARE_NODE_TYPE(Property)
1213
1214  virtual bool IsValidLeftHandSide() { return true; }
1215  virtual bool IsInlineable() const;
1216
1217  Expression* obj() const { return obj_; }
1218  Expression* key() const { return key_; }
1219  virtual int position() const { return pos_; }
1220  bool is_synthetic() const { return type_ == SYNTHETIC; }
1221
1222  bool IsStringLength() const { return is_string_length_; }
1223  bool IsStringAccess() const { return is_string_access_; }
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.
1228  void set_is_arguments_access(bool is_arguments_access) {
1229    is_arguments_access_ = is_arguments_access;
1230  }
1231  bool is_arguments_access() const { return is_arguments_access_; }
1232
1233  // Type feedback information.
1234  void RecordTypeFeedback(TypeFeedbackOracle* oracle);
1235  virtual bool IsMonomorphic() { return is_monomorphic_; }
1236  virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; }
1237  virtual bool IsArrayLength() { return is_array_length_; }
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
1259class Call: public Expression {
1260 public:
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
1275  Expression* expression() const { return expression_; }
1276  ZoneList<Expression*>* arguments() const { return arguments_; }
1277  virtual int position() const { return pos_; }
1278
1279  void RecordTypeFeedback(TypeFeedbackOracle* oracle);
1280  virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; }
1281  virtual bool IsMonomorphic() { return is_monomorphic_; }
1282  CheckType check_type() const { return check_type_; }
1283  Handle<JSFunction> target() { return target_; }
1284  Handle<JSObject> holder() { return holder_; }
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.
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
1314class AstSentinels {
1315 public:
1316  ~AstSentinels() { }
1317
1318  // Returns a property singleton property access on 'this'.  Used
1319  // during preparsing.
1320  Property* this_property() { return &this_property_; }
1321  VariableProxySentinel* this_proxy() { return &this_proxy_; }
1322  VariableProxySentinel* identifier_proxy() { return &identifier_proxy_; }
1323  ValidLeftHandSideSentinel* valid_left_hand_side_sentinel() {
1324    return &valid_left_hand_side_sentinel_;
1325  }
1326  Call* call_sentinel() { return &call_sentinel_; }
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
1344class CallNew: public Expression {
1345 public:
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
1353  Expression* expression() const { return expression_; }
1354  ZoneList<Expression*>* arguments() const { return arguments_; }
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").
1368class CallRuntime: public Expression {
1369 public:
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
1379  Handle<String> name() const { return name_; }
1380  const Runtime::Function* function() const { return function_; }
1381  ZoneList<Expression*>* arguments() const { return arguments_; }
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
1391class UnaryOperation: public Expression {
1392 public:
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
1404  Token::Value op() const { return op_; }
1405  Expression* expression() const { return expression_; }
1406
1407 private:
1408  Token::Value op_;
1409  Expression* expression_;
1410};
1411
1412
1413class BinaryOperation: public Expression {
1414 public:
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
1435  Token::Value op() const { return op_; }
1436  Expression* left() const { return left_; }
1437  Expression* right() const { return right_; }
1438  virtual int position() const { return pos_; }
1439
1440  // Bailout support.
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
1454class CountOperation: public Expression {
1455 public:
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
1464  DECLARE_NODE_TYPE(CountOperation)
1465
1466  bool is_prefix() const { return is_prefix_; }
1467  bool is_postfix() const { return !is_prefix_; }
1468
1469  Token::Value op() const { return op_; }
1470  Token::Value binary_op() {
1471    return (op() == Token::INC) ? Token::ADD : Token::SUB;
1472  }
1473
1474  Expression* expression() const { return expression_; }
1475  virtual int position() const { return pos_; }
1476
1477  virtual void MarkAsStatement() { is_prefix_ = true; }
1478
1479  virtual bool IsInlineable() const;
1480
1481  void RecordTypeFeedback(TypeFeedbackOracle* oracle);
1482  virtual bool IsMonomorphic() { return is_monomorphic_; }
1483  virtual Handle<Map> GetMonomorphicReceiverType() {
1484    return monomorphic_receiver_type_;
1485  }
1486
1487  // Bailout support.
1488  int AssignmentId() const { return assignment_id_; }
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
1503class CompareOperation: public Expression {
1504 public:
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
1513  DECLARE_NODE_TYPE(CompareOperation)
1514
1515  Token::Value op() const { return op_; }
1516  Expression* left() const { return left_; }
1517  Expression* right() const { return right_; }
1518  virtual int position() const { return pos_; }
1519
1520  virtual bool IsInlineable() const;
1521
1522  // Type feedback information.
1523  void RecordTypeFeedback(TypeFeedbackOracle* oracle);
1524  bool IsSmiCompare() { return compare_type_ == SMI_ONLY; }
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
1538class CompareToNull: public Expression {
1539 public:
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
1547  bool is_strict() const { return is_strict_; }
1548  Token::Value op() const { return is_strict_ ? Token::EQ_STRICT : Token::EQ; }
1549  Expression* expression() const { return expression_; }
1550
1551 private:
1552  bool is_strict_;
1553  Expression* expression_;
1554};
1555
1556
1557class Conditional: public Expression {
1558 public:
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
1577  Expression* condition() const { return condition_; }
1578  Expression* then_expression() const { return then_expression_; }
1579  Expression* else_expression() const { return else_expression_; }
1580
1581  int then_expression_position() const { return then_expression_position_; }
1582  int else_expression_position() const { return else_expression_position_; }
1583
1584  int ThenId() const { return then_id_; }
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
1598class 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
1606  Assignment* AsSimpleAssignment() { return !is_compound() ? this : NULL; }
1607
1608  Token::Value binary_op() const;
1609
1610  Token::Value op() const { return op_; }
1611  Expression* target() const { return target_; }
1612  Expression* value() const { return value_; }
1613  virtual int position() const { return pos_; }
1614  BinaryOperation* binary_operation() const { return binary_operation_; }
1615
1616  // This check relies on the definition order of token in token.h.
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.
1623  bool starts_initialization_block() { return block_start_; }
1624  bool ends_initialization_block() { return block_end_; }
1625  void mark_block_start() { block_start_ = true; }
1626  void mark_block_end() { block_end_ = true; }
1627
1628  // Type feedback information.
1629  void RecordTypeFeedback(TypeFeedbackOracle* oracle);
1630  virtual bool IsMonomorphic() { return is_monomorphic_; }
1631  virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; }
1632  virtual Handle<Map> GetMonomorphicReceiverType() {
1633    return monomorphic_receiver_type_;
1634  }
1635
1636  // Bailout support.
1637  int CompoundLoadId() const { return compound_load_id_; }
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
1658class Throw: public Expression {
1659 public:
1660  Throw(Expression* exception, int pos)
1661      : exception_(exception), pos_(pos) {}
1662
1663  DECLARE_NODE_TYPE(Throw)
1664
1665  Expression* exception() const { return exception_; }
1666  virtual int position() const { return pos_; }
1667  virtual bool IsInlineable() const;
1668
1669 private:
1670  Expression* exception_;
1671  int pos_;
1672};
1673
1674
1675class FunctionLiteral: public Expression {
1676 public:
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
1704  DECLARE_NODE_TYPE(FunctionLiteral)
1705
1706  Handle<String> name() const { return name_; }
1707  Scope* scope() const { return scope_; }
1708  ZoneList<Statement*>* body() const { return body_; }
1709  void set_function_token_position(int pos) { function_token_position_ = pos; }
1710  int function_token_position() const { return function_token_position_; }
1711  int start_position() const { return start_position_; }
1712  int end_position() const { return end_position_; }
1713  bool is_expression() const { return is_expression_; }
1714  bool strict_mode() const;
1715
1716  int materialized_literal_count() { return materialized_literal_count_; }
1717  int expected_property_count() { return expected_property_count_; }
1718  bool has_only_simple_this_property_assignments() {
1719      return has_only_simple_this_property_assignments_;
1720  }
1721  Handle<FixedArray> this_property_assignments() {
1722      return this_property_assignments_;
1723  }
1724  int num_parameters() { return num_parameters_; }
1725
1726  bool AllowsLazyCompilation();
1727
1728  Handle<String> debug_name() const {
1729    if (name_->length() > 0) return name_;
1730    return inferred_name();
1731  }
1732
1733  Handle<String> inferred_name() const { return inferred_name_; }
1734  void set_inferred_name(Handle<String> inferred_name) {
1735    inferred_name_ = inferred_name;
1736  }
1737
1738  bool pretenure() { return pretenure_; }
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
1760class SharedFunctionInfoLiteral: public Expression {
1761 public:
1762  explicit SharedFunctionInfoLiteral(
1763      Handle<SharedFunctionInfo> shared_function_info)
1764      : shared_function_info_(shared_function_info) { }
1765
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
1778class ThisFunction: public Expression {
1779 public:
1780  DECLARE_NODE_TYPE(ThisFunction)
1781  virtual bool IsInlineable() const;
1782};
1783
1784
1785// ----------------------------------------------------------------------------
1786// Regular expressions
1787
1788
1789class RegExpVisitor BASE_EMBEDDED {
1790 public:
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
1799class RegExpTree: public ZoneObject {
1800 public:
1801  static const int kInfinity = kMaxInt;
1802  virtual ~RegExpTree() { }
1803  virtual void* Accept(RegExpVisitor* visitor, void* data) = 0;
1804  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
1805                             RegExpNode* on_success) = 0;
1806  virtual bool IsTextElement() { return false; }
1807  virtual bool IsAnchoredAtStart() { return false; }
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.
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
1824class 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();
1835  virtual int min_match() { return min_match_; }
1836  virtual int max_match() { return max_match_; }
1837  ZoneList<RegExpTree*>* alternatives() { return alternatives_; }
1838 private:
1839  ZoneList<RegExpTree*>* alternatives_;
1840  int min_match_;
1841  int max_match_;
1842};
1843
1844
1845class 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();
1856  virtual int min_match() { return min_match_; }
1857  virtual int max_match() { return max_match_; }
1858  ZoneList<RegExpTree*>* nodes() { return nodes_; }
1859 private:
1860  ZoneList<RegExpTree*>* nodes_;
1861  int min_match_;
1862  int max_match_;
1863};
1864
1865
1866class 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  };
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();
1884  virtual int min_match() { return 0; }
1885  virtual int max_match() { return 0; }
1886  Type type() { return type_; }
1887 private:
1888  Type type_;
1889};
1890
1891
1892class CharacterSet BASE_EMBEDDED {
1893 public:
1894  explicit CharacterSet(uc16 standard_set_type)
1895      : ranges_(NULL),
1896        standard_set_type_(standard_set_type) {}
1897  explicit CharacterSet(ZoneList<CharacterRange>* ranges)
1898      : ranges_(ranges),
1899        standard_set_type_(0) {}
1900  ZoneList<CharacterRange>* ranges();
1901  uc16 standard_set_type() { return standard_set_type_; }
1902  void set_standard_set_type(uc16 special_set_type) {
1903    standard_set_type_ = special_set_type;
1904  }
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
1915class RegExpCharacterClass: public RegExpTree {
1916 public:
1917  RegExpCharacterClass(ZoneList<CharacterRange>* ranges, bool is_negated)
1918      : set_(ranges),
1919        is_negated_(is_negated) { }
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();
1928  virtual bool IsTextElement() { return true; }
1929  virtual int min_match() { return 1; }
1930  virtual int max_match() { return 1; }
1931  virtual void AppendToText(RegExpText* text);
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
1947  uc16 standard_type() { return set_.standard_set_type(); }
1948  ZoneList<CharacterRange>* ranges() { return set_.ranges(); }
1949  bool is_negated() { return is_negated_; }
1950 private:
1951  CharacterSet set_;
1952  bool is_negated_;
1953};
1954
1955
1956class RegExpAtom: public RegExpTree {
1957 public:
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();
1964  virtual bool IsTextElement() { return true; }
1965  virtual int min_match() { return data_.length(); }
1966  virtual int max_match() { return data_.length(); }
1967  virtual void AppendToText(RegExpText* text);
1968  Vector<const uc16> data() { return data_; }
1969  int length() { return data_.length(); }
1970 private:
1971  Vector<const uc16> data_;
1972};
1973
1974
1975class RegExpText: public RegExpTree {
1976 public:
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();
1983  virtual bool IsTextElement() { return true; }
1984  virtual int min_match() { return length_; }
1985  virtual int max_match() { return length_; }
1986  virtual void AppendToText(RegExpText* text);
1987  void AddElement(TextElement elm)  {
1988    elements_.Add(elm);
1989    length_ += elm.length();
1990  }
1991  ZoneList<TextElement>* elements() { return &elements_; }
1992 private:
1993  ZoneList<TextElement> elements_;
1994  int length_;
1995};
1996
1997
1998class RegExpQuantifier: public RegExpTree {
1999 public:
2000  enum Type { GREEDY, NON_GREEDY, POSSESSIVE };
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();
2026  virtual int min_match() { return min_match_; }
2027  virtual int max_match() { return max_match_; }
2028  int min() { return min_; }
2029  int max() { return max_; }
2030  bool is_possessive() { return type_ == POSSESSIVE; }
2031  bool is_non_greedy() { return type_ == NON_GREEDY; }
2032  bool is_greedy() { return type_ == GREEDY; }
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
2044class RegExpCapture: public RegExpTree {
2045 public:
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();
2060  virtual int min_match() { return body_->min_match(); }
2061  virtual int max_match() { return body_->max_match(); }
2062  RegExpTree* body() { return body_; }
2063  int index() { return index_; }
2064  static int StartRegister(int index) { return index * 2; }
2065  static int EndRegister(int index) { return index * 2 + 1; }
2066 private:
2067  RegExpTree* body_;
2068  int index_;
2069};
2070
2071
2072class RegExpLookahead: public RegExpTree {
2073 public:
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();
2090  virtual int min_match() { return 0; }
2091  virtual int max_match() { return 0; }
2092  RegExpTree* body() { return body_; }
2093  bool is_positive() { return is_positive_; }
2094  int capture_count() { return capture_count_; }
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
2104class RegExpBackReference: public RegExpTree {
2105 public:
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();
2113  virtual int min_match() { return 0; }
2114  virtual int max_match() { return capture_->max_match(); }
2115  int index() { return capture_->index(); }
2116  RegExpCapture* capture() { return capture_; }
2117 private:
2118  RegExpCapture* capture_;
2119};
2120
2121
2122class RegExpEmpty: public RegExpTree {
2123 public:
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();
2130  virtual int min_match() { return 0; }
2131  virtual int max_match() { return 0; }
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
2142class AstVisitor BASE_EMBEDDED {
2143 public:
2144  AstVisitor() : isolate_(Isolate::Current()), stack_overflow_(false) { }
2145  virtual ~AstVisitor() { }
2146
2147  // Stack overflow check and dynamic dispatch.
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.
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.
2162  void SetStackOverflow() { stack_overflow_ = true; }
2163  void ClearStackOverflow() { stack_overflow_ = false; }
2164
2165  // Nodes not appearing in the AST, including slots.
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;
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