Revision: 19812
Author:   [email protected]
Date:     Tue Mar 11 16:30:47 2014 UTC
Log:      Move ParseArguments to ParserBase and add tests.

Notes:
- PreParser didn't produce "too_many_arguments"; now it does.
- The argument count in the error message was wrong; fixed it.

BUG=v8:3126
LOG=N
[email protected]

Review URL: https://codereview.chromium.org/194503004
http://code.google.com/p/v8/source/detail?r=19812

Modified:
 /branches/bleeding_edge/src/messages.js
 /branches/bleeding_edge/src/parser.cc
 /branches/bleeding_edge/src/parser.h
 /branches/bleeding_edge/src/preparser.cc
 /branches/bleeding_edge/src/preparser.h
 /branches/bleeding_edge/test/cctest/test-parsing.cc

=======================================
--- /branches/bleeding_edge/src/messages.js     Tue Mar 11 14:39:08 2014 UTC
+++ /branches/bleeding_edge/src/messages.js     Tue Mar 11 16:30:47 2014 UTC
@@ -155,8 +155,8 @@
invalid_preparser_data: ["Invalid preparser data for function ", "%0"], strict_mode_with: ["Strict mode code may not include a with statement"], strict_eval_arguments: ["Unexpected eval or arguments in strict mode"], - too_many_arguments: ["Too many arguments in function call (only 32766 allowed)"], - too_many_parameters: ["Too many parameters in function definition (only 32766 allowed)"], + too_many_arguments: ["Too many arguments in function call (only 65535 allowed)"], + too_many_parameters: ["Too many parameters in function definition (only 65535 allowed)"], too_many_variables: ["Too many variables declared (only 131071 allowed)"], strict_param_dupe: ["Strict mode function may not have duplicate parameter names"], strict_octal_literal: ["Octal literals are not allowed in strict mode."],
=======================================
--- /branches/bleeding_edge/src/parser.cc       Tue Mar 11 15:40:41 2014 UTC
+++ /branches/bleeding_edge/src/parser.cc       Tue Mar 11 16:30:47 2014 UTC
@@ -3499,29 +3499,6 @@
Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
   return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
 }
-
-
-ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
-  // Arguments ::
-  //   '(' (AssignmentExpression)*[','] ')'
-
- ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4, zone());
-  Expect(Token::LPAREN, CHECK_OK);
-  bool done = (peek() == Token::RPAREN);
-  while (!done) {
-    Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
-    result->Add(argument, zone());
-    if (result->length() > Code::kMaxArguments) {
-      ReportMessageAt(scanner()->location(), "too_many_arguments");
-      *ok = false;
-      return NULL;
-    }
-    done = (peek() == Token::RPAREN);
-    if (!done) Expect(Token::COMMA, CHECK_OK);
-  }
-  Expect(Token::RPAREN, CHECK_OK);
-  return result;
-}


 class SingletonLogger : public ParserRecorder {
=======================================
--- /branches/bleeding_edge/src/parser.h        Tue Mar 11 15:40:41 2014 UTC
+++ /branches/bleeding_edge/src/parser.h        Tue Mar 11 16:30:47 2014 UTC
@@ -488,6 +488,9 @@
   static Literal* EmptyLiteral() {
     return NULL;
   }
+  static ZoneList<Expression*>* NullExpressionList() {
+    return NULL;
+  }

   // Odd-ball literal creators.
   Literal* GetLiteralTheHole(int position,
@@ -687,7 +690,6 @@
                                   Expression* subject,
                                   Statement* body);

-  ZoneList<Expression*>* ParseArguments(bool* ok);
   FunctionLiteral* ParseFunctionLiteral(
       Handle<String> name,
       Scanner::Location function_name_location,
=======================================
--- /branches/bleeding_edge/src/preparser.cc    Tue Mar 11 15:40:41 2014 UTC
+++ /branches/bleeding_edge/src/preparser.cc    Tue Mar 11 16:30:47 2014 UTC
@@ -1135,28 +1135,6 @@
 }


-PreParser::Arguments PreParser::ParseArguments(bool* ok) {
-  // Arguments ::
-  //   '(' (AssignmentExpression)*[','] ')'
-
-  Expect(Token::LPAREN, ok);
-  if (!*ok) return -1;
-  bool done = (peek() == Token::RPAREN);
-  int argc = 0;
-  while (!done) {
-    ParseAssignmentExpression(true, ok);
-    if (!*ok) return -1;
-    argc++;
-    done = (peek() == Token::RPAREN);
-    if (!done) {
-      Expect(Token::COMMA, ok);
-      if (!*ok) return -1;
-    }
-  }
-  Expect(Token::RPAREN, ok);
-  return argc;
-}
-
 PreParser::Expression PreParser::ParseFunctionLiteral(
     Identifier function_name,
     Scanner::Location function_name_location,
=======================================
--- /branches/bleeding_edge/src/preparser.h     Tue Mar 11 15:40:41 2014 UTC
+++ /branches/bleeding_edge/src/preparser.h     Tue Mar 11 16:30:47 2014 UTC
@@ -342,6 +342,7 @@
typename Traits::Type::Expression ParseExpression(bool accept_IN, bool* ok);
   typename Traits::Type::Expression ParseArrayLiteral(bool* ok);
   typename Traits::Type::Expression ParseObjectLiteral(bool* ok);
+  typename Traits::Type::ExpressionList ParseArguments(bool* ok);

   // Used to detect duplicates in object literals. Each of the values
   // kGetterProperty, kSetterProperty and kValueProperty represents
@@ -556,8 +557,12 @@
 class PreParserExpressionList {
  public:
   // These functions make list->Add(some_expression) work (and do nothing).
+  PreParserExpressionList() : length_(0) {}
   PreParserExpressionList* operator->() { return this; }
-  void Add(PreParserExpression, void*) { }
+  void Add(PreParserExpression, void*) { ++length_; }
+  int length() const { return length_; }
+ private:
+  int length_;
 };


@@ -720,6 +725,9 @@
   static PreParserExpression EmptyLiteral() {
     return PreParserExpression::Default();
   }
+  static PreParserExpressionList NullExpressionList() {
+    return PreParserExpressionList();
+  }

   // Odd-ball literal creators.
   static PreParserExpression GetLiteralTheHole(int position,
@@ -910,8 +918,6 @@
     kUnknownSourceElements
   };

-  typedef int Arguments;
-
   // All ParseXXX functions take as the last argument an *ok parameter
   // which is set to false if parsing failed; it is unchanged otherwise.
   // By making the 'exception handling' explicit, we are forced to check
@@ -955,7 +961,6 @@
   Expression ParseObjectLiteral(bool* ok);
   Expression ParseV8Intrinsic(bool* ok);

-  Arguments ParseArguments(bool* ok);
   Expression ParseFunctionLiteral(
       Identifier name,
       Scanner::Location function_name_location,
@@ -1153,6 +1158,13 @@
 #define DUMMY )  // to make indentation work
 #undef DUMMY

+// Used in functions where the return type is not Traits::Type::Expression.
+#define CHECK_OK_CUSTOM(x) ok); \
+  if (!*ok) return this->x(); \
+  ((void)0
+#define DUMMY )  // to make indentation work
+#undef DUMMY
+
 template <class Traits>
typename Traits::Type::Expression ParserBase<Traits>::ParsePrimaryExpression(
     bool* ok) {
@@ -1370,7 +1382,10 @@
             number_of_boilerplate_properties++;
           }
           properties->Add(property, zone());
-          if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
+          if (peek() != Token::RBRACE) {
+            // Need {} because of the CHECK_OK macro.
+            Expect(Token::COMMA, CHECK_OK);
+          }

           if (fni_ != NULL) {
             fni_->Infer();
@@ -1437,7 +1452,10 @@
     properties->Add(property, zone());

     // TODO(1240767): Consider allowing trailing comma.
-    if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
+    if (peek() != Token::RBRACE) {
+      // Need {} because of the CHECK_OK macro.
+      Expect(Token::COMMA, CHECK_OK);
+    }

     if (fni_ != NULL) {
       fni_->Infer();
@@ -1457,8 +1475,39 @@
 }


+template <class Traits>
+typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
+    bool* ok) {
+  // Arguments ::
+  //   '(' (AssignmentExpression)*[','] ')'
+
+  typename Traits::Type::ExpressionList result =
+      this->NewExpressionList(4, zone_);
+  Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
+  bool done = (peek() == Token::RPAREN);
+  while (!done) {
+    typename Traits::Type::Expression argument =
+        this->ParseAssignmentExpression(true,
+ CHECK_OK_CUSTOM(NullExpressionList));
+    result->Add(argument, zone_);
+    if (result->length() > Code::kMaxArguments) {
+      ReportMessageAt(scanner()->location(), "too_many_arguments");
+      *ok = false;
+      return this->NullExpressionList();
+    }
+    done = (peek() == Token::RPAREN);
+    if (!done) {
+      // Need {} because of the CHECK_OK_CUSTOM macro.
+      Expect(Token::COMMA, CHECK_OK_CUSTOM(NullExpressionList));
+    }
+  }
+  Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullExpressionList));
+  return result;
+}
+

 #undef CHECK_OK
+#undef CHECK_OK_CUSTOM


 template <typename Traits>
=======================================
--- /branches/bleeding_edge/test/cctest/test-parsing.cc Tue Mar 11 14:41:22 2014 UTC +++ /branches/bleeding_edge/test/cctest/test-parsing.cc Tue Mar 11 16:30:47 2014 UTC
@@ -35,6 +35,7 @@
 #include "compiler.h"
 #include "execution.h"
 #include "isolate.h"
+#include "objects.h"
 #include "parser.h"
 #include "preparser.h"
 #include "scanner-character-streams.h"
@@ -1463,7 +1464,9 @@

 void RunParserSyncTest(const char* context_data[][2],
                        const char* statement_data[],
-                       ParserSyncTestResult result) {
+                       ParserSyncTestResult result,
+                       const ParserFlag* flags = NULL,
+                       int flags_len = 0) {
   v8::HandleScope handles(CcTest::isolate());
   v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
   v8::Context::Scope context_scope(context);
@@ -1472,10 +1475,14 @@
   CcTest::i_isolate()->stack_guard()->SetStackLimit(
       reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);

-  static const ParserFlag flags[] = {
+  static const ParserFlag default_flags[] = {
     kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators,
     kAllowForOf, kAllowNativesSyntax
   };
+  if (!flags) {
+    flags = default_flags;
+    flags_len = ARRAY_SIZE(default_flags);
+  }
   for (int i = 0; context_data[i][0] != NULL; ++i) {
     for (int j = 0; statement_data[j] != NULL; ++j) {
       int kPrefixLen = i::StrLength(context_data[i][0]);
@@ -1493,7 +1500,7 @@
       CHECK(length == kProgramSize);
       TestParserSync(program.start(),
                      flags,
-                     ARRAY_SIZE(flags),
+                     flags_len,
                      result);
     }
   }
@@ -2320,3 +2327,27 @@

   RunParserSyncTest(context_data, statement_data, kSuccess);
 }
+
+
+TEST(TooManyArguments) {
+  const char* context_data[][2] = {
+    {"foo(", "0)"},
+    { NULL, NULL }
+  };
+
+  using v8::internal::Code;
+  char statement[Code::kMaxArguments * 2];
+  for (int i = 0; i < Code::kMaxArguments; ++i) {
+    statement[2 * i] = '0';
+    statement[2 * i + 1] = ',';
+  }
+
+  const char* statement_data[] = {
+    statement,
+    NULL
+  };
+
+  // The test is quite slow, so run it with a reduced set of flags.
+  static const ParserFlag empty_flags[] = {kAllowLazy};
+  RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
+}

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to