• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_PARSER_H_
6 #define V8_PARSER_H_
7 
8 #include "src/allocation.h"
9 #include "src/ast.h"
10 #include "src/compiler.h"  // For CachedDataMode
11 #include "src/preparse-data.h"
12 #include "src/preparse-data-format.h"
13 #include "src/preparser.h"
14 #include "src/scopes.h"
15 
16 namespace v8 {
17 class ScriptCompiler;
18 
19 namespace internal {
20 
21 class CompilationInfo;
22 class ParserLog;
23 class PositionStack;
24 class Target;
25 
26 template <typename T> class ZoneListWrapper;
27 
28 
29 class FunctionEntry BASE_EMBEDDED {
30  public:
31   enum {
32     kStartPositionIndex,
33     kEndPositionIndex,
34     kLiteralCountIndex,
35     kPropertyCountIndex,
36     kStrictModeIndex,
37     kSize
38   };
39 
FunctionEntry(Vector<unsigned> backing)40   explicit FunctionEntry(Vector<unsigned> backing)
41     : backing_(backing) { }
42 
FunctionEntry()43   FunctionEntry() : backing_() { }
44 
start_pos()45   int start_pos() { return backing_[kStartPositionIndex]; }
end_pos()46   int end_pos() { return backing_[kEndPositionIndex]; }
literal_count()47   int literal_count() { return backing_[kLiteralCountIndex]; }
property_count()48   int property_count() { return backing_[kPropertyCountIndex]; }
strict_mode()49   StrictMode strict_mode() {
50     DCHECK(backing_[kStrictModeIndex] == SLOPPY ||
51            backing_[kStrictModeIndex] == STRICT);
52     return static_cast<StrictMode>(backing_[kStrictModeIndex]);
53   }
54 
is_valid()55   bool is_valid() { return !backing_.is_empty(); }
56 
57  private:
58   Vector<unsigned> backing_;
59 };
60 
61 
62 // Wrapper around ScriptData to provide parser-specific functionality.
63 class ParseData {
64  public:
ParseData(ScriptData * script_data)65   explicit ParseData(ScriptData* script_data) : script_data_(script_data) {
66     CHECK(IsAligned(script_data->length(), sizeof(unsigned)));
67     CHECK(IsSane());
68   }
69   void Initialize();
70   FunctionEntry GetFunctionEntry(int start);
71   int FunctionCount();
72 
73   bool HasError();
74 
Data()75   unsigned* Data() {  // Writable data as unsigned int array.
76     return reinterpret_cast<unsigned*>(const_cast<byte*>(script_data_->data()));
77   }
78 
79  private:
80   bool IsSane();
81   unsigned Magic();
82   unsigned Version();
83   int FunctionsSize();
Length()84   int Length() const {
85     // Script data length is already checked to be a multiple of unsigned size.
86     return script_data_->length() / sizeof(unsigned);
87   }
88 
89   ScriptData* script_data_;
90   int function_index_;
91 
92   DISALLOW_COPY_AND_ASSIGN(ParseData);
93 };
94 
95 // ----------------------------------------------------------------------------
96 // REGEXP PARSING
97 
98 // A BufferedZoneList is an automatically growing list, just like (and backed
99 // by) a ZoneList, that is optimized for the case of adding and removing
100 // a single element. The last element added is stored outside the backing list,
101 // and if no more than one element is ever added, the ZoneList isn't even
102 // allocated.
103 // Elements must not be NULL pointers.
104 template <typename T, int initial_size>
105 class BufferedZoneList {
106  public:
BufferedZoneList()107   BufferedZoneList() : list_(NULL), last_(NULL) {}
108 
109   // Adds element at end of list. This element is buffered and can
110   // be read using last() or removed using RemoveLast until a new Add or until
111   // RemoveLast or GetList has been called.
Add(T * value,Zone * zone)112   void Add(T* value, Zone* zone) {
113     if (last_ != NULL) {
114       if (list_ == NULL) {
115         list_ = new(zone) ZoneList<T*>(initial_size, zone);
116       }
117       list_->Add(last_, zone);
118     }
119     last_ = value;
120   }
121 
last()122   T* last() {
123     DCHECK(last_ != NULL);
124     return last_;
125   }
126 
RemoveLast()127   T* RemoveLast() {
128     DCHECK(last_ != NULL);
129     T* result = last_;
130     if ((list_ != NULL) && (list_->length() > 0))
131       last_ = list_->RemoveLast();
132     else
133       last_ = NULL;
134     return result;
135   }
136 
Get(int i)137   T* Get(int i) {
138     DCHECK((0 <= i) && (i < length()));
139     if (list_ == NULL) {
140       DCHECK_EQ(0, i);
141       return last_;
142     } else {
143       if (i == list_->length()) {
144         DCHECK(last_ != NULL);
145         return last_;
146       } else {
147         return list_->at(i);
148       }
149     }
150   }
151 
Clear()152   void Clear() {
153     list_ = NULL;
154     last_ = NULL;
155   }
156 
length()157   int length() {
158     int length = (list_ == NULL) ? 0 : list_->length();
159     return length + ((last_ == NULL) ? 0 : 1);
160   }
161 
GetList(Zone * zone)162   ZoneList<T*>* GetList(Zone* zone) {
163     if (list_ == NULL) {
164       list_ = new(zone) ZoneList<T*>(initial_size, zone);
165     }
166     if (last_ != NULL) {
167       list_->Add(last_, zone);
168       last_ = NULL;
169     }
170     return list_;
171   }
172 
173  private:
174   ZoneList<T*>* list_;
175   T* last_;
176 };
177 
178 
179 // Accumulates RegExp atoms and assertions into lists of terms and alternatives.
180 class RegExpBuilder: public ZoneObject {
181  public:
182   explicit RegExpBuilder(Zone* zone);
183   void AddCharacter(uc16 character);
184   // "Adds" an empty expression. Does nothing except consume a
185   // following quantifier
186   void AddEmpty();
187   void AddAtom(RegExpTree* tree);
188   void AddAssertion(RegExpTree* tree);
189   void NewAlternative();  // '|'
190   void AddQuantifierToAtom(
191       int min, int max, RegExpQuantifier::QuantifierType type);
192   RegExpTree* ToRegExp();
193 
194  private:
195   void FlushCharacters();
196   void FlushText();
197   void FlushTerms();
zone()198   Zone* zone() const { return zone_; }
199 
200   Zone* zone_;
201   bool pending_empty_;
202   ZoneList<uc16>* characters_;
203   BufferedZoneList<RegExpTree, 2> terms_;
204   BufferedZoneList<RegExpTree, 2> text_;
205   BufferedZoneList<RegExpTree, 2> alternatives_;
206 #ifdef DEBUG
207   enum {ADD_NONE, ADD_CHAR, ADD_TERM, ADD_ASSERT, ADD_ATOM} last_added_;
208 #define LAST(x) last_added_ = x;
209 #else
210 #define LAST(x)
211 #endif
212 };
213 
214 
215 class RegExpParser BASE_EMBEDDED {
216  public:
217   RegExpParser(FlatStringReader* in,
218                Handle<String>* error,
219                bool multiline_mode,
220                Zone* zone);
221 
222   static bool ParseRegExp(FlatStringReader* input,
223                           bool multiline,
224                           RegExpCompileData* result,
225                           Zone* zone);
226 
227   RegExpTree* ParsePattern();
228   RegExpTree* ParseDisjunction();
229   RegExpTree* ParseGroup();
230   RegExpTree* ParseCharacterClass();
231 
232   // Parses a {...,...} quantifier and stores the range in the given
233   // out parameters.
234   bool ParseIntervalQuantifier(int* min_out, int* max_out);
235 
236   // Parses and returns a single escaped character.  The character
237   // must not be 'b' or 'B' since they are usually handle specially.
238   uc32 ParseClassCharacterEscape();
239 
240   // Checks whether the following is a length-digit hexadecimal number,
241   // and sets the value if it is.
242   bool ParseHexEscape(int length, uc32* value);
243 
244   uc32 ParseOctalLiteral();
245 
246   // Tries to parse the input as a back reference.  If successful it
247   // stores the result in the output parameter and returns true.  If
248   // it fails it will push back the characters read so the same characters
249   // can be reparsed.
250   bool ParseBackReferenceIndex(int* index_out);
251 
252   CharacterRange ParseClassAtom(uc16* char_class);
253   RegExpTree* ReportError(Vector<const char> message);
254   void Advance();
255   void Advance(int dist);
256   void Reset(int pos);
257 
258   // Reports whether the pattern might be used as a literal search string.
259   // Only use if the result of the parse is a single atom node.
260   bool simple();
contains_anchor()261   bool contains_anchor() { return contains_anchor_; }
set_contains_anchor()262   void set_contains_anchor() { contains_anchor_ = true; }
captures_started()263   int captures_started() { return captures_ == NULL ? 0 : captures_->length(); }
position()264   int position() { return next_pos_ - 1; }
failed()265   bool failed() { return failed_; }
266 
267   static const int kMaxCaptures = 1 << 16;
268   static const uc32 kEndMarker = (1 << 21);
269 
270  private:
271   enum SubexpressionType {
272     INITIAL,
273     CAPTURE,  // All positive values represent captures.
274     POSITIVE_LOOKAHEAD,
275     NEGATIVE_LOOKAHEAD,
276     GROUPING
277   };
278 
279   class RegExpParserState : public ZoneObject {
280    public:
RegExpParserState(RegExpParserState * previous_state,SubexpressionType group_type,int disjunction_capture_index,Zone * zone)281     RegExpParserState(RegExpParserState* previous_state,
282                       SubexpressionType group_type,
283                       int disjunction_capture_index,
284                       Zone* zone)
285         : previous_state_(previous_state),
286           builder_(new(zone) RegExpBuilder(zone)),
287           group_type_(group_type),
288           disjunction_capture_index_(disjunction_capture_index) {}
289     // Parser state of containing expression, if any.
previous_state()290     RegExpParserState* previous_state() { return previous_state_; }
IsSubexpression()291     bool IsSubexpression() { return previous_state_ != NULL; }
292     // RegExpBuilder building this regexp's AST.
builder()293     RegExpBuilder* builder() { return builder_; }
294     // Type of regexp being parsed (parenthesized group or entire regexp).
group_type()295     SubexpressionType group_type() { return group_type_; }
296     // Index in captures array of first capture in this sub-expression, if any.
297     // Also the capture index of this sub-expression itself, if group_type
298     // is CAPTURE.
capture_index()299     int capture_index() { return disjunction_capture_index_; }
300 
301    private:
302     // Linked list implementation of stack of states.
303     RegExpParserState* previous_state_;
304     // Builder for the stored disjunction.
305     RegExpBuilder* builder_;
306     // Stored disjunction type (capture, look-ahead or grouping), if any.
307     SubexpressionType group_type_;
308     // Stored disjunction's capture index (if any).
309     int disjunction_capture_index_;
310   };
311 
isolate()312   Isolate* isolate() { return isolate_; }
zone()313   Zone* zone() const { return zone_; }
314 
current()315   uc32 current() { return current_; }
has_more()316   bool has_more() { return has_more_; }
has_next()317   bool has_next() { return next_pos_ < in()->length(); }
318   uc32 Next();
in()319   FlatStringReader* in() { return in_; }
320   void ScanForCaptures();
321 
322   Isolate* isolate_;
323   Zone* zone_;
324   Handle<String>* error_;
325   ZoneList<RegExpCapture*>* captures_;
326   FlatStringReader* in_;
327   uc32 current_;
328   int next_pos_;
329   // The capture count is only valid after we have scanned for captures.
330   int capture_count_;
331   bool has_more_;
332   bool multiline_;
333   bool simple_;
334   bool contains_anchor_;
335   bool is_scanned_for_captures_;
336   bool failed_;
337 };
338 
339 // ----------------------------------------------------------------------------
340 // JAVASCRIPT PARSING
341 
342 class Parser;
343 class SingletonLogger;
344 
345 class ParserTraits {
346  public:
347   struct Type {
348     // TODO(marja): To be removed. The Traits object should contain all the data
349     // it needs.
350     typedef v8::internal::Parser* Parser;
351 
352     // Used by FunctionState and BlockState.
353     typedef v8::internal::Scope Scope;
354     typedef v8::internal::Scope* ScopePtr;
355     typedef Variable GeneratorVariable;
356     typedef v8::internal::Zone Zone;
357 
358     typedef v8::internal::AstProperties AstProperties;
359     typedef Vector<VariableProxy*> ParameterIdentifierVector;
360 
361     // Return types for traversing functions.
362     typedef const AstRawString* Identifier;
363     typedef v8::internal::Expression* Expression;
364     typedef Yield* YieldExpression;
365     typedef v8::internal::FunctionLiteral* FunctionLiteral;
366     typedef v8::internal::ClassLiteral* ClassLiteral;
367     typedef v8::internal::Literal* Literal;
368     typedef ObjectLiteral::Property* ObjectLiteralProperty;
369     typedef ZoneList<v8::internal::Expression*>* ExpressionList;
370     typedef ZoneList<ObjectLiteral::Property*>* PropertyList;
371     typedef ZoneList<v8::internal::Statement*>* StatementList;
372 
373     // For constructing objects returned by the traversing functions.
374     typedef AstNodeFactory<AstConstructionVisitor> Factory;
375   };
376 
377   class Checkpoint;
378 
ParserTraits(Parser * parser)379   explicit ParserTraits(Parser* parser) : parser_(parser) {}
380 
381   // Custom operations executed when FunctionStates are created and destructed.
382   template <typename FunctionState>
SetUpFunctionState(FunctionState * function_state)383   static void SetUpFunctionState(FunctionState* function_state) {
384     function_state->saved_id_gen_ = *function_state->ast_node_id_gen_;
385     *function_state->ast_node_id_gen_ =
386         AstNode::IdGen(BailoutId::FirstUsable().ToInt());
387   }
388 
389   template <typename FunctionState>
TearDownFunctionState(FunctionState * function_state)390   static void TearDownFunctionState(FunctionState* function_state) {
391     if (function_state->outer_function_state_ != NULL) {
392       *function_state->ast_node_id_gen_ = function_state->saved_id_gen_;
393     }
394   }
395 
396   // Helper functions for recursive descent.
397   bool IsEvalOrArguments(const AstRawString* identifier) const;
398   V8_INLINE bool IsFutureStrictReserved(const AstRawString* identifier) const;
399 
400   // Returns true if the expression is of type "this.foo".
401   static bool IsThisProperty(Expression* expression);
402 
403   static bool IsIdentifier(Expression* expression);
404 
405   bool IsPrototype(const AstRawString* identifier) const;
406 
407   bool IsConstructor(const AstRawString* identifier) const;
408 
AsIdentifier(Expression * expression)409   static const AstRawString* AsIdentifier(Expression* expression) {
410     DCHECK(IsIdentifier(expression));
411     return expression->AsVariableProxy()->raw_name();
412   }
413 
IsBoilerplateProperty(ObjectLiteral::Property * property)414   static bool IsBoilerplateProperty(ObjectLiteral::Property* property) {
415     return ObjectLiteral::IsBoilerplateProperty(property);
416   }
417 
IsArrayIndex(const AstRawString * string,uint32_t * index)418   static bool IsArrayIndex(const AstRawString* string, uint32_t* index) {
419     return string->AsArrayIndex(index);
420   }
421 
422   // Functions for encapsulating the differences between parsing and preparsing;
423   // operations interleaved with the recursive descent.
PushLiteralName(FuncNameInferrer * fni,const AstRawString * id)424   static void PushLiteralName(FuncNameInferrer* fni, const AstRawString* id) {
425     fni->PushLiteralName(id);
426   }
427   void PushPropertyName(FuncNameInferrer* fni, Expression* expression);
InferFunctionName(FuncNameInferrer * fni,FunctionLiteral * func_to_infer)428   static void InferFunctionName(FuncNameInferrer* fni,
429                                 FunctionLiteral* func_to_infer) {
430     fni->AddFunction(func_to_infer);
431   }
432 
CheckFunctionLiteralInsideTopLevelObjectLiteral(Scope * scope,ObjectLiteralProperty * property,bool * has_function)433   static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
434       Scope* scope, ObjectLiteralProperty* property, bool* has_function) {
435     Expression* value = property->value();
436     if (scope->DeclarationScope()->is_global_scope() &&
437         value->AsFunctionLiteral() != NULL) {
438       *has_function = true;
439       value->AsFunctionLiteral()->set_pretenure();
440     }
441   }
442 
443   // If we assign a function literal to a property we pretenure the
444   // literal so it can be added as a constant function property.
445   static void CheckAssigningFunctionLiteralToProperty(Expression* left,
446                                                       Expression* right);
447 
448   // Keep track of eval() calls since they disable all local variable
449   // optimizations. This checks if expression is an eval call, and if yes,
450   // forwards the information to scope.
451   void CheckPossibleEvalCall(Expression* expression, Scope* scope);
452 
453   // Determine if the expression is a variable proxy and mark it as being used
454   // in an assignment or with a increment/decrement operator.
455   static Expression* MarkExpressionAsAssigned(Expression* expression);
456 
457   // Returns true if we have a binary expression between two numeric
458   // literals. In that case, *x will be changed to an expression which is the
459   // computed value.
460   bool ShortcutNumericLiteralBinaryExpression(
461       Expression** x, Expression* y, Token::Value op, int pos,
462       AstNodeFactory<AstConstructionVisitor>* factory);
463 
464   // Rewrites the following types of unary expressions:
465   // not <literal> -> true / false
466   // + <numeric literal> -> <numeric literal>
467   // - <numeric literal> -> <numeric literal with value negated>
468   // ! <literal> -> true / false
469   // The following rewriting rules enable the collection of type feedback
470   // without any special stub and the multiplication is removed later in
471   // Crankshaft's canonicalization pass.
472   // + foo -> foo * 1
473   // - foo -> foo * (-1)
474   // ~ foo -> foo ^(~0)
475   Expression* BuildUnaryExpression(
476       Expression* expression, Token::Value op, int pos,
477       AstNodeFactory<AstConstructionVisitor>* factory);
478 
479   // Generate AST node that throws a ReferenceError with the given type.
480   Expression* NewThrowReferenceError(const char* type, int pos);
481 
482   // Generate AST node that throws a SyntaxError with the given
483   // type. The first argument may be null (in the handle sense) in
484   // which case no arguments are passed to the constructor.
485   Expression* NewThrowSyntaxError(
486       const char* type, const AstRawString* arg, int pos);
487 
488   // Generate AST node that throws a TypeError with the given
489   // type. Both arguments must be non-null (in the handle sense).
490   Expression* NewThrowTypeError(const char* type, const AstRawString* arg,
491                                 int pos);
492 
493   // Generic AST generator for throwing errors from compiled code.
494   Expression* NewThrowError(
495       const AstRawString* constructor, const char* type,
496       const AstRawString* arg, int pos);
497 
498   // Reporting errors.
499   void ReportMessageAt(Scanner::Location source_location,
500                        const char* message,
501                        const char* arg = NULL,
502                        bool is_reference_error = false);
503   void ReportMessage(const char* message,
504                      const char* arg = NULL,
505                      bool is_reference_error = false);
506   void ReportMessage(const char* message,
507                      const AstRawString* arg,
508                      bool is_reference_error = false);
509   void ReportMessageAt(Scanner::Location source_location,
510                        const char* message,
511                        const AstRawString* arg,
512                        bool is_reference_error = false);
513 
514   // "null" return type creators.
EmptyIdentifier()515   static const AstRawString* EmptyIdentifier() {
516     return NULL;
517   }
EmptyExpression()518   static Expression* EmptyExpression() {
519     return NULL;
520   }
EmptyArrowParamList()521   static Expression* EmptyArrowParamList() { return NULL; }
EmptyLiteral()522   static Literal* EmptyLiteral() {
523     return NULL;
524   }
EmptyObjectLiteralProperty()525   static ObjectLiteralProperty* EmptyObjectLiteralProperty() { return NULL; }
EmptyFunctionLiteral()526   static FunctionLiteral* EmptyFunctionLiteral() { return NULL; }
527 
528   // Used in error return values.
NullExpressionList()529   static ZoneList<Expression*>* NullExpressionList() {
530     return NULL;
531   }
532 
533   // Non-NULL empty string.
534   V8_INLINE const AstRawString* EmptyIdentifierString();
535 
536   // Odd-ball literal creators.
537   Literal* GetLiteralTheHole(int position,
538                              AstNodeFactory<AstConstructionVisitor>* factory);
539 
540   // Producing data during the recursive descent.
541   const AstRawString* GetSymbol(Scanner* scanner);
542   const AstRawString* GetNextSymbol(Scanner* scanner);
543   const AstRawString* GetNumberAsSymbol(Scanner* scanner);
544 
545   Expression* ThisExpression(Scope* scope,
546                              AstNodeFactory<AstConstructionVisitor>* factory,
547                              int pos = RelocInfo::kNoPosition);
548   Expression* SuperReference(Scope* scope,
549                              AstNodeFactory<AstConstructionVisitor>* factory,
550                              int pos = RelocInfo::kNoPosition);
551   Expression* ClassLiteral(const AstRawString* name, Expression* extends,
552                            Expression* constructor,
553                            ZoneList<ObjectLiteral::Property*>* properties,
554                            int pos,
555                            AstNodeFactory<AstConstructionVisitor>* factory);
556 
557   Literal* ExpressionFromLiteral(
558       Token::Value token, int pos, Scanner* scanner,
559       AstNodeFactory<AstConstructionVisitor>* factory);
560   Expression* ExpressionFromIdentifier(
561       const AstRawString* name, int pos, Scope* scope,
562       AstNodeFactory<AstConstructionVisitor>* factory);
563   Expression* ExpressionFromString(
564       int pos, Scanner* scanner,
565       AstNodeFactory<AstConstructionVisitor>* factory);
566   Expression* GetIterator(Expression* iterable,
567                           AstNodeFactory<AstConstructionVisitor>* factory);
NewExpressionList(int size,Zone * zone)568   ZoneList<v8::internal::Expression*>* NewExpressionList(int size, Zone* zone) {
569     return new(zone) ZoneList<v8::internal::Expression*>(size, zone);
570   }
NewPropertyList(int size,Zone * zone)571   ZoneList<ObjectLiteral::Property*>* NewPropertyList(int size, Zone* zone) {
572     return new(zone) ZoneList<ObjectLiteral::Property*>(size, zone);
573   }
NewStatementList(int size,Zone * zone)574   ZoneList<v8::internal::Statement*>* NewStatementList(int size, Zone* zone) {
575     return new(zone) ZoneList<v8::internal::Statement*>(size, zone);
576   }
577   V8_INLINE Scope* NewScope(Scope* parent_scope, ScopeType scope_type);
578 
579   // Utility functions
580   int DeclareArrowParametersFromExpression(Expression* expression, Scope* scope,
581                                            Scanner::Location* dupe_loc,
582                                            bool* ok);
583   V8_INLINE AstValueFactory* ast_value_factory();
584 
585   // Temporary glue; these functions will move to ParserBase.
586   Expression* ParseV8Intrinsic(bool* ok);
587   FunctionLiteral* ParseFunctionLiteral(
588       const AstRawString* name, Scanner::Location function_name_location,
589       bool name_is_strict_reserved, FunctionKind kind,
590       int function_token_position, FunctionLiteral::FunctionType type,
591       FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
592   V8_INLINE void SkipLazyFunctionBody(const AstRawString* name,
593                                       int* materialized_literal_count,
594                                       int* expected_property_count, bool* ok);
595   V8_INLINE ZoneList<Statement*>* ParseEagerFunctionBody(
596       const AstRawString* name, int pos, Variable* fvar,
597       Token::Value fvar_init_op, bool is_generator, bool* ok);
598   V8_INLINE void CheckConflictingVarDeclarations(v8::internal::Scope* scope,
599                                                  bool* ok);
600 
601  private:
602   Parser* parser_;
603 };
604 
605 
606 class Parser : public ParserBase<ParserTraits> {
607  public:
608   // Note that the hash seed in ParseInfo must be the hash seed from the
609   // Isolate's heap, otherwise the heap will be in an inconsistent state once
610   // the strings created by the Parser are internalized.
611   struct ParseInfo {
612     uintptr_t stack_limit;
613     uint32_t hash_seed;
614     UnicodeCache* unicode_cache;
615   };
616 
617   Parser(CompilationInfo* info, ParseInfo* parse_info);
~Parser()618   ~Parser() {
619     delete reusable_preparser_;
620     reusable_preparser_ = NULL;
621     delete cached_parse_data_;
622     cached_parse_data_ = NULL;
623   }
624 
625   // Parses the source code represented by the compilation info and sets its
626   // function literal.  Returns false (and deallocates any allocated AST
627   // nodes) if parsing failed.
628   static bool Parse(CompilationInfo* info,
629                     bool allow_lazy = false) {
630     ParseInfo parse_info = {info->isolate()->stack_guard()->real_climit(),
631                             info->isolate()->heap()->HashSeed(),
632                             info->isolate()->unicode_cache()};
633     Parser parser(info, &parse_info);
634     parser.set_allow_lazy(allow_lazy);
635     if (parser.Parse()) {
636       info->SetStrictMode(info->function()->strict_mode());
637       return true;
638     }
639     return false;
640   }
641   bool Parse();
642   void ParseOnBackground();
643 
644   // Handle errors detected during parsing, move statistics to Isolate,
645   // internalize strings (move them to the heap).
646   void Internalize();
647 
648  private:
649   friend class ParserTraits;
650 
651   // Limit the allowed number of local variables in a function. The hard limit
652   // is that offsets computed by FullCodeGenerator::StackOperand and similar
653   // functions are ints, and they should not overflow. In addition, accessing
654   // local variables creates user-controlled constants in the generated code,
655   // and we don't want too much user-controlled memory inside the code (this was
656   // the reason why this limit was introduced in the first place; see
657   // https://codereview.chromium.org/7003030/ ).
658   static const int kMaxNumFunctionLocals = 4194303;  // 2^22-1
659 
660   enum VariableDeclarationContext {
661     kModuleElement,
662     kBlockElement,
663     kStatement,
664     kForStatement
665   };
666 
667   // If a list of variable declarations includes any initializers.
668   enum VariableDeclarationProperties {
669     kHasInitializers,
670     kHasNoInitializers
671   };
672 
673   // Returns NULL if parsing failed.
674   FunctionLiteral* ParseProgram();
675 
676   FunctionLiteral* ParseLazy();
677   FunctionLiteral* ParseLazy(Utf16CharacterStream* source);
678 
isolate()679   Isolate* isolate() { return info_->isolate(); }
info()680   CompilationInfo* info() const { return info_; }
script()681   Handle<Script> script() const { return info_->script(); }
ast_value_factory()682   AstValueFactory* ast_value_factory() const {
683     return info_->ast_value_factory();
684   }
685 
686   // Called by ParseProgram after setting up the scanner.
687   FunctionLiteral* DoParseProgram(CompilationInfo* info, Scope** scope,
688                                   Scope** ad_hoc_eval_scope);
689 
690   void SetCachedData();
691 
inside_with()692   bool inside_with() const { return scope_->inside_with(); }
compile_options()693   ScriptCompiler::CompileOptions compile_options() const {
694     return info_->compile_options();
695   }
DeclarationScope(VariableMode mode)696   Scope* DeclarationScope(VariableMode mode) {
697     return IsLexicalVariableMode(mode)
698         ? scope_ : scope_->DeclarationScope();
699   }
700 
701   // All ParseXXX functions take as the last argument an *ok parameter
702   // which is set to false if parsing failed; it is unchanged otherwise.
703   // By making the 'exception handling' explicit, we are forced to check
704   // for failure at the call sites.
705   void* ParseSourceElements(ZoneList<Statement*>* processor, int end_token,
706                             bool is_eval, bool is_global,
707                             Scope** ad_hoc_eval_scope, bool* ok);
708   Statement* ParseModuleElement(ZoneList<const AstRawString*>* labels,
709                                 bool* ok);
710   Statement* ParseModuleDeclaration(ZoneList<const AstRawString*>* names,
711                                     bool* ok);
712   Module* ParseModule(bool* ok);
713   Module* ParseModuleLiteral(bool* ok);
714   Module* ParseModulePath(bool* ok);
715   Module* ParseModuleVariable(bool* ok);
716   Module* ParseModuleUrl(bool* ok);
717   Module* ParseModuleSpecifier(bool* ok);
718   Block* ParseImportDeclaration(bool* ok);
719   Statement* ParseExportDeclaration(bool* ok);
720   Statement* ParseBlockElement(ZoneList<const AstRawString*>* labels, bool* ok);
721   Statement* ParseStatement(ZoneList<const AstRawString*>* labels, bool* ok);
722   Statement* ParseFunctionDeclaration(ZoneList<const AstRawString*>* names,
723                                       bool* ok);
724   Statement* ParseClassDeclaration(ZoneList<const AstRawString*>* names,
725                                    bool* ok);
726   Statement* ParseNativeDeclaration(bool* ok);
727   Block* ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok);
728   Block* ParseVariableStatement(VariableDeclarationContext var_context,
729                                 ZoneList<const AstRawString*>* names,
730                                 bool* ok);
731   Block* ParseVariableDeclarations(VariableDeclarationContext var_context,
732                                    VariableDeclarationProperties* decl_props,
733                                    ZoneList<const AstRawString*>* names,
734                                    const AstRawString** out,
735                                    bool* ok);
736   Statement* ParseExpressionOrLabelledStatement(
737       ZoneList<const AstRawString*>* labels, bool* ok);
738   IfStatement* ParseIfStatement(ZoneList<const AstRawString*>* labels,
739                                 bool* ok);
740   Statement* ParseContinueStatement(bool* ok);
741   Statement* ParseBreakStatement(ZoneList<const AstRawString*>* labels,
742                                  bool* ok);
743   Statement* ParseReturnStatement(bool* ok);
744   Statement* ParseWithStatement(ZoneList<const AstRawString*>* labels,
745                                 bool* ok);
746   CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
747   SwitchStatement* ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
748                                         bool* ok);
749   DoWhileStatement* ParseDoWhileStatement(ZoneList<const AstRawString*>* labels,
750                                           bool* ok);
751   WhileStatement* ParseWhileStatement(ZoneList<const AstRawString*>* labels,
752                                       bool* ok);
753   Statement* ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok);
754   Statement* ParseThrowStatement(bool* ok);
755   Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
756   TryStatement* ParseTryStatement(bool* ok);
757   DebuggerStatement* ParseDebuggerStatement(bool* ok);
758 
759   // Support for hamony block scoped bindings.
760   Block* ParseScopedBlock(ZoneList<const AstRawString*>* labels, bool* ok);
761 
762   // Initialize the components of a for-in / for-of statement.
763   void InitializeForEachStatement(ForEachStatement* stmt,
764                                   Expression* each,
765                                   Expression* subject,
766                                   Statement* body);
767   Statement* DesugarLetBindingsInForStatement(
768       Scope* inner_scope, ZoneList<const AstRawString*>* names,
769       ForStatement* loop, Statement* init, Expression* cond, Statement* next,
770       Statement* body, bool* ok);
771 
772   FunctionLiteral* ParseFunctionLiteral(
773       const AstRawString* name, Scanner::Location function_name_location,
774       bool name_is_strict_reserved, FunctionKind kind,
775       int function_token_position, FunctionLiteral::FunctionType type,
776       FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
777 
778   // Magical syntax support.
779   Expression* ParseV8Intrinsic(bool* ok);
780 
781   bool CheckInOrOf(bool accept_OF, ForEachStatement::VisitMode* visit_mode);
782 
783   // Get odd-ball literals.
784   Literal* GetLiteralUndefined(int position);
785 
786   // For harmony block scoping mode: Check if the scope has conflicting var/let
787   // declarations from different scopes. It covers for example
788   //
789   // function f() { { { var x; } let x; } }
790   // function g() { { var x; let x; } }
791   //
792   // The var declarations are hoisted to the function scope, but originate from
793   // a scope where the name has also been let bound or the var declaration is
794   // hoisted over such a scope.
795   void CheckConflictingVarDeclarations(Scope* scope, bool* ok);
796 
797   // Parser support
798   VariableProxy* NewUnresolved(const AstRawString* name,
799                                VariableMode mode,
800                                Interface* interface);
801   void Declare(Declaration* declaration, bool resolve, bool* ok);
802 
803   bool TargetStackContainsLabel(const AstRawString* label);
804   BreakableStatement* LookupBreakTarget(const AstRawString* label, bool* ok);
805   IterationStatement* LookupContinueTarget(const AstRawString* label, bool* ok);
806 
807   void RegisterTargetUse(Label* target, Target* stop);
808 
809   // Factory methods.
810 
811   Scope* NewScope(Scope* parent, ScopeType type);
812 
813   // Skip over a lazy function, either using cached data if we have it, or
814   // by parsing the function with PreParser. Consumes the ending }.
815   void SkipLazyFunctionBody(const AstRawString* function_name,
816                             int* materialized_literal_count,
817                             int* expected_property_count,
818                             bool* ok);
819 
820   PreParser::PreParseResult ParseLazyFunctionBodyWithPreParser(
821       SingletonLogger* logger);
822 
823   // Consumes the ending }.
824   ZoneList<Statement*>* ParseEagerFunctionBody(
825       const AstRawString* function_name, int pos, Variable* fvar,
826       Token::Value fvar_init_op, bool is_generator, bool* ok);
827 
828   void HandleSourceURLComments();
829 
830   void ThrowPendingError();
831 
832   Scanner scanner_;
833   PreParser* reusable_preparser_;
834   Scope* original_scope_;  // for ES5 function declarations in sloppy eval
835   Target* target_stack_;  // for break, continue statements
836   ParseData* cached_parse_data_;
837 
838   CompilationInfo* info_;
839 
840   // Pending errors.
841   bool has_pending_error_;
842   Scanner::Location pending_error_location_;
843   const char* pending_error_message_;
844   const AstRawString* pending_error_arg_;
845   const char* pending_error_char_arg_;
846   bool pending_error_is_reference_error_;
847 
848   // Other information which will be stored in Parser and moved to Isolate after
849   // parsing.
850   int use_counts_[v8::Isolate::kUseCounterFeatureCount];
851   int total_preparse_skipped_;
852   HistogramTimer* pre_parse_timer_;
853 };
854 
855 
IsFutureStrictReserved(const AstRawString * identifier)856 bool ParserTraits::IsFutureStrictReserved(
857     const AstRawString* identifier) const {
858   return identifier->IsOneByteEqualTo("yield") ||
859          parser_->scanner()->IdentifierIsFutureStrictReserved(identifier);
860 }
861 
862 
NewScope(Scope * parent_scope,ScopeType scope_type)863 Scope* ParserTraits::NewScope(Scope* parent_scope, ScopeType scope_type) {
864   return parser_->NewScope(parent_scope, scope_type);
865 }
866 
867 
EmptyIdentifierString()868 const AstRawString* ParserTraits::EmptyIdentifierString() {
869   return parser_->ast_value_factory()->empty_string();
870 }
871 
872 
SkipLazyFunctionBody(const AstRawString * function_name,int * materialized_literal_count,int * expected_property_count,bool * ok)873 void ParserTraits::SkipLazyFunctionBody(const AstRawString* function_name,
874                                         int* materialized_literal_count,
875                                         int* expected_property_count,
876                                         bool* ok) {
877   return parser_->SkipLazyFunctionBody(
878       function_name, materialized_literal_count, expected_property_count, ok);
879 }
880 
881 
ParseEagerFunctionBody(const AstRawString * name,int pos,Variable * fvar,Token::Value fvar_init_op,bool is_generator,bool * ok)882 ZoneList<Statement*>* ParserTraits::ParseEagerFunctionBody(
883     const AstRawString* name, int pos, Variable* fvar,
884     Token::Value fvar_init_op, bool is_generator, bool* ok) {
885   return parser_->ParseEagerFunctionBody(name, pos, fvar, fvar_init_op,
886                                          is_generator, ok);
887 }
888 
CheckConflictingVarDeclarations(v8::internal::Scope * scope,bool * ok)889 void ParserTraits::CheckConflictingVarDeclarations(v8::internal::Scope* scope,
890                                                    bool* ok) {
891   parser_->CheckConflictingVarDeclarations(scope, ok);
892 }
893 
894 
ast_value_factory()895 AstValueFactory* ParserTraits::ast_value_factory() {
896   return parser_->ast_value_factory();
897 }
898 
899 
900 // Support for handling complex values (array and object literals) that
901 // can be fully handled at compile time.
902 class CompileTimeValue: public AllStatic {
903  public:
904   enum LiteralType {
905     OBJECT_LITERAL_FAST_ELEMENTS,
906     OBJECT_LITERAL_SLOW_ELEMENTS,
907     ARRAY_LITERAL
908   };
909 
910   static bool IsCompileTimeValue(Expression* expression);
911 
912   // Get the value as a compile time value.
913   static Handle<FixedArray> GetValue(Isolate* isolate, Expression* expression);
914 
915   // Get the type of a compile time value returned by GetValue().
916   static LiteralType GetLiteralType(Handle<FixedArray> value);
917 
918   // Get the elements array of a compile time value returned by GetValue().
919   static Handle<FixedArray> GetElements(Handle<FixedArray> value);
920 
921  private:
922   static const int kLiteralTypeSlot = 0;
923   static const int kElementsSlot = 1;
924 
925   DISALLOW_IMPLICIT_CONSTRUCTORS(CompileTimeValue);
926 };
927 
928 } }  // namespace v8::internal
929 
930 #endif  // V8_PARSER_H_
931