ES6: Add support for method shorthand in object literals
authorarv@chromium.org <arv@chromium.org>
Wed, 10 Sep 2014 16:39:42 +0000 (16:39 +0000)
committerarv@chromium.org <arv@chromium.org>
Wed, 10 Sep 2014 16:39:42 +0000 (16:39 +0000)
This is governed by the harmony-object-literals flag.

BUG=v8:3516
LOG=Y
R=rossberg@chromium.org

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

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

37 files changed:
src/arm/full-codegen-arm.cc
src/arm/lithium-codegen-arm.cc
src/arm64/full-codegen-arm64.cc
src/arm64/lithium-codegen-arm64.cc
src/ast.h
src/code-stubs-hydrogen.cc
src/code-stubs.h
src/compiler.cc
src/contexts.h
src/factory.cc
src/factory.h
src/flag-definitions.h
src/full-codegen.cc
src/globals.h
src/hydrogen-instructions.h
src/ia32/full-codegen-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/mips/full-codegen-mips.cc
src/mips/lithium-codegen-mips.cc
src/mips64/full-codegen-mips64.cc
src/mips64/lithium-codegen-mips64.cc
src/objects-inl.h
src/objects.h
src/parser.cc
src/parser.h
src/preparser.cc
src/preparser.h
src/runtime.cc
src/runtime.h
src/v8natives.js
src/x64/full-codegen-x64.cc
src/x64/lithium-codegen-x64.cc
src/x87/full-codegen-x87.cc
src/x87/lithium-codegen-x87.cc
test/cctest/test-parsing.cc
test/mjsunit/harmony/object-literals-method.js [new file with mode: 0644]
test/mjsunit/runtime-gen/functionisconcisemethod.js [new file with mode: 0644]

index dfd0e61..361f4a8 100644 (file)
@@ -1332,9 +1332,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
       !pretenure &&
       scope()->is_function_scope() &&
       info->num_literals() == 0) {
-    FastNewClosureStub stub(isolate(),
-                            info->strict_mode(),
-                            info->is_generator());
+    FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
     __ mov(r2, Operand(info));
     __ CallStub(&stub);
   } else {
index 37e6d20..377d38b 100644 (file)
@@ -5492,9 +5492,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
   // space for nested functions that don't need literals cloning.
   bool pretenure = instr->hydrogen()->pretenure();
   if (!pretenure && instr->hydrogen()->has_no_literals()) {
-    FastNewClosureStub stub(isolate(),
-                            instr->hydrogen()->strict_mode(),
-                            instr->hydrogen()->is_generator());
+    FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
+                            instr->hydrogen()->kind());
     __ mov(r2, Operand(instr->hydrogen()->shared_info()));
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   } else {
index 198e781..2e576ad 100644 (file)
@@ -1318,9 +1318,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
       !pretenure &&
       scope()->is_function_scope() &&
       info->num_literals() == 0) {
-    FastNewClosureStub stub(isolate(),
-                            info->strict_mode(),
-                            info->is_generator());
+    FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
     __ Mov(x2, Operand(info));
     __ CallStub(&stub);
   } else {
index 904eecd..da237a6 100644 (file)
@@ -2864,9 +2864,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
   // space for nested functions that don't need literals cloning.
   bool pretenure = instr->hydrogen()->pretenure();
   if (!pretenure && instr->hydrogen()->has_no_literals()) {
-    FastNewClosureStub stub(isolate(),
-                            instr->hydrogen()->strict_mode(),
-                            instr->hydrogen()->is_generator());
+    FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
+                            instr->hydrogen()->kind());
     __ Mov(x2, Operand(instr->hydrogen()->shared_info()));
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   } else {
index f8f65f1..c5a924c 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -2325,12 +2325,6 @@ class FunctionLiteral FINAL : public Expression {
     kNotParenthesized
   };
 
-  enum KindFlag {
-    kNormalFunction,
-    kArrowFunction,
-    kGeneratorFunction
-  };
-
   enum ArityRestriction {
     NORMAL_ARITY,
     GETTER_ARITY,
@@ -2420,8 +2414,16 @@ class FunctionLiteral FINAL : public Expression {
     bitfield_ = IsParenthesized::update(bitfield_, kIsParenthesized);
   }
 
-  bool is_generator() { return IsGenerator::decode(bitfield_); }
-  bool is_arrow() { return IsArrow::decode(bitfield_); }
+  FunctionKind kind() { return FunctionKindBits::decode(bitfield_); }
+  bool is_arrow() {
+    return IsArrowFunction(FunctionKindBits::decode(bitfield_));
+  }
+  bool is_generator() {
+    return IsGeneratorFunction(FunctionKindBits::decode(bitfield_));
+  }
+  bool is_concise_method() {
+    return IsConciseMethod(FunctionKindBits::decode(bitfield_));
+  }
 
   int ast_node_count() { return ast_properties_.node_count(); }
   AstProperties::Flags* flags() { return ast_properties_.flags(); }
@@ -2445,7 +2447,7 @@ class FunctionLiteral FINAL : public Expression {
                   int parameter_count, FunctionType function_type,
                   ParameterFlag has_duplicate_parameters,
                   IsFunctionFlag is_function,
-                  IsParenthesizedFlag is_parenthesized, KindFlag kind,
+                  IsParenthesizedFlag is_parenthesized, FunctionKind kind,
                   int position, IdGen* id_gen)
       : Expression(zone, position, id_gen),
         raw_name_(name),
@@ -2464,8 +2466,8 @@ class FunctionLiteral FINAL : public Expression {
                 HasDuplicateParameters::encode(has_duplicate_parameters) |
                 IsFunction::encode(is_function) |
                 IsParenthesized::encode(is_parenthesized) |
-                IsGenerator::encode(kind == kGeneratorFunction) |
-                IsArrow::encode(kind == kArrowFunction);
+                FunctionKindBits::encode(kind);
+    DCHECK(IsValidFunctionKind(kind));
   }
 
  private:
@@ -2486,14 +2488,13 @@ class FunctionLiteral FINAL : public Expression {
   int function_token_position_;
 
   unsigned bitfield_;
-  class IsExpression: public BitField<bool, 0, 1> {};
-  class IsAnonymous: public BitField<bool, 1, 1> {};
-  class Pretenure: public BitField<bool, 2, 1> {};
-  class HasDuplicateParameters: public BitField<ParameterFlag, 3, 1> {};
-  class IsFunction: public BitField<IsFunctionFlag, 4, 1> {};
-  class IsParenthesized: public BitField<IsParenthesizedFlag, 5, 1> {};
-  class IsGenerator : public BitField<bool, 6, 1> {};
-  class IsArrow : public BitField<bool, 7, 1> {};
+  class IsExpression : public BitField<bool, 0, 1> {};
+  class IsAnonymous : public BitField<bool, 1, 1> {};
+  class Pretenure : public BitField<bool, 2, 1> {};
+  class HasDuplicateParameters : public BitField<ParameterFlag, 3, 1> {};
+  class IsFunction : public BitField<IsFunctionFlag, 4, 1> {};
+  class IsParenthesized : public BitField<IsParenthesizedFlag, 5, 1> {};
+  class FunctionKindBits : public BitField<FunctionKind, 6, 3> {};
 };
 
 
@@ -3439,8 +3440,8 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
       FunctionLiteral::ParameterFlag has_duplicate_parameters,
       FunctionLiteral::FunctionType function_type,
       FunctionLiteral::IsFunctionFlag is_function,
-      FunctionLiteral::IsParenthesizedFlag is_parenthesized,
-      FunctionLiteral::KindFlag kind, int position) {
+      FunctionLiteral::IsParenthesizedFlag is_parenthesized, FunctionKind kind,
+      int position) {
     FunctionLiteral* lit = new (zone_) FunctionLiteral(
         zone_, name, ast_value_factory, scope, body, materialized_literal_count,
         expected_property_count, handler_count, parameter_count, function_type,
index e3261a3..57bf1e8 100644 (file)
@@ -1343,7 +1343,7 @@ HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() {
                                              NOT_TENURED, JS_FUNCTION_TYPE);
 
   int map_index = Context::FunctionMapIndex(casted_stub()->strict_mode(),
-                                            casted_stub()->is_generator());
+                                            casted_stub()->kind());
 
   // Compute the function map in the current native context and set that
   // as the map of the allocated object.
index a5be529..626e14e 100644 (file)
@@ -551,21 +551,27 @@ class NumberToStringStub FINAL : public HydrogenCodeStub {
 class FastNewClosureStub : public HydrogenCodeStub {
  public:
   FastNewClosureStub(Isolate* isolate, StrictMode strict_mode,
-                     bool is_generator)
+                     FunctionKind kind)
       : HydrogenCodeStub(isolate) {
+    DCHECK(IsValidFunctionKind(kind));
     set_sub_minor_key(StrictModeBits::encode(strict_mode) |
-                      IsGeneratorBits::encode(is_generator));
+                      FunctionKindBits::encode(kind));
   }
 
   StrictMode strict_mode() const {
     return StrictModeBits::decode(sub_minor_key());
   }
 
-  bool is_generator() const { return IsGeneratorBits::decode(sub_minor_key()); }
+  FunctionKind kind() const {
+    return FunctionKindBits::decode(sub_minor_key());
+  }
+  bool is_arrow() const { return IsArrowFunction(kind()); }
+  bool is_generator() const { return IsGeneratorFunction(kind()); }
+  bool is_concise_method() const { return IsConciseMethod(kind()); }
 
  private:
   class StrictModeBits : public BitField<StrictMode, 0, 1> {};
-  class IsGeneratorBits : public BitField<bool, 1, 1> {};
+  class FunctionKindBits : public BitField<FunctionKind, 1, 3> {};
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
   DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
index e0c8ae3..162c65b 100644 (file)
@@ -654,8 +654,7 @@ static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
   function_info->set_is_function(lit->is_function());
   function_info->set_bailout_reason(lit->dont_optimize_reason());
   function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
-  function_info->set_is_generator(lit->is_generator());
-  function_info->set_is_arrow(lit->is_arrow());
+  function_info->set_kind(lit->kind());
 }
 
 
@@ -871,9 +870,8 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
     // Allocate function.
     DCHECK(!info->code().is_null());
     result = isolate->factory()->NewSharedFunctionInfo(
-        lit->name(), lit->materialized_literal_count(), lit->is_generator(),
-        lit->is_arrow(), info->code(),
-        ScopeInfo::Create(info->scope(), info->zone()),
+        lit->name(), lit->materialized_literal_count(), lit->kind(),
+        info->code(), ScopeInfo::Create(info->scope(), info->zone()),
         info->feedback_vector());
 
     DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position());
@@ -1094,9 +1092,8 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(
 
   // Create a shared function info object.
   Handle<SharedFunctionInfo> result = factory->NewSharedFunctionInfo(
-      literal->name(), literal->materialized_literal_count(),
-      literal->is_generator(), literal->is_arrow(), info.code(), scope_info,
-      info.feedback_vector());
+      literal->name(), literal->materialized_literal_count(), literal->kind(),
+      info.code(), scope_info, info.feedback_vector());
   SetFunctionInfo(result, literal, false, script);
   RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
   result->set_allows_lazy_compilation(allow_lazy);
index e8d2291..ae80021 100644 (file)
@@ -553,14 +553,20 @@ class Context: public FixedArray {
     return kHeaderSize + index * kPointerSize - kHeapObjectTag;
   }
 
-  static int FunctionMapIndex(StrictMode strict_mode, bool is_generator) {
-    return is_generator
-      ? (strict_mode == SLOPPY
-         ? SLOPPY_GENERATOR_FUNCTION_MAP_INDEX
-         : STRICT_GENERATOR_FUNCTION_MAP_INDEX)
-      : (strict_mode == SLOPPY
-         ? SLOPPY_FUNCTION_MAP_INDEX
-         : STRICT_FUNCTION_MAP_INDEX);
+  static int FunctionMapIndex(StrictMode strict_mode, FunctionKind kind) {
+    if (IsGeneratorFunction(kind)) {
+      return strict_mode == SLOPPY ? SLOPPY_GENERATOR_FUNCTION_MAP_INDEX
+                                   : STRICT_GENERATOR_FUNCTION_MAP_INDEX;
+    }
+
+    if (IsConciseMethod(kind)) {
+      return strict_mode == SLOPPY
+                 ? SLOPPY_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX
+                 : STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX;
+    }
+
+    return strict_mode == SLOPPY ? SLOPPY_FUNCTION_MAP_INDEX
+                                 : STRICT_FUNCTION_MAP_INDEX;
   }
 
   static const int kSize = kHeaderSize + NATIVE_CONTEXT_SLOTS * kPointerSize;
index 6688cc1..f931b7f 100644 (file)
@@ -1237,6 +1237,9 @@ void Factory::InitializeFunction(Handle<JSFunction> function,
   function->set_prototype_or_initial_map(*the_hole_value());
   function->set_literals_or_bindings(*empty_fixed_array());
   function->set_next_function_link(*undefined_value());
+
+  // TODO(arv): This does not look correct. We need to make sure we use
+  // a Map that has no prototype property.
   if (info->is_arrow()) function->RemovePrototype();
 }
 
@@ -1356,8 +1359,7 @@ Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
     Handle<SharedFunctionInfo> info,
     Handle<Context> context,
     PretenureFlag pretenure) {
-  int map_index = Context::FunctionMapIndex(info->strict_mode(),
-                                            info->is_generator());
+  int map_index = Context::FunctionMapIndex(info->strict_mode(), info->kind());
   Handle<Map> map(Map::cast(context->native_context()->get(map_index)));
   Handle<JSFunction> result = NewFunction(map, info, context, pretenure);
 
@@ -1904,13 +1906,14 @@ Handle<FixedArray> Factory::NewTypeFeedbackVector(int slot_count) {
 
 
 Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
-    Handle<String> name, int number_of_literals, bool is_generator,
-    bool is_arrow, Handle<Code> code, Handle<ScopeInfo> scope_info,
+    Handle<String> name, int number_of_literals, FunctionKind kind,
+    Handle<Code> code, Handle<ScopeInfo> scope_info,
     Handle<FixedArray> feedback_vector) {
+  DCHECK(IsValidFunctionKind(kind));
   Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name, code);
   shared->set_scope_info(*scope_info);
   shared->set_feedback_vector(*feedback_vector);
-  shared->set_is_arrow(is_arrow);
+  shared->set_kind(kind);
   int literals_array_size = number_of_literals;
   // If the function contains object, regexp or array literals,
   // allocate extra space for a literals array prefix containing the
@@ -1919,7 +1922,7 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
     literals_array_size += JSFunction::kLiteralsPrefixSize;
   }
   shared->set_num_literals(literals_array_size);
-  if (is_generator) {
+  if (IsGeneratorFunction(kind)) {
     shared->set_instance_class_name(isolate()->heap()->Generator_string());
     shared->DisableOptimization(kGenerator);
   }
index 92e6d5c..47b16f5 100644 (file)
@@ -598,8 +598,8 @@ class Factory FINAL {
 
   // Allocates a new SharedFunctionInfo object.
   Handle<SharedFunctionInfo> NewSharedFunctionInfo(
-      Handle<String> name, int number_of_literals, bool is_generator,
-      bool is_arrow, Handle<Code> code, Handle<ScopeInfo> scope_info,
+      Handle<String> name, int number_of_literals, FunctionKind kind,
+      Handle<Code> code, Handle<ScopeInfo> scope_info,
       Handle<FixedArray> feedback_vector);
   Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name,
                                                    MaybeHandle<Code> code);
index fe5f443..5e85389 100644 (file)
@@ -161,6 +161,8 @@ DEFINE_BOOL(harmony_strings, false, "enable harmony string")
 DEFINE_BOOL(harmony_arrays, false, "enable harmony arrays")
 DEFINE_BOOL(harmony_arrow_functions, false, "enable harmony arrow functions")
 DEFINE_BOOL(harmony_classes, false, "enable harmony classes")
+DEFINE_BOOL(harmony_object_literals, false,
+            "enable harmony object literal extensions")
 DEFINE_BOOL(harmony, false, "enable all harmony features (except proxies)")
 
 DEFINE_IMPLICATION(harmony, harmony_scoping)
@@ -172,6 +174,7 @@ DEFINE_IMPLICATION(harmony, harmony_strings)
 DEFINE_IMPLICATION(harmony, harmony_arrays)
 DEFINE_IMPLICATION(harmony, harmony_arrow_functions)
 DEFINE_IMPLICATION(harmony, harmony_classes)
+DEFINE_IMPLICATION(harmony, harmony_object_literals)
 DEFINE_IMPLICATION(harmony_modules, harmony_scoping)
 
 DEFINE_IMPLICATION(harmony, es_staging)
index cfbef49..aee5ca7 100644 (file)
@@ -1547,11 +1547,9 @@ void FullCodeGenerator::VisitNativeFunctionLiteral(
   const int literals = fun->NumberOfLiterals();
   Handle<Code> code = Handle<Code>(fun->shared()->code());
   Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
-  bool is_generator = false;
-  bool is_arrow = false;
   Handle<SharedFunctionInfo> shared =
       isolate()->factory()->NewSharedFunctionInfo(
-          name, literals, is_generator, is_arrow, code,
+          name, literals, FunctionKind::kNormalFunction, code,
           Handle<ScopeInfo>(fun->shared()->scope_info()),
           Handle<FixedArray>(fun->shared()->feedback_vector()));
   shared->set_construct_stub(*construct_stub);
index cc31be1..55bb572 100644 (file)
@@ -756,6 +756,41 @@ enum MinusZeroMode {
   FAIL_ON_MINUS_ZERO
 };
 
+
+enum FunctionKind {
+  kNormalFunction = 0,
+  kArrowFunction = 1,
+  kGeneratorFunction = 2,
+  kConciseMethod = 4
+};
+
+
+inline bool IsValidFunctionKind(FunctionKind kind) {
+  // At the moment these are mutually exclusive but in the future that wont be
+  // the case since ES6 allows concise generator methods.
+  return kind == FunctionKind::kNormalFunction ||
+         kind == FunctionKind::kArrowFunction ||
+         kind == FunctionKind::kGeneratorFunction ||
+         kind == FunctionKind::kConciseMethod;
+}
+
+
+inline bool IsArrowFunction(FunctionKind kind) {
+  DCHECK(IsValidFunctionKind(kind));
+  return kind & FunctionKind::kArrowFunction;
+}
+
+
+inline bool IsGeneratorFunction(FunctionKind kind) {
+  DCHECK(IsValidFunctionKind(kind));
+  return kind & FunctionKind::kGeneratorFunction;
+}
+
+
+inline bool IsConciseMethod(FunctionKind kind) {
+  DCHECK(IsValidFunctionKind(kind));
+  return kind & FunctionKind::kConciseMethod;
+}
 } }  // namespace v8::internal
 
 namespace i = v8::internal;
index 1c32400..bcf5492 100644 (file)
@@ -7481,18 +7481,20 @@ class HFunctionLiteral FINAL : public HTemplateInstruction<1> {
   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
   bool pretenure() const { return pretenure_; }
   bool has_no_literals() const { return has_no_literals_; }
-  bool is_generator() const { return is_generator_; }
+  bool is_arrow() const { return IsArrowFunction(kind_); }
+  bool is_generator() const { return IsGeneratorFunction(kind_); }
+  bool is_concise_method() const { return IsConciseMethod(kind_); }
+  FunctionKind kind() const { return kind_; }
   StrictMode strict_mode() const { return strict_mode_; }
 
  private:
-  HFunctionLiteral(HValue* context,
-                   Handle<SharedFunctionInfo> shared,
+  HFunctionLiteral(HValue* context, Handle<SharedFunctionInfo> shared,
                    bool pretenure)
       : HTemplateInstruction<1>(HType::JSObject()),
         shared_info_(shared),
+        kind_(shared->kind()),
         pretenure_(pretenure),
         has_no_literals_(shared->num_literals() == 0),
-        is_generator_(shared->is_generator()),
         strict_mode_(shared->strict_mode()) {
     SetOperandAt(0, context);
     set_representation(Representation::Tagged());
@@ -7502,9 +7504,9 @@ class HFunctionLiteral FINAL : public HTemplateInstruction<1> {
   virtual bool IsDeletable() const OVERRIDE { return true; }
 
   Handle<SharedFunctionInfo> shared_info_;
+  FunctionKind kind_;
   bool pretenure_ : 1;
   bool has_no_literals_ : 1;
-  bool is_generator_ : 1;
   StrictMode strict_mode_;
 };
 
index 1990f68..db1430b 100644 (file)
@@ -1254,9 +1254,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
       !pretenure &&
       scope()->is_function_scope() &&
       info->num_literals() == 0) {
-    FastNewClosureStub stub(isolate(),
-                            info->strict_mode(),
-                            info->is_generator());
+    FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
     __ mov(ebx, Immediate(info));
     __ CallStub(&stub);
   } else {
index c094596..d9504c7 100644 (file)
@@ -5290,9 +5290,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
   // space for nested functions that don't need literals cloning.
   bool pretenure = instr->hydrogen()->pretenure();
   if (!pretenure && instr->hydrogen()->has_no_literals()) {
-    FastNewClosureStub stub(isolate(),
-                            instr->hydrogen()->strict_mode(),
-                            instr->hydrogen()->is_generator());
+    FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
+                            instr->hydrogen()->kind());
     __ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   } else {
index 62205bd..e5ef9ec 100644 (file)
@@ -1319,9 +1319,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
       !pretenure &&
       scope()->is_function_scope() &&
       info->num_literals() == 0) {
-    FastNewClosureStub stub(isolate(),
-                            info->strict_mode(),
-                            info->is_generator());
+    FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
     __ li(a2, Operand(info));
     __ CallStub(&stub);
   } else {
index 978ef73..aca6bb3 100644 (file)
@@ -5479,9 +5479,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
   // space for nested functions that don't need literals cloning.
   bool pretenure = instr->hydrogen()->pretenure();
   if (!pretenure && instr->hydrogen()->has_no_literals()) {
-    FastNewClosureStub stub(isolate(),
-                            instr->hydrogen()->strict_mode(),
-                            instr->hydrogen()->is_generator());
+    FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
+                            instr->hydrogen()->kind());
     __ li(a2, Operand(instr->hydrogen()->shared_info()));
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   } else {
index 4b3a644..5341599 100644 (file)
@@ -1314,9 +1314,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
       !pretenure &&
       scope()->is_function_scope() &&
       info->num_literals() == 0) {
-    FastNewClosureStub stub(isolate(),
-                            info->strict_mode(),
-                            info->is_generator());
+    FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
     __ li(a2, Operand(info));
     __ CallStub(&stub);
   } else {
index 8a58d4b..7da40ff 100644 (file)
@@ -5519,9 +5519,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
   // space for nested functions that don't need literals cloning.
   bool pretenure = instr->hydrogen()->pretenure();
   if (!pretenure && instr->hydrogen()->has_no_literals()) {
-    FastNewClosureStub stub(isolate(),
-                            instr->hydrogen()->strict_mode(),
-                            instr->hydrogen()->is_generator());
+    FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
+                            instr->hydrogen()->kind());
     __ li(a2, Operand(instr->hydrogen()->shared_info()));
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   } else {
index 1fffea2..20a12b6 100644 (file)
@@ -5559,6 +5559,19 @@ void SharedFunctionInfo::set_strict_mode(StrictMode strict_mode) {
 }
 
 
+FunctionKind SharedFunctionInfo::kind() {
+  return FunctionKindBits::decode(compiler_hints());
+}
+
+
+void SharedFunctionInfo::set_kind(FunctionKind kind) {
+  DCHECK(IsValidFunctionKind(kind));
+  int hints = compiler_hints();
+  hints = FunctionKindBits::update(hints, kind);
+  set_compiler_hints(hints);
+}
+
+
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, inline_builtin,
                kInlineBuiltin)
@@ -5570,8 +5583,10 @@ BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_cache, kDontCache)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush)
-BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_arrow, kIsArrow)
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator)
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_concise_method,
+               kIsConciseMethod)
 
 ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
 ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
index add8337..32dd94f 100644 (file)
@@ -7121,6 +7121,12 @@ class SharedFunctionInfo: public HeapObject {
   // Indicates that this function is an arrow function.
   DECL_BOOLEAN_ACCESSORS(is_arrow)
 
+  // Indicates that this function is a concise method.
+  DECL_BOOLEAN_ACCESSORS(is_concise_method)
+
+  inline FunctionKind kind();
+  inline void set_kind(FunctionKind kind);
+
   // Indicates whether or not the code in the shared function support
   // deoptimization.
   inline bool has_deoptimization_support();
@@ -7315,17 +7321,20 @@ class SharedFunctionInfo: public HeapObject {
     kIsFunction,
     kDontCache,
     kDontFlush,
-    kIsGenerator,
     kIsArrow,
+    kIsGenerator,
+    kIsConciseMethod,
     kCompilerHintsCount  // Pseudo entry
   };
 
-  class DeoptCountBits: public BitField<int, 0, 4> {};
-  class OptReenableTriesBits: public BitField<int, 4, 18> {};
-  class ICAgeBits: public BitField<int, 22, 8> {};
+  class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 3> {};
+
+  class DeoptCountBits : public BitField<int, 0, 4> {};
+  class OptReenableTriesBits : public BitField<int, 4, 18> {};
+  class ICAgeBits : public BitField<int, 22, 8> {};
 
-  class OptCountBits: public BitField<int, 0, 22> {};
-  class DisabledOptimizationReasonBits: public BitField<int, 22, 8> {};
+  class OptCountBits : public BitField<int, 0, 22> {};
+  class DisabledOptimizationReasonBits : public BitField<int, 22, 8> {};
 
  private:
 #if V8_HOST_ARCH_32_BIT
index d385efe..b5f9c1b 100644 (file)
@@ -724,18 +724,13 @@ Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
 
 
 FunctionLiteral* ParserTraits::ParseFunctionLiteral(
-    const AstRawString* name,
-    Scanner::Location function_name_location,
-    bool name_is_strict_reserved,
-    bool is_generator,
-    int function_token_position,
-    FunctionLiteral::FunctionType type,
-    FunctionLiteral::ArityRestriction arity_restriction,
-    bool* ok) {
-  return parser_->ParseFunctionLiteral(name, function_name_location,
-                                       name_is_strict_reserved, is_generator,
-                                       function_token_position, type,
-                                       arity_restriction, ok);
+    const AstRawString* name, Scanner::Location function_name_location,
+    bool name_is_strict_reserved, 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,
+      function_token_position, type, arity_restriction, ok);
 }
 
 
@@ -767,6 +762,7 @@ Parser::Parser(CompilationInfo* info, ParseInfo* parse_info)
   set_allow_arrow_functions(FLAG_harmony_arrow_functions);
   set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
   set_allow_classes(FLAG_harmony_classes);
+  set_allow_harmony_object_literals(FLAG_harmony_object_literals);
   for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
        ++feature) {
     use_counts_[feature] = 0;
@@ -911,8 +907,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
           function_state.handler_count(), 0,
           FunctionLiteral::kNoDuplicateParameters,
           FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval,
-          FunctionLiteral::kNotParenthesized, FunctionLiteral::kNormalFunction,
-          0);
+          FunctionLiteral::kNotParenthesized, FunctionKind::kNormalFunction, 0);
       result->set_ast_properties(factory()->visitor()->ast_properties());
       result->set_dont_optimize_reason(
           factory()->visitor()->dont_optimize_reason());
@@ -999,18 +994,16 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
               ? FunctionLiteral::ANONYMOUS_EXPRESSION
               : FunctionLiteral::NAMED_EXPRESSION)
         : FunctionLiteral::DECLARATION;
-    bool is_generator = shared_info->is_generator();
     bool ok = true;
 
     if (shared_info->is_arrow()) {
-      DCHECK(!is_generator);
       Expression* expression = ParseExpression(false, &ok);
       DCHECK(expression->IsFunctionLiteral());
       result = expression->AsFunctionLiteral();
     } else {
       result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
                                     false,  // Strict mode name already checked.
-                                    is_generator, RelocInfo::kNoPosition,
+                                    shared_info->kind(), RelocInfo::kNoPosition,
                                     function_type,
                                     FunctionLiteral::NORMAL_ARITY, &ok);
     }
@@ -1894,14 +1887,12 @@ Statement* Parser::ParseFunctionDeclaration(
   bool is_strict_reserved = false;
   const AstRawString* name = ParseIdentifierOrStrictReservedWord(
       &is_strict_reserved, CHECK_OK);
-  FunctionLiteral* fun = ParseFunctionLiteral(name,
-                                              scanner()->location(),
-                                              is_strict_reserved,
-                                              is_generator,
-                                              pos,
-                                              FunctionLiteral::DECLARATION,
-                                              FunctionLiteral::NORMAL_ARITY,
-                                              CHECK_OK);
+  FunctionLiteral* fun =
+      ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
+                           is_generator ? FunctionKind::kGeneratorFunction
+                                        : FunctionKind::kNormalFunction,
+                           pos, FunctionLiteral::DECLARATION,
+                           FunctionLiteral::NORMAL_ARITY, CHECK_OK);
   // Even if we're not at the top-level of the global or a function
   // scope, we treat it as such and introduce the function with its
   // initial value upon entering the corresponding scope.
@@ -3365,14 +3356,10 @@ int ParserTraits::DeclareArrowParametersFromExpression(
 
 
 FunctionLiteral* Parser::ParseFunctionLiteral(
-    const AstRawString* function_name,
-    Scanner::Location function_name_location,
-    bool name_is_strict_reserved,
-    bool is_generator,
-    int function_token_pos,
+    const AstRawString* function_name, Scanner::Location function_name_location,
+    bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
     FunctionLiteral::FunctionType function_type,
-    FunctionLiteral::ArityRestriction arity_restriction,
-    bool* ok) {
+    FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
   // Function ::
   //   '(' FormalParameterList? ')' '{' FunctionBody '}'
   //
@@ -3385,6 +3372,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
   int pos = function_token_pos == RelocInfo::kNoPosition
       ? peek_position() : function_token_pos;
 
+  bool is_generator = IsGeneratorFunction(kind);
+
   // Anonymous functions were passed either the empty symbol or a null
   // handle as the function name.  Remember if we were passed a non-empty
   // handle to decide whether to invoke function name inference.
@@ -3593,7 +3582,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
     }
 
     // Validate strict mode.
-    if (strict_mode() == STRICT) {
+    // Concise methods use StrictFormalParameters.
+    if (strict_mode() == STRICT || IsConciseMethod(kind)) {
       CheckStrictFunctionNameAndParameters(function_name,
                                            name_is_strict_reserved,
                                            function_name_location,
@@ -3601,6 +3591,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
                                            dupe_error_loc,
                                            reserved_loc,
                                            CHECK_OK);
+    }
+    if (strict_mode() == STRICT) {
       CheckOctalLiteral(scope->start_position(),
                         scope->end_position(),
                         CHECK_OK);
@@ -3613,9 +3605,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
     }
   }
 
-  FunctionLiteral::KindFlag kind = is_generator
-                                       ? FunctionLiteral::kGeneratorFunction
-                                       : FunctionLiteral::kNormalFunction;
   FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
       function_name, ast_value_factory_, scope, body,
       materialized_literal_count, expected_property_count, handler_count,
@@ -3775,6 +3764,8 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
     reusable_preparser_->set_allow_harmony_numeric_literals(
         allow_harmony_numeric_literals());
     reusable_preparser_->set_allow_classes(allow_classes());
+    reusable_preparser_->set_allow_harmony_object_literals(
+        allow_harmony_object_literals());
   }
   PreParser::PreParseResult result =
       reusable_preparser_->PreParseLazyFunction(strict_mode(),
index c975471..a344252 100644 (file)
@@ -573,14 +573,10 @@ class ParserTraits {
   // Temporary glue; these functions will move to ParserBase.
   Expression* ParseV8Intrinsic(bool* ok);
   FunctionLiteral* ParseFunctionLiteral(
-      const AstRawString* name,
-      Scanner::Location function_name_location,
-      bool name_is_strict_reserved,
-      bool is_generator,
-      int function_token_position,
-      FunctionLiteral::FunctionType type,
-      FunctionLiteral::ArityRestriction arity_restriction,
-      bool* ok);
+      const AstRawString* name, Scanner::Location function_name_location,
+      bool name_is_strict_reserved, FunctionKind kind,
+      int function_token_position, FunctionLiteral::FunctionType type,
+      FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
   V8_INLINE void SkipLazyFunctionBody(const AstRawString* name,
                                       int* materialized_literal_count,
                                       int* expected_property_count, bool* ok);
@@ -746,14 +742,10 @@ class Parser : public ParserBase<ParserTraits> {
       Statement* body, bool* ok);
 
   FunctionLiteral* ParseFunctionLiteral(
-      const AstRawString* name,
-      Scanner::Location function_name_location,
-      bool name_is_strict_reserved,
-      bool is_generator,
-      int function_token_position,
-      FunctionLiteral::FunctionType type,
-      FunctionLiteral::ArityRestriction arity_restriction,
-      bool* ok);
+      const AstRawString* name, Scanner::Location function_name_location,
+      bool name_is_strict_reserved, FunctionKind kind,
+      int function_token_position, FunctionLiteral::FunctionType type,
+      FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
 
   // Magical syntax support.
   Expression* ParseV8Intrinsic(bool* ok);
index f100f4a..b658f5c 100644 (file)
@@ -102,16 +102,12 @@ 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,
-    FunctionLiteral::ArityRestriction arity_restriction,
-    bool* ok) {
+    PreParserIdentifier name, Scanner::Location function_name_location,
+    bool name_is_strict_reserved, 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, is_generator,
+      name, function_name_location, name_is_strict_reserved, kind,
       function_token_position, type, arity_restriction, ok);
 }
 
@@ -340,14 +336,11 @@ 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,
-                       is_generator,
-                       pos,
-                       FunctionLiteral::DECLARATION,
-                       FunctionLiteral::NORMAL_ARITY,
-                       CHECK_OK);
+  ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
+                       is_generator ? FunctionKind::kGeneratorFunction
+                                    : FunctionKind::kNormalFunction,
+                       pos, FunctionLiteral::DECLARATION,
+                       FunctionLiteral::NORMAL_ARITY, CHECK_OK);
   return Statement::FunctionDeclaration();
 }
 
@@ -805,14 +798,10 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
 
 
 PreParser::Expression PreParser::ParseFunctionLiteral(
-    Identifier function_name,
-    Scanner::Location function_name_location,
-    bool name_is_strict_reserved,
-    bool is_generator,
-    int function_token_pos,
+    Identifier function_name, Scanner::Location function_name_location,
+    bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
     FunctionLiteral::FunctionType function_type,
-    FunctionLiteral::ArityRestriction arity_restriction,
-    bool* ok) {
+    FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
   // Function ::
   //   '(' FormalParameterList? ')' '{' FunctionBody '}'
 
@@ -821,7 +810,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
   PreParserScope function_scope(scope_, FUNCTION_SCOPE);
   FunctionState function_state(&function_state_, &scope_, &function_scope, NULL,
                                this->ast_value_factory());
-  function_state.set_is_generator(is_generator);
+  function_state.set_is_generator(IsGeneratorFunction(kind));
   //  FormalParameterList ::
   //    '(' (Identifier)*[','] ')'
   Expect(Token::LPAREN, CHECK_OK);
@@ -876,7 +865,8 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
 
   // Validate strict mode. We can do this only after parsing the function,
   // since the function can declare itself strict.
-  if (strict_mode() == STRICT) {
+  // Concise methods use StrictFormalParameters.
+  if (strict_mode() == STRICT || IsConciseMethod(kind)) {
     if (function_name.IsEvalOrArguments()) {
       ReportMessageAt(function_name_location, "strict_eval_arguments");
       *ok = false;
index 87addfb..15887ba 100644 (file)
@@ -85,6 +85,7 @@ class ParserBase : public Traits {
         allow_natives_syntax_(false),
         allow_generators_(false),
         allow_arrow_functions_(false),
+        allow_harmony_object_literals_(false),
         zone_(zone),
         ast_node_id_gen_(ast_node_id_gen) {}
 
@@ -100,6 +101,9 @@ class ParserBase : public Traits {
     return scanner()->HarmonyNumericLiterals();
   }
   bool allow_classes() const { return scanner()->HarmonyClasses(); }
+  bool allow_harmony_object_literals() const {
+    return allow_harmony_object_literals_;
+  }
 
   // Setters that determine whether certain syntactical constructs are
   // allowed to be parsed by this instance of the parser.
@@ -114,8 +118,9 @@ class ParserBase : public Traits {
   void set_allow_harmony_numeric_literals(bool allow) {
     scanner()->SetHarmonyNumericLiterals(allow);
   }
-  void set_allow_classes(bool allow) {
-    scanner()->SetHarmonyClasses(allow);
+  void set_allow_classes(bool allow) { scanner()->SetHarmonyClasses(allow); }
+  void set_allow_harmony_object_literals(bool allow) {
+    allow_harmony_object_literals_ = allow;
   }
 
  protected:
@@ -481,6 +486,7 @@ class ParserBase : public Traits {
   ExpressionT ParseObjectLiteral(bool* ok);
   ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker,
                                                  bool* ok);
+  IdentifierT ParsePropertyName(bool* is_getter, bool* is_setter, bool* ok);
   typename Traits::Type::ExpressionList ParseArguments(bool* ok);
   ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
   ExpressionT ParseYieldExpression(bool* ok);
@@ -579,6 +585,7 @@ class ParserBase : public Traits {
   bool allow_natives_syntax_;
   bool allow_generators_;
   bool allow_arrow_functions_;
+  bool allow_harmony_object_literals_;
 
   typename Traits::Type::Zone* zone_;  // Only used by Parser.
   AstNode::IdGen* ast_node_id_gen_;
@@ -1054,8 +1061,8 @@ class PreParserFactory {
       FunctionLiteral::ParameterFlag has_duplicate_parameters,
       FunctionLiteral::FunctionType function_type,
       FunctionLiteral::IsFunctionFlag is_function,
-      FunctionLiteral::IsParenthesizedFlag is_parenthesized,
-      FunctionLiteral::KindFlag kind, int position) {
+      FunctionLiteral::IsParenthesizedFlag is_parenthesized, FunctionKind kind,
+      int position) {
     return PreParserExpression::Default();
   }
 
@@ -1331,14 +1338,10 @@ class PreParserTraits {
   // Temporary glue; these functions will move to ParserBase.
   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,
-      FunctionLiteral::ArityRestriction arity_restriction,
-      bool* ok);
+      PreParserIdentifier name, Scanner::Location function_name_location,
+      bool name_is_strict_reserved, FunctionKind kind,
+      int function_token_position, FunctionLiteral::FunctionType type,
+      FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
 
  private:
   PreParser* pre_parser_;
@@ -1469,14 +1472,10 @@ class PreParser : public ParserBase<PreParserTraits> {
                              bool is_generator, bool* ok);
 
   Expression ParseFunctionLiteral(
-      Identifier name,
-      Scanner::Location function_name_location,
-      bool name_is_strict_reserved,
-      bool is_generator,
-      int function_token_pos,
+      Identifier name, Scanner::Location function_name_location,
+      bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
       FunctionLiteral::FunctionType function_type,
-      FunctionLiteral::ArityRestriction arity_restriction,
-      bool* ok);
+      FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
   void ParseLazyFunctionLiteralBody(bool* ok);
 
   bool CheckInOrOf(bool accept_OF);
@@ -1852,84 +1851,85 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
 
 
 template <class Traits>
-typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
-    Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, bool* ok) {
-  LiteralT key = this->EmptyLiteral();
+typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParsePropertyName(
+    bool* is_getter, bool* is_setter, bool* ok) {
   Token::Value next = peek();
-  int next_pos = peek_position();
-
   switch (next) {
-    case Token::STRING: {
+    case Token::STRING:
       Consume(Token::STRING);
-      IdentifierT 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()->NewStringLiteral(string, next_pos);
-      break;
-    }
-    case Token::NUMBER: {
+      return this->GetSymbol(scanner_);
+    case Token::NUMBER:
       Consume(Token::NUMBER);
-      key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_,
-                                        factory());
-      break;
-    }
-    default: {
-      bool is_getter = false;
-      bool is_setter = false;
-      IdentifierT id = ParseIdentifierNameOrGetOrSet(
-          &is_getter, &is_setter, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
-      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.
-        IdentifierT name = this->EmptyIdentifier();
-        switch (peek()) {
-          case Token::STRING:
-            Consume(Token::STRING);
-            name = this->GetSymbol(scanner_);
-            break;
-          case Token::NUMBER:
-            Consume(Token::NUMBER);
-            name = this->GetNumberAsSymbol(scanner_);
-            break;
-          default:
-            name = ParseIdentifierName(
-                CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
-        }
-        // Validate the property.
-        PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
-        checker->CheckProperty(next, type,
-                               CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
-        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,
-                is_getter ? FunctionLiteral::GETTER_ARITY
-                          : FunctionLiteral::SETTER_ARITY,
-                CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
-        return factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
-      }
-      // 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()->NewStringLiteral(id, next_pos);
-    }
+      return this->GetNumberAsSymbol(scanner_);
+    default:
+      return ParseIdentifierNameOrGetOrSet(is_getter, is_setter,
+                                           CHECK_OK_CUSTOM(EmptyIdentifier));
   }
+}
+
 
-  // Validate the property
-  checker->CheckProperty(next, kValueProperty,
-                         CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+template <class Traits>
+typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
+    Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, bool* ok) {
+  // TODO(arv): Add support for concise generator methods.
+  ExpressionT value = this->EmptyExpression();
+  bool is_getter = false;
+  bool is_setter = false;
+  Token::Value name_token = peek();
+  int next_pos = peek_position();
+  IdentifierT name = ParsePropertyName(
+      &is_getter, &is_setter, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+  if (fni_ != NULL) this->PushLiteralName(fni_, name);
+
+  if (peek() == Token::COLON) {
+    // PropertyDefinition : PropertyName ':' AssignmentExpression
+    checker->CheckProperty(name_token, kValueProperty,
+                           CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+    Consume(Token::COLON);
+    value = this->ParseAssignmentExpression(
+        true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+
+  } else if (allow_harmony_object_literals_ && peek() == Token::LPAREN) {
+    // Concise Method
+    checker->CheckProperty(name_token, kValueProperty,
+                           CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+    value = this->ParseFunctionLiteral(
+        name, scanner()->location(),
+        false,  // reserved words are allowed here
+        FunctionKind::kConciseMethod, RelocInfo::kNoPosition,
+        FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::NORMAL_ARITY,
+        CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+
+  } else if (is_getter || is_setter) {
+    // Accessor
+    bool dont_care = false;
+    name_token = peek();
+    name = ParsePropertyName(&dont_care, &dont_care,
+                             CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+    // Validate the property.
+    checker->CheckProperty(name_token,
+                           is_getter ? kGetterProperty : kSetterProperty,
+                           CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+    typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral(
+        name, scanner()->location(),
+        false,  // reserved words are allowed here
+        FunctionKind::kNormalFunction, RelocInfo::kNoPosition,
+        FunctionLiteral::ANONYMOUS_EXPRESSION,
+        is_getter ? FunctionLiteral::GETTER_ARITY
+                  : FunctionLiteral::SETTER_ARITY,
+        CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+    return factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
+  } else {
+    Token::Value next = Next();
+    ReportUnexpectedToken(next);
+    *ok = false;
+    return this->EmptyObjectLiteralProperty();
+  }
 
-  Expect(Token::COLON, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
-  ExpressionT value = this->ParseAssignmentExpression(
-      true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+  uint32_t index;
+  LiteralT key = this->IsArrayIndex(name, &index)
+                     ? factory()->NewNumberLiteral(index, next_pos)
+                     : factory()->NewStringLiteral(name, next_pos);
 
   return factory()->NewObjectLiteralProperty(key, value);
 }
@@ -2428,14 +2428,12 @@ ParserBase<Traits>::ParseMemberExpression(bool* ok) {
       function_name_location = scanner()->location();
       function_type = FunctionLiteral::NAMED_EXPRESSION;
     }
-    result = this->ParseFunctionLiteral(name,
-                                        function_name_location,
-                                        is_strict_reserved_name,
-                                        is_generator,
-                                        function_token_position,
-                                        function_type,
-                                        FunctionLiteral::NORMAL_ARITY,
-                                        CHECK_OK);
+    result = this->ParseFunctionLiteral(
+        name, function_name_location, is_strict_reserved_name,
+        is_generator ? FunctionKind::kGeneratorFunction
+                     : FunctionKind::kNormalFunction,
+        function_token_position, function_type, FunctionLiteral::NORMAL_ARITY,
+        CHECK_OK);
   } else if (peek() == Token::SUPER) {
     int beg_pos = position();
     Consume(Token::SUPER);
@@ -2596,7 +2594,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<
       materialized_literal_count, expected_property_count, handler_count,
       num_parameters, FunctionLiteral::kNoDuplicateParameters,
       FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction,
-      FunctionLiteral::kNotParenthesized, FunctionLiteral::kArrowFunction,
+      FunctionLiteral::kNotParenthesized, FunctionKind::kArrowFunction,
       start_pos);
 
   function_literal->set_function_token_position(start_pos);
index d18c22c..77c7bb9 100644 (file)
@@ -2775,6 +2775,14 @@ RUNTIME_FUNCTION(Runtime_FunctionIsArrow) {
 }
 
 
+RUNTIME_FUNCTION(Runtime_FunctionIsConciseMethod) {
+  SealHandleScope shs(isolate);
+  DCHECK(args.length() == 1);
+  CONVERT_ARG_CHECKED(JSFunction, f, 0);
+  return isolate->heap()->ToBoolean(f->shared()->is_concise_method());
+}
+
+
 RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) {
   SealHandleScope shs(isolate);
   DCHECK(args.length() == 1);
@@ -8125,8 +8133,8 @@ RUNTIME_FUNCTION(Runtime_NewClosureFromStubFailure) {
   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
   Handle<Context> context(isolate->context());
   PretenureFlag pretenure_flag = NOT_TENURED;
-  return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
-      shared,  context, pretenure_flag);
+  return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
+                                                                pretenure_flag);
 }
 
 
index 6be7515..4f11c2e 100644 (file)
@@ -197,6 +197,7 @@ namespace internal {
   F(FunctionMarkNameShouldPrintAsAnonymous, 1, 1)                     \
   F(FunctionIsGenerator, 1, 1)                                        \
   F(FunctionIsArrow, 1, 1)                                            \
+  F(FunctionIsConciseMethod, 1, 1)                                    \
   F(FunctionBindArguments, 4, 1)                                      \
   F(BoundFunctionGetBindings, 1, 1)                                   \
   F(FunctionRemovePrototype, 1, 1)                                    \
index a522738..405e7d6 100644 (file)
@@ -1757,7 +1757,12 @@ function FunctionSourceString(func) {
   var name = %FunctionNameShouldPrintAsAnonymous(func)
       ? 'anonymous'
       : %FunctionGetName(func);
-  var head = %FunctionIsGenerator(func) ? 'function* ' : 'function ';
+
+  // TODO(arv): Handle concise generator methods.
+
+  var head = %FunctionIsConciseMethod(func)
+      ? ''
+      : %FunctionIsGenerator(func) ? 'function* ' : 'function ';
   return head + name + source;
 }
 
index fd6bcae..5babef0 100644 (file)
@@ -1288,9 +1288,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
       !pretenure &&
       scope()->is_function_scope() &&
       info->num_literals() == 0) {
-    FastNewClosureStub stub(isolate(),
-                            info->strict_mode(),
-                            info->is_generator());
+    FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
     __ Move(rbx, info);
     __ CallStub(&stub);
   } else {
index c39833e..c59d9e0 100644 (file)
@@ -5457,9 +5457,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
   // space for nested functions that don't need literals cloning.
   bool pretenure = instr->hydrogen()->pretenure();
   if (!pretenure && instr->hydrogen()->has_no_literals()) {
-    FastNewClosureStub stub(isolate(),
-                            instr->hydrogen()->strict_mode(),
-                            instr->hydrogen()->is_generator());
+    FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
+                            instr->hydrogen()->kind());
     __ Move(rbx, instr->hydrogen()->shared_info());
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   } else {
index a9b2b31..78d2ec0 100644 (file)
@@ -1251,9 +1251,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
       !pretenure &&
       scope()->is_function_scope() &&
       info->num_literals() == 0) {
-    FastNewClosureStub stub(isolate(),
-                            info->strict_mode(),
-                            info->is_generator());
+    FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
     __ mov(ebx, Immediate(info));
     __ CallStub(&stub);
   } else {
index 6a3f991..07c9fb0 100644 (file)
@@ -5295,9 +5295,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
   // space for nested functions that don't need literals cloning.
   bool pretenure = instr->hydrogen()->pretenure();
   if (!pretenure && instr->hydrogen()->has_no_literals()) {
-    FastNewClosureStub stub(isolate(),
-                            instr->hydrogen()->strict_mode(),
-                            instr->hydrogen()->is_generator());
+    FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
+                            instr->hydrogen()->kind());
     __ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   } else {
index f4400a4..fea34a8 100644 (file)
@@ -1217,7 +1217,8 @@ enum ParserFlag {
   kAllowGenerators,
   kAllowHarmonyNumericLiterals,
   kAllowArrowFunctions,
-  kAllowClasses
+  kAllowClasses,
+  kAllowHarmonyObjectLiterals
 };
 
 
@@ -1237,6 +1238,8 @@ void SetParserFlags(i::ParserBase<Traits>* parser,
   parser->set_allow_generators(flags.Contains(kAllowGenerators));
   parser->set_allow_harmony_numeric_literals(
       flags.Contains(kAllowHarmonyNumericLiterals));
+  parser->set_allow_harmony_object_literals(
+      flags.Contains(kAllowHarmonyObjectLiterals));
   parser->set_allow_arrow_functions(flags.Contains(kAllowArrowFunctions));
   parser->set_allow_classes(flags.Contains(kAllowClasses));
 }
@@ -1446,9 +1449,11 @@ TEST(ParserSync) {
   CcTest::i_isolate()->stack_guard()->SetStackLimit(
       i::GetCurrentStackPosition() - 128 * 1024);
 
-  static const ParserFlag flags1[] = {kAllowLazy, kAllowHarmonyScoping,
-                                      kAllowModules, kAllowGenerators,
-                                      kAllowArrowFunctions};
+  static const ParserFlag flags1[] = {
+      kAllowLazy,                 kAllowHarmonyScoping,
+      kAllowModules,              kAllowGenerators,
+      kAllowArrowFunctions,       kAllowHarmonyNumericLiterals,
+      kAllowHarmonyObjectLiterals};
   for (int i = 0; context_data[i][0] != NULL; ++i) {
     for (int j = 0; statement_data[j] != NULL; ++j) {
       for (int k = 0; termination_data[k] != NULL; ++k) {
@@ -1523,9 +1528,12 @@ void RunParserSyncTest(const char* context_data[][2],
       i::GetCurrentStackPosition() - 128 * 1024);
 
   static const ParserFlag default_flags[] = {
-      kAllowLazy,       kAllowHarmonyScoping, kAllowModules,
-      kAllowGenerators, kAllowNativesSyntax,  kAllowArrowFunctions,
-      kAllowClasses};
+      kAllowArrowFunctions,        kAllowClasses,
+      kAllowGenerators,            kAllowHarmonyNumericLiterals,
+      kAllowHarmonyObjectLiterals, kAllowHarmonyScoping,
+      kAllowLazy,                  kAllowModules,
+      kAllowNativesSyntax,
+  };
   ParserFlag* generated_flags = NULL;
   if (flags == NULL) {
     flags = default_flags;
@@ -2520,23 +2528,36 @@ TEST(ErrorsObjectLiteralChecking) {
   };
 
   const char* statement_data[] = {
-      ",", "foo: 1, get foo() {}", "foo: 1, set foo(v) {}",
-      "\"foo\": 1, get \"foo\"() {}", "\"foo\": 1, set \"foo\"(v) {}",
-      "1: 1, get 1() {}", "1: 1, set 1() {}",
+      ",",
+      "foo: 1, get foo() {}",
+      "foo: 1, set foo(v) {}",
+      "\"foo\": 1, get \"foo\"() {}",
+      "\"foo\": 1, set \"foo\"(v) {}",
+      "1: 1, get 1() {}",
+      "1: 1, set 1() {}",
+      "get foo() {}, get foo() {}",
+      "set foo(_) {}, set foo(_) {}",
       // It's counter-intuitive, but these collide too (even in classic
       // mode). Note that we can have "foo" and foo as properties in classic
       // mode,
       // but we cannot have "foo" and get foo, or foo and get "foo".
-      "foo: 1, get \"foo\"() {}", "foo: 1, set \"foo\"(v) {}",
-      "\"foo\": 1, get foo() {}", "\"foo\": 1, set foo(v) {}",
-      "1: 1, get \"1\"() {}", "1: 1, set \"1\"() {}",
+      "foo: 1, get \"foo\"() {}",
+      "foo: 1, set \"foo\"(v) {}",
+      "\"foo\": 1, get foo() {}",
+      "\"foo\": 1, set foo(v) {}",
+      "1: 1, get \"1\"() {}",
+      "1: 1, set \"1\"() {}",
       "\"1\": 1, get 1() {}"
       "\"1\": 1, set 1(v) {}"
       // Wrong number of parameters
       "get bar(x) {}",
-      "get bar(x, y) {}", "set bar() {}", "set bar(x, y) {}",
+      "get bar(x, y) {}",
+      "set bar() {}",
+      "set bar(x, y) {}",
       // Parsing FunctionLiteral for getter or setter fails
-      "get foo( +", "get foo() \"error\"", NULL};
+      "get foo( +",
+      "get foo() \"error\"",
+      NULL};
 
   RunParserSyncTest(context_data, statement_data, kError);
 }
@@ -2573,6 +2594,8 @@ TEST(NoErrorsObjectLiteralChecking) {
     "\"foo\": 1, set \"bar\"(v) {}",
     "1: 1, get 2() {}",
     "1: 1, set 2(v) {}",
+    "get: 1, get foo() {}",
+    "set: 1, set foo(_) {}",
     // Keywords, future reserved and strict future reserved are also allowed as
     // property names.
     "if: 4",
@@ -3392,3 +3415,144 @@ TEST(ErrorsSuper) {
   RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
                     always_flags, arraysize(always_flags));
 }
+
+
+TEST(NoErrorsMethodDefinition) {
+  const char* context_data[][2] = {{"({", "});"},
+                                   {"'use strict'; ({", "});"},
+                                   {NULL, NULL}};
+
+  const char* object_literal_body_data[] = {
+    "m() {}",
+    "m(x) { return x; }",
+    "m(x, y) {}, n() {}",
+    "set(x, y) {}",
+    "get(x, y) {}",
+    NULL
+  };
+
+  static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
+  RunParserSyncTest(context_data, object_literal_body_data, kSuccess, NULL, 0,
+                    always_flags, arraysize(always_flags));
+}
+
+
+TEST(MethodDefinitionNames) {
+  const char* context_data[][2] = {{"({", "(x, y) {}});"},
+                                   {"'use strict'; ({", "(x, y) {}});"},
+                                   {NULL, NULL}};
+
+  const char* name_data[] = {
+    "m",
+    "'m'",
+    "\"m\"",
+    "\"m n\"",
+    "true",
+    "false",
+    "null",
+    "0",
+    "1.2",
+    "1e1",
+    "1E1",
+    "1e+1",
+    "1e-1",
+
+    // Keywords
+    "async",
+    "await",
+    "break",
+    "case",
+    "catch",
+    "class",
+    "const",
+    "continue",
+    "debugger",
+    "default",
+    "delete",
+    "do",
+    "else",
+    "enum",
+    "export",
+    "extends",
+    "finally",
+    "for",
+    "function",
+    "if",
+    "implements",
+    "import",
+    "in",
+    "instanceof",
+    "interface",
+    "let",
+    "new",
+    "package",
+    "private",
+    "protected",
+    "public",
+    "return",
+    "static",
+    "super",
+    "switch",
+    "this",
+    "throw",
+    "try",
+    "typeof",
+    "var",
+    "void",
+    "while",
+    "with",
+    "yield",
+    NULL
+  };
+
+  static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
+  RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
+                    always_flags, arraysize(always_flags));
+}
+
+
+TEST(MethodDefinitionStrictFormalParamereters) {
+  const char* context_data[][2] = {{"({method(", "){}});"},
+                                   {"'use strict'; ({method(", "){}});"},
+                                   {NULL, NULL}};
+
+  const char* params_data[] = {
+    "x, x",
+    "x, y, x",
+    "eval",
+    "arguments",
+    "var",
+    "const",
+    NULL
+  };
+
+  static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
+  RunParserSyncTest(context_data, params_data, kError, NULL, 0,
+                    always_flags, arraysize(always_flags));
+}
+
+
+TEST(MethodDefinitionDuplicateProperty) {
+  // Duplicate properties are allowed in ES6 but we haven't removed that check
+  // yet.
+  const char* context_data[][2] = {{"'use strict'; ({", "});"},
+                                   {NULL, NULL}};
+
+  const char* params_data[] = {
+    "x: 1, x() {}",
+    "x() {}, x: 1",
+    "x() {}, get x() {}",
+    "x() {}, set x(_) {}",
+    "x() {}, x() {}",
+    "x() {}, y() {}, x() {}",
+    "x() {}, \"x\"() {}",
+    "x() {}, 'x'() {}",
+    "0() {}, '0'() {}",
+    "1.0() {}, 1: 1",
+    NULL
+  };
+
+  static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
+  RunParserSyncTest(context_data, params_data, kError, NULL, 0,
+                    always_flags, arraysize(always_flags));
+}
diff --git a/test/mjsunit/harmony/object-literals-method.js b/test/mjsunit/harmony/object-literals-method.js
new file mode 100644 (file)
index 0000000..2af0859
--- /dev/null
@@ -0,0 +1,123 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-object-literals --allow-natives-syntax
+
+
+(function TestDescriptor() {
+  var object = {
+    method() {
+      return 42;
+    }
+  };
+  assertEquals(42, object.method());
+})();
+
+
+(function TestDescriptor() {
+  var object = {
+    method() {
+      return 42;
+    }
+  };
+
+  var desc = Object.getOwnPropertyDescriptor(object, 'method');
+  assertTrue(desc.enumerable);
+  assertTrue(desc.configurable);
+  assertTrue(desc.writable);
+  assertEquals('function', typeof desc.value);
+
+  assertEquals(42, desc.value());
+})();
+
+
+(function TestProto() {
+  var object = {
+    method() {
+      return 42;
+    }
+  };
+
+  assertEquals(Function.prototype, Object.getPrototypeOf(object.method));
+})();
+
+
+(function TestNotConstructable() {
+  var object = {
+    method() {
+      return 42;
+    }
+  };
+
+  assertThrows(function() {
+    new object.method;
+  });
+})();
+
+
+(function TestFunctionName() {
+  var object = {
+    method() {
+      return 42;
+    },
+    1() {},
+    2.0() {}
+  };
+  var f = object.method;
+  assertEquals('method', f.name);
+  var g = object[1];
+  assertEquals('1', g.name);
+
+  var h = object[2];
+  assertEquals('2', h.name);
+})();
+
+
+(function TestNoBinding() {
+  var method = 'local';
+  var calls = 0;
+  var object = {
+    method() {
+      calls++;
+      assertEquals('local', method);
+    }
+  };
+  object.method();
+  assertEquals(1, calls);
+})();
+
+
+(function TestNoPrototype() {
+  var object = {
+    method() {
+      return 42;
+    }
+  };
+  var f = object.method;
+  assertFalse(f.hasOwnProperty('prototype'));
+  assertEquals(undefined, f.prototype);
+
+  f.prototype = 42;
+  assertEquals(42, f.prototype);
+})();
+
+
+(function TestToString() {
+  var object = {
+    method() { 42; }
+  };
+  assertEquals('method() { 42; }', object.method.toString());
+})();
+
+
+(function TestOptimized() {
+  var object = {
+    method() { return 42; }
+  };
+  assertEquals(42, object.method());
+  assertEquals(42, object.method());
+  %OptimizeFunctionOnNextCall(object.method);
+  assertEquals(42, object.method());
+  assertFalse(object.method.hasOwnProperty('prototype'));
+})();
diff --git a/test/mjsunit/runtime-gen/functionisconcisemethod.js b/test/mjsunit/runtime-gen/functionisconcisemethod.js
new file mode 100644 (file)
index 0000000..95bc85b
--- /dev/null
@@ -0,0 +1,5 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
+// Flags: --allow-natives-syntax --harmony --harmony-proxies
+var _f = function() {};
+%FunctionIsConciseMethod(_f);