Fix lazy compilation of eval() under nosnap/--use-strict
authoradamk <adamk@chromium.org>
Thu, 9 Jul 2015 21:31:11 +0000 (14:31 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 9 Jul 2015 21:31:18 +0000 (21:31 +0000)
When running without a snapshot, the GlobalEval function gets lazy compiled.
By the time we compile it, its name is "eval", which causes the parser to
choke (functions named "eval" aren't allowed in strict mode!).

Instead, we now always skip checking the function name when lazy-parsing,
as the name has already been checked appropriately by the preparser.

Also cleaned up other cases that don't require name checking by introducing
FunctionNameValidity enum and passing appropriate values throughout the
parser and preparser.

This lets us pass an additional 18 test262 tests.

BUG=v8:4198
LOG=n

Review URL: https://codereview.chromium.org/1227093005

Cr-Commit-Position: refs/heads/master@{#29559}

src/parser.cc
src/parser.h
src/preparser.cc
src/preparser.h
test/test262-es6/test262-es6.status

index 7533911..a45a4b1 100644 (file)
@@ -871,11 +871,11 @@ Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
 
 FunctionLiteral* ParserTraits::ParseFunctionLiteral(
     const AstRawString* name, Scanner::Location function_name_location,
-    bool name_is_strict_reserved, FunctionKind kind,
+    FunctionNameValidity function_name_validity, FunctionKind kind,
     int function_token_position, FunctionLiteral::FunctionType type,
     FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
   return parser_->ParseFunctionLiteral(
-      name, function_name_location, name_is_strict_reserved, kind,
+      name, function_name_location, function_name_validity, kind,
       function_token_position, type, arity_restriction, ok);
 }
 
@@ -1227,9 +1227,8 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
                                   shared_info->end_position());
     } else {
       result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
-                                    false,  // Strict mode name already checked.
-                                    shared_info->kind(), RelocInfo::kNoPosition,
-                                    function_type,
+                                    kSkipFunctionNameCheck, shared_info->kind(),
+                                    RelocInfo::kNoPosition, function_type,
                                     FunctionLiteral::NORMAL_ARITY, &ok);
     }
     // Make sure the results agree.
@@ -2194,7 +2193,9 @@ Statement* Parser::ParseFunctionDeclaration(
   const AstRawString* name = ParseIdentifierOrStrictReservedWord(
       &is_strict_reserved, CHECK_OK);
   FunctionLiteral* fun =
-      ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
+      ParseFunctionLiteral(name, scanner()->location(),
+                           is_strict_reserved ? kFunctionNameIsStrictReserved
+                                              : kFunctionNameValidityUnknown,
                            is_generator ? FunctionKind::kGeneratorFunction
                                         : FunctionKind::kNormalFunction,
                            pos, FunctionLiteral::DECLARATION,
@@ -3914,8 +3915,8 @@ void ParserTraits::ReindexLiterals(
 
 FunctionLiteral* Parser::ParseFunctionLiteral(
     const AstRawString* function_name, Scanner::Location function_name_location,
-    bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
-    FunctionLiteral::FunctionType function_type,
+    FunctionNameValidity function_name_validity, FunctionKind kind,
+    int function_token_pos, FunctionLiteral::FunctionType function_type,
     FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
   // Function ::
   //   '(' FormalParameterList? ')' '{' FunctionBody '}'
@@ -4128,9 +4129,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
 
     // Validate name and parameter names. We can do this only after parsing the
     // function, since the function can declare itself strict.
-    CheckFunctionName(language_mode(), kind, function_name,
-                      name_is_strict_reserved, function_name_location,
-                      CHECK_OK);
+    CheckFunctionName(language_mode(), function_name, function_name_validity,
+                      function_name_location, CHECK_OK);
     const bool use_strict_params =
         !parsing_state.is_simple_parameter_list || IsConciseMethod(kind);
     const bool allow_duplicate_parameters =
index 1dd19d9..acad434 100644 (file)
@@ -794,7 +794,7 @@ class ParserTraits {
   Expression* ParseV8Intrinsic(bool* ok);
   FunctionLiteral* ParseFunctionLiteral(
       const AstRawString* name, Scanner::Location function_name_location,
-      bool name_is_strict_reserved, FunctionKind kind,
+      FunctionNameValidity function_name_validity, FunctionKind kind,
       int function_token_position, FunctionLiteral::FunctionType type,
       FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
   V8_INLINE void SkipLazyFunctionBody(
@@ -1096,7 +1096,7 @@ class Parser : public ParserBase<ParserTraits> {
 
   FunctionLiteral* ParseFunctionLiteral(
       const AstRawString* name, Scanner::Location function_name_location,
-      bool name_is_strict_reserved, FunctionKind kind,
+      FunctionNameValidity function_name_validity, FunctionKind kind,
       int function_token_position, FunctionLiteral::FunctionType type,
       FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
 
index abf28c1..c7a19bc 100644 (file)
@@ -91,11 +91,11 @@ PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
 
 PreParserExpression PreParserTraits::ParseFunctionLiteral(
     PreParserIdentifier name, Scanner::Location function_name_location,
-    bool name_is_strict_reserved, FunctionKind kind,
+    FunctionNameValidity function_name_validity, FunctionKind kind,
     int function_token_position, FunctionLiteral::FunctionType type,
     FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
   return pre_parser_->ParseFunctionLiteral(
-      name, function_name_location, name_is_strict_reserved, kind,
+      name, function_name_location, function_name_validity, kind,
       function_token_position, type, arity_restriction, ok);
 }
 
@@ -419,7 +419,9 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
   bool is_strict_reserved = false;
   Identifier name = ParseIdentifierOrStrictReservedWord(
       &is_strict_reserved, CHECK_OK);
-  ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
+  ParseFunctionLiteral(name, scanner()->location(),
+                       is_strict_reserved ? kFunctionNameIsStrictReserved
+                                          : kFunctionNameValidityUnknown,
                        is_generator ? FunctionKind::kGeneratorFunction
                                     : FunctionKind::kNormalFunction,
                        pos, FunctionLiteral::DECLARATION,
@@ -1028,8 +1030,8 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
 
 PreParser::Expression PreParser::ParseFunctionLiteral(
     Identifier function_name, Scanner::Location function_name_location,
-    bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
-    FunctionLiteral::FunctionType function_type,
+    FunctionNameValidity function_name_validity, FunctionKind kind,
+    int function_token_pos, FunctionLiteral::FunctionType function_type,
     FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
   // Function ::
   //   '(' FormalParameterList? ')' '{' FunctionBody '}'
@@ -1072,8 +1074,8 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
 
   // Validate name and parameter names. We can do this only after parsing the
   // function, since the function can declare itself strict.
-  CheckFunctionName(language_mode(), kind, function_name,
-                    name_is_strict_reserved, function_name_location, CHECK_OK);
+  CheckFunctionName(language_mode(), function_name, function_name_validity,
+                    function_name_location, CHECK_OK);
   const bool strict_formal_parameters =
       !parsing_state.is_simple_parameter_list || IsConciseMethod(kind);
   const bool allow_duplicate_parameters =
index aa86664..cff443a 100644 (file)
 namespace v8 {
 namespace internal {
 
+
+enum FunctionNameValidity {
+  kFunctionNameIsStrictReserved,
+  kSkipFunctionNameCheck,
+  kFunctionNameValidityUnknown
+};
+
+
 // Common base class shared between parser and pre-parser. Traits encapsulate
 // the differences between Parser and PreParser:
 
@@ -449,13 +457,10 @@ class ParserBase : public Traits {
 
   // Checking the name of a function literal. This has to be done after parsing
   // the function, since the function can declare itself strict.
-  void CheckFunctionName(LanguageMode language_mode, FunctionKind kind,
-                         IdentifierT function_name,
-                         bool function_name_is_strict_reserved,
-                         const Scanner::Location& function_name_loc,
-                         bool* ok) {
-    // Property names are never checked.
-    if (IsConciseMethod(kind) || IsAccessorFunction(kind)) return;
+  void CheckFunctionName(LanguageMode language_mode, IdentifierT function_name,
+                         FunctionNameValidity function_name_validity,
+                         const Scanner::Location& function_name_loc, bool* ok) {
+    if (function_name_validity == kSkipFunctionNameCheck) return;
     // The function name needs to be checked in strict mode.
     if (is_sloppy(language_mode)) return;
 
@@ -465,7 +470,7 @@ class ParserBase : public Traits {
       *ok = false;
       return;
     }
-    if (function_name_is_strict_reserved) {
+    if (function_name_validity == kFunctionNameIsStrictReserved) {
       Traits::ReportMessageAt(function_name_loc,
                               MessageTemplate::kUnexpectedStrictReserved);
       *ok = false;
@@ -1620,7 +1625,7 @@ class PreParserTraits {
   PreParserExpression ParseV8Intrinsic(bool* ok);
   PreParserExpression ParseFunctionLiteral(
       PreParserIdentifier name, Scanner::Location function_name_location,
-      bool name_is_strict_reserved, FunctionKind kind,
+      FunctionNameValidity function_name_validity, FunctionKind kind,
       int function_token_position, FunctionLiteral::FunctionType type,
       FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
 
@@ -1768,8 +1773,8 @@ class PreParser : public ParserBase<PreParserTraits> {
 
   Expression ParseFunctionLiteral(
       Identifier name, Scanner::Location function_name_location,
-      bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
-      FunctionLiteral::FunctionType function_type,
+      FunctionNameValidity function_name_validity, FunctionKind kind,
+      int function_token_pos, FunctionLiteral::FunctionType function_type,
       FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
   void ParseLazyFunctionLiteralBody(bool* ok,
                                     Scanner::BookmarkScope* bookmark = nullptr);
@@ -2543,9 +2548,8 @@ ParserBase<Traits>::ParsePropertyDefinition(
     if (!in_class) kind = WithObjectLiteralBit(kind);
 
     value = this->ParseFunctionLiteral(
-        name, scanner()->location(),
-        false,  // reserved words are allowed here
-        kind, RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
+        name, scanner()->location(), kSkipFunctionNameCheck, kind,
+        RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
         FunctionLiteral::NORMAL_ARITY,
         CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
 
@@ -2576,9 +2580,8 @@ ParserBase<Traits>::ParsePropertyDefinition(
     FunctionKind kind = FunctionKind::kAccessorFunction;
     if (!in_class) kind = WithObjectLiteralBit(kind);
     typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral(
-        name, scanner()->location(),
-        false,  // reserved words are allowed here
-        kind, RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
+        name, scanner()->location(), kSkipFunctionNameCheck, kind,
+        RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
         is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY,
         CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
 
@@ -3293,7 +3296,9 @@ ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier,
       function_type = FunctionLiteral::NAMED_EXPRESSION;
     }
     result = this->ParseFunctionLiteral(
-        name, function_name_location, is_strict_reserved_name,
+        name, function_name_location,
+        is_strict_reserved_name ? kFunctionNameIsStrictReserved
+                                : kFunctionNameValidityUnknown,
         is_generator ? FunctionKind::kGeneratorFunction
                      : FunctionKind::kNormalFunction,
         function_token_position, function_type, FunctionLiteral::NORMAL_ARITY,
index 65ded6d..0b0dc75 100644 (file)
   'intl402/13.2.1_5': [PASS, FAIL],
   'intl402/13.3.0_7': [PASS, FAIL],
 
-  # These tests fail in nosnap in strict mode
-  # https://code.google.com/p/v8/issues/detail?id=4198
-  'built-ins/String/S15.5.1.1_A1_T6': [PASS, FAIL_OK],
-  'built-ins/eval/S15.1.2.1_A1.1_T1': [PASS, FAIL_OK],
-  'built-ins/eval/S15.1.2.1_A1.1_T2': [PASS, FAIL_OK],
-  'built-ins/eval/S15.1.2.1_A4.3': [PASS, FAIL_OK],
-  'built-ins/eval/S15.1.2.1_A4.4': [PASS, FAIL_OK],
-  'language/eval-code/10.4.2-1-1': [PASS, FAIL_OK],
-  'language/eval-code/10.4.2-1-2': [PASS, FAIL_OK],
-  'language/eval-code/10.4.2-1-3': [PASS, FAIL_OK],
-  'language/eval-code/10.4.2-1-5': [PASS, FAIL_OK],
-  'language/eval-code/S10.4.2.1_A1': [PASS, FAIL_OK],
-  'language/function-code/10.4.3-1-19-s': [PASS, FAIL_OK],
-  'language/function-code/10.4.3-1-19gs': [PASS, FAIL_OK],
-  'language/function-code/10.4.3-1-20-s': [PASS, FAIL_OK],
-  'language/function-code/10.4.3-1-20gs': [PASS, FAIL_OK],
-  'language/statements/variable/12.2.1-10-s': [PASS, FAIL_OK],
-  'language/statements/variable/12.2.1-20-s': [PASS, FAIL_OK],
-  'language/statements/variable/12.2.1-21-s': [PASS, FAIL_OK],
-  'language/statements/variable/12.2.1-9-s': [PASS, FAIL_OK],
-
   ##################### DELIBERATE INCOMPATIBILITIES #####################
 
   'built-ins/Math/exp/S15.8.2.8_A6': [PASS, FAIL_OK],  # Math.exp (less precise with --fast-math)