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