Move ParseObjectLiteral to ParserBase.
authormarja@chromium.org <marja@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 11 Mar 2014 15:40:41 +0000 (15:40 +0000)
committermarja@chromium.org <marja@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 11 Mar 2014 15:40:41 +0000 (15:40 +0000)
BUG=v8:3126
LOG=N
R=ulan@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19805 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/func-name-inferrer.h
src/parser.cc
src/parser.h
src/preparser.cc
src/preparser.h

index f57e778..41953ff 100644 (file)
 #ifndef V8_FUNC_NAME_INFERRER_H_
 #define V8_FUNC_NAME_INFERRER_H_
 
+#include "handles.h"
+#include "zone.h"
+
 namespace v8 {
 namespace internal {
 
+class FunctionLiteral;
 class Isolate;
 
 // FuncNameInferrer is a stateful class that is used to perform name
index cf5fcae..65b8616 100644 (file)
@@ -33,7 +33,6 @@
 #include "char-predicates-inl.h"
 #include "codegen.h"
 #include "compiler.h"
-#include "func-name-inferrer.h"
 #include "messages.h"
 #include "parser.h"
 #include "platform.h"
@@ -520,7 +519,7 @@ Expression* ParserTraits::ThisExpression(
 }
 
 
-Expression* ParserTraits::ExpressionFromLiteral(
+Literal* ParserTraits::ExpressionFromLiteral(
     Token::Value token, int pos,
     Scanner* scanner,
     AstNodeFactory<AstConstructionVisitor>* factory) {
@@ -577,11 +576,6 @@ Literal* ParserTraits::GetLiteralTheHole(
 }
 
 
-Expression* ParserTraits::ParseObjectLiteral(bool* ok) {
-  return parser_->ParseObjectLiteral(ok);
-}
-
-
 Expression* ParserTraits::ParseAssignmentExpression(bool accept_IN, bool* ok) {
   return parser_->ParseAssignmentExpression(accept_IN, ok);
 }
@@ -592,6 +586,20 @@ Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
 }
 
 
+FunctionLiteral* ParserTraits::ParseFunctionLiteral(
+    Handle<String> name,
+    Scanner::Location function_name_location,
+    bool name_is_strict_reserved,
+    bool is_generator,
+    int function_token_position,
+    FunctionLiteral::FunctionType type,
+    bool* ok) {
+  return parser_->ParseFunctionLiteral(name, function_name_location,
+                                       name_is_strict_reserved, is_generator,
+                                       function_token_position, type, ok);
+}
+
+
 Parser::Parser(CompilationInfo* info)
     : ParserBase<ParserTraits>(&scanner_,
                                info->isolate()->stack_guard()->real_climit(),
@@ -606,7 +614,6 @@ Parser::Parser(CompilationInfo* info)
       original_scope_(NULL),
       target_stack_(NULL),
       pre_parse_data_(NULL),
-      fni_(NULL),
       info_(info) {
   ASSERT(!script_.is_null());
   isolate_->set_ast_node_id(0);
@@ -3494,169 +3501,6 @@ Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
 }
 
 
-Expression* Parser::ParseObjectLiteral(bool* ok) {
-  // ObjectLiteral ::
-  // '{' ((
-  //       ((IdentifierName | String | Number) ':' AssignmentExpression) |
-  //       (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
-  //      ) ',')* '}'
-  // (Except that trailing comma is not required and not allowed.)
-
-  int pos = peek_position();
-  ZoneList<ObjectLiteral::Property*>* properties =
-      new(zone()) ZoneList<ObjectLiteral::Property*>(4, zone());
-  int number_of_boilerplate_properties = 0;
-  bool has_function = false;
-
-  ObjectLiteralChecker checker(this, strict_mode());
-
-  Expect(Token::LBRACE, CHECK_OK);
-
-  while (peek() != Token::RBRACE) {
-    if (fni_ != NULL) fni_->Enter();
-
-    Literal* key = NULL;
-    Token::Value next = peek();
-    int next_pos = peek_position();
-
-    switch (next) {
-      case Token::FUTURE_RESERVED_WORD:
-      case Token::FUTURE_STRICT_RESERVED_WORD:
-      case Token::IDENTIFIER: {
-        bool is_getter = false;
-        bool is_setter = false;
-        Handle<String> id =
-            ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
-        if (fni_ != NULL) fni_->PushLiteralName(id);
-
-        if ((is_getter || is_setter) && peek() != Token::COLON) {
-          // Special handling of getter and setter syntax:
-          // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
-          // We have already read the "get" or "set" keyword.
-          Token::Value next = Next();
-          if (next != i::Token::IDENTIFIER &&
-              next != i::Token::FUTURE_RESERVED_WORD &&
-              next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
-              next != i::Token::NUMBER &&
-              next != i::Token::STRING &&
-              !Token::IsKeyword(next)) {
-            ReportUnexpectedToken(next);
-            *ok = false;
-            return NULL;
-          }
-          // Validate the property.
-          PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
-          checker.CheckProperty(next, type, CHECK_OK);
-          Handle<String> name = GetSymbol();
-          FunctionLiteral* value =
-              ParseFunctionLiteral(name,
-                                   scanner()->location(),
-                                   false,   // reserved words are allowed here
-                                   false,   // not a generator
-                                   RelocInfo::kNoPosition,
-                                   FunctionLiteral::ANONYMOUS_EXPRESSION,
-                                   CHECK_OK);
-          // Allow any number of parameters for compatibilty with JSC.
-          // Specification only allows zero parameters for get and one for set.
-          ObjectLiteral::Property* property =
-              factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
-          if (ObjectLiteral::IsBoilerplateProperty(property)) {
-            number_of_boilerplate_properties++;
-          }
-          properties->Add(property, zone());
-          if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
-
-          if (fni_ != NULL) {
-            fni_->Infer();
-            fni_->Leave();
-          }
-          continue;  // restart the while
-        }
-        // Failed to parse as get/set property, so it's just a normal property
-        // (which might be called "get" or "set" or something else).
-        key = factory()->NewLiteral(id, next_pos);
-        break;
-      }
-      case Token::STRING: {
-        Consume(Token::STRING);
-        Handle<String> string = GetSymbol();
-        if (fni_ != NULL) fni_->PushLiteralName(string);
-        uint32_t index;
-        if (!string.is_null() && string->AsArrayIndex(&index)) {
-          key = factory()->NewNumberLiteral(index, next_pos);
-          break;
-        }
-        key = factory()->NewLiteral(string, next_pos);
-        break;
-      }
-      case Token::NUMBER: {
-        Consume(Token::NUMBER);
-        ASSERT(scanner()->is_literal_ascii());
-        double value = StringToDouble(isolate()->unicode_cache(),
-                                      scanner()->literal_ascii_string(),
-                                      ALLOW_HEX | ALLOW_OCTAL |
-                                          ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
-        key = factory()->NewNumberLiteral(value, next_pos);
-        break;
-      }
-      default:
-        if (Token::IsKeyword(next)) {
-          Consume(next);
-          Handle<String> string = GetSymbol();
-          key = factory()->NewLiteral(string, next_pos);
-        } else {
-          Token::Value next = Next();
-          ReportUnexpectedToken(next);
-          *ok = false;
-          return NULL;
-        }
-    }
-
-    // Validate the property
-    checker.CheckProperty(next, kValueProperty, CHECK_OK);
-
-    Expect(Token::COLON, CHECK_OK);
-    Expression* value = ParseAssignmentExpression(true, CHECK_OK);
-
-    ObjectLiteral::Property* property =
-        factory()->NewObjectLiteralProperty(key, value);
-
-    // Mark top-level object literals that contain function literals and
-    // pretenure the literal so it can be added as a constant function
-    // property.
-    if (scope_->DeclarationScope()->is_global_scope() &&
-        value->AsFunctionLiteral() != NULL) {
-      has_function = true;
-      value->AsFunctionLiteral()->set_pretenure();
-    }
-
-    // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
-    if (ObjectLiteral::IsBoilerplateProperty(property)) {
-      number_of_boilerplate_properties++;
-    }
-    properties->Add(property, zone());
-
-    // TODO(1240767): Consider allowing trailing comma.
-    if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
-
-    if (fni_ != NULL) {
-      fni_->Infer();
-      fni_->Leave();
-    }
-  }
-  Expect(Token::RBRACE, CHECK_OK);
-
-  // Computation of literal_index must happen before pre parse bailout.
-  int literal_index = function_state_->NextMaterializedLiteralIndex();
-
-  return factory()->NewObjectLiteral(properties,
-                                     literal_index,
-                                     number_of_boilerplate_properties,
-                                     has_function,
-                                     pos);
-}
-
-
 ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
   // Arguments ::
   //   '(' (AssignmentExpression)*[','] ')'
index 062150d..fd3fc47 100644 (file)
@@ -39,7 +39,6 @@ namespace v8 {
 namespace internal {
 
 class CompilationInfo;
-class FuncNameInferrer;
 class ParserLog;
 class PositionStack;
 class Target;
@@ -420,7 +419,11 @@ class ParserTraits {
     // Return types for traversing functions.
     typedef Handle<String> Identifier;
     typedef v8::internal::Expression* Expression;
+    typedef v8::internal::FunctionLiteral* FunctionLiteral;
+    typedef v8::internal::Literal* Literal;
+    typedef ObjectLiteral::Property* ObjectLiteralProperty;
     typedef ZoneList<v8::internal::Expression*>* ExpressionList;
+    typedef ZoneList<ObjectLiteral::Property*>* PropertyList;
   };
 
   explicit ParserTraits(Parser* parser) : parser_(parser) {}
@@ -445,6 +448,27 @@ class ParserTraits {
   // Helper functions for recursive descent.
   bool IsEvalOrArguments(Handle<String> identifier) const;
 
+  static bool IsBoilerplateProperty(ObjectLiteral::Property* property) {
+    return ObjectLiteral::IsBoilerplateProperty(property);
+  }
+
+  static bool IsArrayIndex(Handle<String> string, uint32_t* index) {
+    return !string.is_null() && string->AsArrayIndex(index);
+  }
+
+  static void PushLiteralName(FuncNameInferrer* fni, Handle<String> id) {
+    fni->PushLiteralName(id);
+  }
+
+  static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
+      Scope* scope, Expression* value, bool* has_function) {
+    if (scope->DeclarationScope()->is_global_scope() &&
+        value->AsFunctionLiteral() != NULL) {
+      *has_function = true;
+      value->AsFunctionLiteral()->set_pretenure();
+    }
+  }
+
   // Reporting errors.
   void ReportMessageAt(Scanner::Location source_location,
                        const char* message,
@@ -461,6 +485,9 @@ class ParserTraits {
   static Expression* EmptyExpression() {
     return NULL;
   }
+  static Literal* EmptyLiteral() {
+    return NULL;
+  }
 
   // Odd-ball literal creators.
   Literal* GetLiteralTheHole(int position,
@@ -472,7 +499,7 @@ class ParserTraits {
                                    PretenureFlag tenured);
   Expression* ThisExpression(Scope* scope,
                              AstNodeFactory<AstConstructionVisitor>* factory);
-  Expression* ExpressionFromLiteral(
+  Literal* ExpressionFromLiteral(
       Token::Value token, int pos, Scanner* scanner,
       AstNodeFactory<AstConstructionVisitor>* factory);
   Expression* ExpressionFromIdentifier(
@@ -484,11 +511,21 @@ class ParserTraits {
   ZoneList<v8::internal::Expression*>* NewExpressionList(int size, Zone* zone) {
     return new(zone) ZoneList<v8::internal::Expression*>(size, zone);
   }
+  ZoneList<ObjectLiteral::Property*>* NewPropertyList(int size, Zone* zone) {
+    return new(zone) ZoneList<ObjectLiteral::Property*>(size, zone);
+  }
 
   // Temporary glue; these functions will move to ParserBase.
-  Expression* ParseObjectLiteral(bool* ok);
   Expression* ParseAssignmentExpression(bool accept_IN, bool* ok);
   Expression* ParseV8Intrinsic(bool* ok);
+  FunctionLiteral* ParseFunctionLiteral(
+      Handle<String> name,
+      Scanner::Location function_name_location,
+      bool name_is_strict_reserved,
+      bool is_generator,
+      int function_token_position,
+      FunctionLiteral::FunctionType type,
+      bool* ok);
 
  private:
   Parser* parser_;
@@ -749,7 +786,6 @@ class Parser : public ParserBase<ParserTraits> {
   Scope* original_scope_;  // for ES5 function declarations in sloppy eval
   Target* target_stack_;  // for break, continue statements
   ScriptDataImpl* pre_parse_data_;
-  FuncNameInferrer* fni_;
 
   Mode mode_;
 
index 0621918..bec72ef 100644 (file)
@@ -122,11 +122,6 @@ PreParserExpression PreParserTraits::ExpressionFromString(
 }
 
 
-PreParserExpression PreParserTraits::ParseObjectLiteral(bool* ok) {
-  return pre_parser_->ParseObjectLiteral(ok);
-}
-
-
 PreParserExpression PreParserTraits::ParseAssignmentExpression(bool accept_IN,
                                                                bool* ok) {
   return pre_parser_->ParseAssignmentExpression(accept_IN, ok);
@@ -138,6 +133,20 @@ PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
 }
 
 
+PreParserExpression PreParserTraits::ParseFunctionLiteral(
+    PreParserIdentifier name,
+    Scanner::Location function_name_location,
+    bool name_is_strict_reserved,
+    bool is_generator,
+    int function_token_position,
+    FunctionLiteral::FunctionType type,
+    bool* ok) {
+  return pre_parser_->ParseFunctionLiteral(
+      name, function_name_location, name_is_strict_reserved, is_generator,
+      function_token_position, type, ok);
+}
+
+
 PreParser::PreParseResult PreParser::PreParseLazyFunction(
     StrictMode strict_mode, bool is_generator, ParserRecorder* log) {
   log_ = log;
@@ -1126,91 +1135,6 @@ PreParser::Expression PreParser::ParseMemberExpressionContinuation(
 }
 
 
-PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
-  // ObjectLiteral ::
-  // '{' ((
-  //       ((IdentifierName | String | Number) ':' AssignmentExpression) |
-  //       (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
-  //      ) ',')* '}'
-  // (Except that trailing comma is not required and not allowed.)
-
-  ObjectLiteralChecker checker(this, strict_mode());
-
-  Expect(Token::LBRACE, CHECK_OK);
-  while (peek() != Token::RBRACE) {
-    Token::Value next = peek();
-    switch (next) {
-      case Token::IDENTIFIER:
-      case Token::FUTURE_RESERVED_WORD:
-      case Token::FUTURE_STRICT_RESERVED_WORD: {
-        bool is_getter = false;
-        bool is_setter = false;
-        ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
-        if ((is_getter || is_setter) && peek() != Token::COLON) {
-            Token::Value next = Next();
-            if (next != Token::IDENTIFIER &&
-                next != Token::FUTURE_RESERVED_WORD &&
-                next != Token::FUTURE_STRICT_RESERVED_WORD &&
-                next != Token::NUMBER &&
-                next != Token::STRING &&
-                !Token::IsKeyword(next)) {
-              ReportUnexpectedToken(next);
-              *ok = false;
-              return Expression::Default();
-            }
-            // Validate the property
-            PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
-            checker.CheckProperty(next, type, CHECK_OK);
-            PreParserIdentifier name = GetSymbol(scanner());
-            ParseFunctionLiteral(name,
-                                 scanner()->location(),
-                                 false,  // reserved words are allowed here
-                                 false,  // not a generator
-                                 RelocInfo::kNoPosition,
-                                 FunctionLiteral::ANONYMOUS_EXPRESSION,
-                                 CHECK_OK);
-            if (peek() != Token::RBRACE) {
-              Expect(Token::COMMA, CHECK_OK);
-            }
-            continue;  // restart the while
-        }
-        break;
-      }
-      case Token::STRING:
-        Consume(next);
-        LogSymbol();
-        break;
-      case Token::NUMBER:
-        Consume(next);
-        break;
-      default:
-        if (Token::IsKeyword(next)) {
-          Consume(next);
-          LogSymbol();
-        } else {
-          Token::Value next = Next();
-          ReportUnexpectedToken(next);
-          *ok = false;
-          return Expression::Default();
-        }
-    }
-
-    // Validate the property
-    checker.CheckProperty(next, kValueProperty, CHECK_OK);
-
-    Expect(Token::COLON, CHECK_OK);
-    ParseAssignmentExpression(true, CHECK_OK);
-
-    // TODO(1240767): Consider allowing trailing comma.
-    if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
-  }
-  Expect(Token::RBRACE, CHECK_OK);
-
-  function_state_->NextMaterializedLiteralIndex();
-  return Expression::Default();
-}
-
-
 PreParser::Arguments PreParser::ParseArguments(bool* ok) {
   // Arguments ::
   //   '(' (AssignmentExpression)*[','] ')'
index c7ac7ff..d1426e5 100644 (file)
@@ -28,6 +28,7 @@
 #ifndef V8_PREPARSER_H
 #define V8_PREPARSER_H
 
+#include "func-name-inferrer.h"
 #include "hashmap.h"
 #include "scopes.h"
 #include "token.h"
@@ -50,6 +51,7 @@ class ParserBase : public Traits {
         scope_(NULL),
         function_state_(NULL),
         extension_(extension),
+        fni_(NULL),
         scanner_(scanner),
         stack_limit_(stack_limit),
         stack_overflow_(false),
@@ -330,8 +332,8 @@ class ParserBase : public Traits {
   typename Traits::Type::Identifier ParseIdentifierName(bool* ok);
   // Parses an identifier and determines whether or not it is 'get' or 'set'.
   typename Traits::Type::Identifier ParseIdentifierNameOrGetOrSet(bool* is_get,
-                                                                bool* is_set,
-                                                                bool* ok);
+                                                                  bool* is_set,
+                                                                  bool* ok);
 
   typename Traits::Type::Expression ParseRegExpLiteral(bool seen_equal,
                                                        bool* ok);
@@ -339,6 +341,7 @@ class ParserBase : public Traits {
   typename Traits::Type::Expression ParsePrimaryExpression(bool* ok);
   typename Traits::Type::Expression ParseExpression(bool accept_IN, bool* ok);
   typename Traits::Type::Expression ParseArrayLiteral(bool* ok);
+  typename Traits::Type::Expression ParseObjectLiteral(bool* ok);
 
   // Used to detect duplicates in object literals. Each of the values
   // kGetterProperty, kSetterProperty and kValueProperty represents
@@ -403,6 +406,7 @@ class ParserBase : public Traits {
   typename Traits::Type::Scope* scope_;  // Scope stack.
   FunctionState* function_state_;  // Function state stack.
   v8::Extension* extension_;
+  FuncNameInferrer* fni_;
 
  private:
   Scanner* scanner_;
@@ -606,6 +610,35 @@ class PreParserFactory {
                                       int pos) {
     return PreParserExpression::Default();
   }
+
+  PreParserExpression NewObjectLiteralProperty(bool is_getter,
+                                               PreParserExpression value,
+                                               int pos) {
+    return PreParserExpression::Default();
+  }
+
+  PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
+                                               PreParserExpression value) {
+    return PreParserExpression::Default();
+  }
+
+  PreParserExpression NewObjectLiteral(PreParserExpressionList properties,
+                                       int literal_index,
+                                       int boilerplate_properties,
+                                       bool has_function,
+                                       int pos) {
+    return PreParserExpression::Default();
+  }
+
+  PreParserExpression NewLiteral(PreParserIdentifier identifier,
+                                 int pos) {
+    return PreParserExpression::Default();
+  }
+
+  PreParserExpression NewNumberLiteral(double number,
+                                       int pos) {
+    return PreParserExpression::Default();
+  }
 };
 
 
@@ -627,7 +660,11 @@ class PreParserTraits {
     // Return types for traversing functions.
     typedef PreParserIdentifier Identifier;
     typedef PreParserExpression Expression;
+    typedef PreParserExpression FunctionLiteral;
+    typedef PreParserExpression ObjectLiteralProperty;
+    typedef PreParserExpression Literal;
     typedef PreParserExpressionList ExpressionList;
+    typedef PreParserExpressionList PropertyList;
   };
 
   explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
@@ -644,6 +681,23 @@ class PreParserTraits {
     return identifier.IsEvalOrArguments();
   }
 
+  static bool IsBoilerplateProperty(PreParserExpression property) {
+    // PreParser doesn't count boilerplate properties.
+    return false;
+  }
+
+  static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) {
+    return false;
+  }
+
+  static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) {
+    // PreParser should not use FuncNameInferrer.
+    ASSERT(false);
+  }
+
+  static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
+      PreParserScope* scope, PreParserExpression value, bool* has_function) {}
+
   // Reporting errors.
   void ReportMessageAt(Scanner::Location location,
                        const char* message,
@@ -663,6 +717,9 @@ class PreParserTraits {
   static PreParserExpression EmptyExpression() {
     return PreParserExpression::Default();
   }
+  static PreParserExpression EmptyLiteral() {
+    return PreParserExpression::Default();
+  }
 
   // Odd-ball literal creators.
   static PreParserExpression GetLiteralTheHole(int position,
@@ -702,10 +759,21 @@ class PreParserTraits {
     return PreParserExpressionList();
   }
 
+  static PreParserExpressionList NewPropertyList(int size, void* zone) {
+    return PreParserExpressionList();
+  }
+
   // Temporary glue; these functions will move to ParserBase.
   PreParserExpression ParseAssignmentExpression(bool accept_IN, bool* ok);
-  PreParserExpression ParseObjectLiteral(bool* ok);
   PreParserExpression ParseV8Intrinsic(bool* ok);
+  PreParserExpression ParseFunctionLiteral(
+      PreParserIdentifier name,
+      Scanner::Location function_name_location,
+      bool name_is_strict_reserved,
+      bool is_generator,
+      int function_token_position,
+      FunctionLiteral::FunctionType type,
+      bool* ok);
 
  private:
   PreParser* pre_parser_;
@@ -1230,6 +1298,166 @@ typename Traits::Type::Expression ParserBase<Traits>::ParseArrayLiteral(
   return factory()->NewArrayLiteral(values, literal_index, pos);
 }
 
+
+template <class Traits>
+typename Traits::Type::Expression ParserBase<Traits>::ParseObjectLiteral(
+    bool* ok) {
+  // ObjectLiteral ::
+  // '{' ((
+  //       ((IdentifierName | String | Number) ':' AssignmentExpression) |
+  //       (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
+  //      ) ',')* '}'
+  // (Except that trailing comma is not required and not allowed.)
+
+  int pos = peek_position();
+  typename Traits::Type::PropertyList properties =
+      this->NewPropertyList(4, zone_);
+  int number_of_boilerplate_properties = 0;
+  bool has_function = false;
+
+  ObjectLiteralChecker checker(this, strict_mode());
+
+  Expect(Token::LBRACE, CHECK_OK);
+
+  while (peek() != Token::RBRACE) {
+    if (fni_ != NULL) fni_->Enter();
+
+    typename Traits::Type::Literal key = this->EmptyLiteral();
+    Token::Value next = peek();
+    int next_pos = peek_position();
+
+    switch (next) {
+      case Token::FUTURE_RESERVED_WORD:
+      case Token::FUTURE_STRICT_RESERVED_WORD:
+      case Token::IDENTIFIER: {
+        bool is_getter = false;
+        bool is_setter = false;
+        typename Traits::Type::Identifier id =
+            ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
+        if (fni_ != NULL) this->PushLiteralName(fni_, id);
+
+        if ((is_getter || is_setter) && peek() != Token::COLON) {
+          // Special handling of getter and setter syntax:
+          // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
+          // We have already read the "get" or "set" keyword.
+          Token::Value next = Next();
+          if (next != i::Token::IDENTIFIER &&
+              next != i::Token::FUTURE_RESERVED_WORD &&
+              next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
+              next != i::Token::NUMBER &&
+              next != i::Token::STRING &&
+              !Token::IsKeyword(next)) {
+            ReportUnexpectedToken(next);
+            *ok = false;
+            return this->EmptyLiteral();
+          }
+          // Validate the property.
+          PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
+          checker.CheckProperty(next, type, CHECK_OK);
+          typename Traits::Type::Identifier name = this->GetSymbol(scanner_);
+          typename Traits::Type::FunctionLiteral value =
+              this->ParseFunctionLiteral(
+                  name, scanner()->location(),
+                  false,  // reserved words are allowed here
+                  false,  // not a generator
+                  RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
+                  CHECK_OK);
+          // Allow any number of parameters for compatibilty with JSC.
+          // Specification only allows zero parameters for get and one for set.
+          typename Traits::Type::ObjectLiteralProperty property =
+              factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
+          if (this->IsBoilerplateProperty(property)) {
+            number_of_boilerplate_properties++;
+          }
+          properties->Add(property, zone());
+          if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
+
+          if (fni_ != NULL) {
+            fni_->Infer();
+            fni_->Leave();
+          }
+          continue;  // restart the while
+        }
+        // Failed to parse as get/set property, so it's just a normal property
+        // (which might be called "get" or "set" or something else).
+        key = factory()->NewLiteral(id, next_pos);
+        break;
+      }
+      case Token::STRING: {
+        Consume(Token::STRING);
+        typename Traits::Type::Identifier string = this->GetSymbol(scanner_);
+        if (fni_ != NULL) this->PushLiteralName(fni_, string);
+        uint32_t index;
+        if (this->IsArrayIndex(string, &index)) {
+          key = factory()->NewNumberLiteral(index, next_pos);
+          break;
+        }
+        key = factory()->NewLiteral(string, next_pos);
+        break;
+      }
+      case Token::NUMBER: {
+        Consume(Token::NUMBER);
+        key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_,
+                                          factory());
+        break;
+      }
+      default:
+        if (Token::IsKeyword(next)) {
+          Consume(next);
+          typename Traits::Type::Identifier string = this->GetSymbol(scanner_);
+          key = factory()->NewLiteral(string, next_pos);
+        } else {
+          Token::Value next = Next();
+          ReportUnexpectedToken(next);
+          *ok = false;
+          return this->EmptyLiteral();
+        }
+    }
+
+    // Validate the property
+    checker.CheckProperty(next, kValueProperty, CHECK_OK);
+
+    Expect(Token::COLON, CHECK_OK);
+    typename Traits::Type::Expression value =
+        this->ParseAssignmentExpression(true, CHECK_OK);
+
+    typename Traits::Type::ObjectLiteralProperty property =
+        factory()->NewObjectLiteralProperty(key, value);
+
+    // Mark top-level object literals that contain function literals and
+    // pretenure the literal so it can be added as a constant function
+    // property. (Parser only.)
+    this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value,
+                                                          &has_function);
+
+    // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
+    if (this->IsBoilerplateProperty(property)) {
+      number_of_boilerplate_properties++;
+    }
+    properties->Add(property, zone());
+
+    // TODO(1240767): Consider allowing trailing comma.
+    if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
+
+    if (fni_ != NULL) {
+      fni_->Infer();
+      fni_->Leave();
+    }
+  }
+  Expect(Token::RBRACE, CHECK_OK);
+
+  // Computation of literal_index must happen before pre parse bailout.
+  int literal_index = function_state_->NextMaterializedLiteralIndex();
+
+  return factory()->NewObjectLiteral(properties,
+                                     literal_index,
+                                     number_of_boilerplate_properties,
+                                     has_function,
+                                     pos);
+}
+
+
+
 #undef CHECK_OK