Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(336)

Side by Side Diff: src/parsing/expression-classifier.h

Issue 2289663002: [parser] Hide expression classifiers in parser implementation (Closed)
Patch Set: Rebase Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/parsing/parser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_PARSING_EXPRESSION_CLASSIFIER_H 5 #ifndef V8_PARSING_EXPRESSION_CLASSIFIER_H
6 #define V8_PARSING_EXPRESSION_CLASSIFIER_H 6 #define V8_PARSING_EXPRESSION_CLASSIFIER_H
7 7
8 #include "src/messages.h" 8 #include "src/messages.h"
9 #include "src/parsing/scanner.h" 9 #include "src/parsing/scanner.h"
10 #include "src/parsing/token.h"
11 10
12 namespace v8 { 11 namespace v8 {
13 namespace internal { 12 namespace internal {
14 13
15 class DuplicateFinder; 14 class DuplicateFinder;
16 15
17 #define ERROR_CODES(T) \ 16 #define ERROR_CODES(T) \
18 T(ExpressionProduction, 0) \ 17 T(ExpressionProduction, 0) \
19 T(FormalParameterInitializerProduction, 1) \ 18 T(FormalParameterInitializerProduction, 1) \
20 T(BindingPatternProduction, 2) \ 19 T(BindingPatternProduction, 2) \
21 T(AssignmentPatternProduction, 3) \ 20 T(AssignmentPatternProduction, 3) \
22 T(DistinctFormalParametersProduction, 4) \ 21 T(DistinctFormalParametersProduction, 4) \
23 T(StrictModeFormalParametersProduction, 5) \ 22 T(StrictModeFormalParametersProduction, 5) \
24 T(ArrowFormalParametersProduction, 6) \ 23 T(ArrowFormalParametersProduction, 6) \
25 T(LetPatternProduction, 7) \ 24 T(LetPatternProduction, 7) \
26 T(TailCallExpressionProduction, 8) \ 25 T(TailCallExpressionProduction, 8) \
27 T(AsyncArrowFormalParametersProduction, 9) 26 T(AsyncArrowFormalParametersProduction, 9)
28 27
28 // Expression classifiers serve two purposes:
29 //
30 // 1) They keep track of error messages that are pending (and other
31 // related information), waiting for the parser to decide whether
32 // the parsed expression is a pattern or not.
33 // 2) They keep track of expressions that may need to be rewritten, if
34 // the parser decides that they are not patterns. (A different
35 // mechanism implements the rewriting of patterns.)
36 //
37 // Expression classifiers are used by the parser in a stack fashion.
38 // Each new classifier is pushed on top of the stack. This happens
39 // automatically by the class's constructor. While on top of the
40 // stack, the classifier records pending error messages and tracks the
41 // pending non-patterns of the expression that is being parsed.
42 //
43 // At the end of its life, a classifier is either "accumulated" to the
44 // one that is below it on the stack, or is "discarded". The former
45 // is achieved by calling the method Accumulate. The latter is
46 // achieved automatically by the destructor, but it can happen earlier
47 // by calling the method Discard. Both actions result in removing the
48 // classifier from the parser's stack.
49
29 template <typename Types> 50 template <typename Types>
30 class ExpressionClassifier { 51 class ExpressionClassifier {
31 public: 52 public:
32 enum ErrorKind : unsigned { 53 enum ErrorKind : unsigned {
33 #define DEFINE_ERROR_KIND(NAME, CODE) k##NAME = CODE, 54 #define DEFINE_ERROR_KIND(NAME, CODE) k##NAME = CODE,
34 ERROR_CODES(DEFINE_ERROR_KIND) 55 ERROR_CODES(DEFINE_ERROR_KIND)
35 #undef DEFINE_ERROR_KIND 56 #undef DEFINE_ERROR_KIND
36 kUnusedError = 15 // Larger than error codes; should fit in 4 bits 57 kUnusedError = 15 // Larger than error codes; should fit in 4 bits
37 }; 58 };
38 59
(...skipping 26 matching lines...) Expand all
65 #define DEFINE_ALL_PRODUCTIONS(NAME, CODE) NAME | 86 #define DEFINE_ALL_PRODUCTIONS(NAME, CODE) NAME |
66 AllProductions = ERROR_CODES(DEFINE_ALL_PRODUCTIONS) /* | */ 0 87 AllProductions = ERROR_CODES(DEFINE_ALL_PRODUCTIONS) /* | */ 0
67 #undef DEFINE_ALL_PRODUCTIONS 88 #undef DEFINE_ALL_PRODUCTIONS
68 }; 89 };
69 // clang-format on 90 // clang-format on
70 91
71 enum FunctionProperties : unsigned { 92 enum FunctionProperties : unsigned {
72 NonSimpleParameter = 1 << 0 93 NonSimpleParameter = 1 << 0
73 }; 94 };
74 95
75 explicit ExpressionClassifier(const typename Types::Base* base, 96 explicit ExpressionClassifier(typename Types::Base* base,
76 DuplicateFinder* duplicate_finder = nullptr) 97 DuplicateFinder* duplicate_finder = nullptr)
77 : zone_(base->impl()->zone()), 98 : base_(base),
99 previous_(base->classifier_),
100 zone_(base->impl()->zone()),
78 non_patterns_to_rewrite_(base->impl()->GetNonPatternList()), 101 non_patterns_to_rewrite_(base->impl()->GetNonPatternList()),
79 reported_errors_(base->impl()->GetReportedErrorList()), 102 reported_errors_(base->impl()->GetReportedErrorList()),
80 duplicate_finder_(duplicate_finder), 103 duplicate_finder_(duplicate_finder),
81 invalid_productions_(0), 104 invalid_productions_(0),
82 function_properties_(0) { 105 function_properties_(0) {
106 base->classifier_ = this;
83 reported_errors_begin_ = reported_errors_end_ = reported_errors_->length(); 107 reported_errors_begin_ = reported_errors_end_ = reported_errors_->length();
84 non_pattern_begin_ = non_patterns_to_rewrite_->length(); 108 non_pattern_begin_ = non_patterns_to_rewrite_->length();
85 } 109 }
86 110
87 ~ExpressionClassifier() { Discard(); } 111 V8_INLINE ~ExpressionClassifier() {
112 Discard();
113 if (base_->classifier_ == this) base_->classifier_ = previous_;
114 }
88 115
89 V8_INLINE bool is_valid(unsigned productions) const { 116 V8_INLINE bool is_valid(unsigned productions) const {
90 return (invalid_productions_ & productions) == 0; 117 return (invalid_productions_ & productions) == 0;
91 } 118 }
92 119
93 V8_INLINE DuplicateFinder* duplicate_finder() const { 120 V8_INLINE DuplicateFinder* duplicate_finder() const {
94 return duplicate_finder_; 121 return duplicate_finder_;
95 } 122 }
96 123
97 V8_INLINE bool is_valid_expression() const { 124 V8_INLINE bool is_valid_expression() const {
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 reported_errors_->at(reported_errors_end_-1).kind = 377 reported_errors_->at(reported_errors_end_-1).kind =
351 kArrowFormalParametersProduction; 378 kArrowFormalParametersProduction;
352 } 379 }
353 } 380 }
354 } 381 }
355 reported_errors_->Rewind(reported_errors_end_); 382 reported_errors_->Rewind(reported_errors_end_);
356 inner->reported_errors_begin_ = inner->reported_errors_end_ = 383 inner->reported_errors_begin_ = inner->reported_errors_end_ =
357 reported_errors_end_; 384 reported_errors_end_;
358 } 385 }
359 386
360 // Accumulate errors that can be arbitrarily deep in an expression.
361 // These correspond to the ECMAScript spec's 'Contains' operation
362 // on productions. This includes:
363 //
364 // - YieldExpression is disallowed in arrow parameters in a generator.
365 // - AwaitExpression is disallowed in arrow parameters in an async function.
366 // - AwaitExpression is disallowed in async arrow parameters.
367 //
368 V8_INLINE void AccumulateFormalParameterContainmentErrors(
369 ExpressionClassifier* inner) {
370 Accumulate(inner, FormalParameterInitializerProduction |
371 AsyncArrowFormalParametersProduction);
372 }
373
374 V8_INLINE int GetNonPatternBegin() const { return non_pattern_begin_; } 387 V8_INLINE int GetNonPatternBegin() const { return non_pattern_begin_; }
375 388
376 V8_INLINE void Discard() { 389 V8_INLINE void Discard() {
377 if (reported_errors_end_ == reported_errors_->length()) { 390 if (reported_errors_end_ == reported_errors_->length()) {
378 reported_errors_->Rewind(reported_errors_begin_); 391 reported_errors_->Rewind(reported_errors_begin_);
379 reported_errors_end_ = reported_errors_begin_; 392 reported_errors_end_ = reported_errors_begin_;
380 } 393 }
381 DCHECK_EQ(reported_errors_begin_, reported_errors_end_); 394 DCHECK_EQ(reported_errors_begin_, reported_errors_end_);
382 DCHECK_LE(non_pattern_begin_, non_patterns_to_rewrite_->length()); 395 DCHECK_LE(non_pattern_begin_, non_patterns_to_rewrite_->length());
383 non_patterns_to_rewrite_->Rewind(non_pattern_begin_); 396 non_patterns_to_rewrite_->Rewind(non_pattern_begin_);
384 } 397 }
385 398
399 ExpressionClassifier* previous() const { return previous_; }
400
386 private: 401 private:
387 V8_INLINE const Error& reported_error(ErrorKind kind) const { 402 V8_INLINE const Error& reported_error(ErrorKind kind) const {
388 if (invalid_productions_ & (1 << kind)) { 403 if (invalid_productions_ & (1 << kind)) {
389 for (int i = reported_errors_begin_; i < reported_errors_end_; i++) { 404 for (int i = reported_errors_begin_; i < reported_errors_end_; i++) {
390 if (reported_errors_->at(i).kind == kind) 405 if (reported_errors_->at(i).kind == kind)
391 return reported_errors_->at(i); 406 return reported_errors_->at(i);
392 } 407 }
393 UNREACHABLE(); 408 UNREACHABLE();
394 } 409 }
395 // We should only be looking for an error when we know that one has 410 // We should only be looking for an error when we know that one has
(...skipping 16 matching lines...) Expand all
412 // could be either after the existing errors of this classifier (i.e., 427 // could be either after the existing errors of this classifier (i.e.,
413 // in an inner classifier) or it could be an existing error (in case a 428 // in an inner classifier) or it could be an existing error (in case a
414 // copy is needed). 429 // copy is needed).
415 V8_INLINE void Copy(int i) { 430 V8_INLINE void Copy(int i) {
416 DCHECK_LT(i, reported_errors_->length()); 431 DCHECK_LT(i, reported_errors_->length());
417 if (reported_errors_end_ != i) 432 if (reported_errors_end_ != i)
418 reported_errors_->at(reported_errors_end_) = reported_errors_->at(i); 433 reported_errors_->at(reported_errors_end_) = reported_errors_->at(i);
419 reported_errors_end_++; 434 reported_errors_end_++;
420 } 435 }
421 436
437 typename Types::Base* base_;
438 ExpressionClassifier* previous_;
422 Zone* zone_; 439 Zone* zone_;
423 ZoneList<typename Types::Expression>* non_patterns_to_rewrite_; 440 ZoneList<typename Types::Expression>* non_patterns_to_rewrite_;
424 ZoneList<Error>* reported_errors_; 441 ZoneList<Error>* reported_errors_;
425 DuplicateFinder* duplicate_finder_; 442 DuplicateFinder* duplicate_finder_;
426 // The uint16_t for non_pattern_begin_ will not be enough in the case, 443 // The uint16_t for non_pattern_begin_ will not be enough in the case,
427 // e.g., of an array literal containing more than 64K inner array 444 // e.g., of an array literal containing more than 64K inner array
428 // literals with spreads, as in: 445 // literals with spreads, as in:
429 // var N=65536; eval("var x=[];" + "[" + "[...x],".repeat(N) + "].length"); 446 // var N=65536; eval("var x=[];" + "[" + "[...x],".repeat(N) + "].length");
430 // An implementation limit error in ParserBase::AddNonPatternForRewriting 447 // An implementation limit error in ParserBase::AddNonPatternForRewriting
431 // will be triggered in this case. 448 // will be triggered in this case.
432 uint16_t non_pattern_begin_; 449 uint16_t non_pattern_begin_;
433 unsigned invalid_productions_ : 14; 450 unsigned invalid_productions_ : 14;
434 unsigned function_properties_ : 2; 451 unsigned function_properties_ : 2;
435 // The uint16_t for reported_errors_begin_ and reported_errors_end_ will 452 // The uint16_t for reported_errors_begin_ and reported_errors_end_ will
436 // not be enough in the case of a long series of expressions using nested 453 // not be enough in the case of a long series of expressions using nested
437 // classifiers, e.g., a long sequence of assignments, as in: 454 // classifiers, e.g., a long sequence of assignments, as in:
438 // literals with spreads, as in: 455 // literals with spreads, as in:
439 // var N=65536; eval("var x;" + "x=".repeat(N) + "42"); 456 // var N=65536; eval("var x;" + "x=".repeat(N) + "42");
440 // This should not be a problem, as such things currently fail with a 457 // This should not be a problem, as such things currently fail with a
441 // stack overflow while parsing. 458 // stack overflow while parsing.
442 uint16_t reported_errors_begin_; 459 uint16_t reported_errors_begin_;
443 uint16_t reported_errors_end_; 460 uint16_t reported_errors_end_;
461
462 DISALLOW_COPY_AND_ASSIGN(ExpressionClassifier);
444 }; 463 };
445 464
446 465
447 #undef ERROR_CODES 466 #undef ERROR_CODES
448 467
449 468
450 } // namespace internal 469 } // namespace internal
451 } // namespace v8 470 } // namespace v8
452 471
453 #endif // V8_PARSING_EXPRESSION_CLASSIFIER_H 472 #endif // V8_PARSING_EXPRESSION_CLASSIFIER_H
OLDNEW
« no previous file with comments | « no previous file | src/parsing/parser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698