Accessor functions should have no prototype property
authorErik Arvidsson <arv@chromium.org>
Thu, 5 Feb 2015 23:34:16 +0000 (18:34 -0500)
committerErik Arvidsson <arv@chromium.org>
Thu, 5 Feb 2015 23:34:28 +0000 (23:34 +0000)
This also removes some convenience functions that were not used.

BUG=v8:3700
LOG=N
R=adamk@chromium.org, adamk

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

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

19 files changed:
src/arm/full-codegen-arm.cc
src/arm64/full-codegen-arm64.cc
src/ast.h
src/code-stubs.h
src/compiler.cc
src/contexts.h
src/globals.h
src/hydrogen-instructions.h
src/ia32/full-codegen-ia32.cc
src/mips/full-codegen-mips.cc
src/mips64/full-codegen-mips64.cc
src/objects-inl.h
src/objects.h
src/ppc/full-codegen-ppc.cc
src/preparser.h
src/x64/full-codegen-x64.cc
src/x87/full-codegen-x87.cc
test/mjsunit/accessors-no-prototype.js [new file with mode: 0644]
test/mjsunit/harmony/classes.js

index f6a7414fb525af093d8232c35228ce649ec4fa2c..a4a17efeec1194ac9acfc4e1fead128612b7962e 100644 (file)
@@ -153,7 +153,7 @@ void FullCodeGenerator::Generate() {
   { Comment cmnt(masm_, "[ Allocate locals");
     int locals_count = info->scope()->num_stack_slots();
     // Generators allocate locals, if any, in context slots.
-    DCHECK(!info->function()->is_generator() || locals_count == 0);
+    DCHECK(!IsGeneratorFunction(info->function()->kind()) || locals_count == 0);
     if (locals_count > 0) {
       if (locals_count >= 128) {
         Label ok;
index c5a71b5199676a1db10d35f9d8d1829180af6223..c6d32670ee7e5e99c9add5f014c7dc6a2c7cfd67 100644 (file)
@@ -155,7 +155,7 @@ void FullCodeGenerator::Generate() {
   { Comment cmnt(masm_, "[ Allocate locals");
     int locals_count = info->scope()->num_stack_slots();
     // Generators allocate locals, if any, in context slots.
-    DCHECK(!info->function()->is_generator() || locals_count == 0);
+    DCHECK(!IsGeneratorFunction(info->function()->kind()) || locals_count == 0);
 
     if (locals_count > 0) {
       if (locals_count >= 128) {
index fca3aabf3a1dfa27ed5e6410a2437525e4ec00eb..4e1fb26c267496cbc4f3e4934fb017a589175b86 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -2548,18 +2548,6 @@ class FunctionLiteral FINAL : public Expression {
   }
 
   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_));
-  }
-  bool is_default_constructor() {
-    return IsDefaultConstructor(FunctionKindBits::decode(bitfield_));
-  }
 
   int ast_node_count() { return ast_properties_.node_count(); }
   AstProperties::Flags* flags() { return ast_properties_.flags(); }
@@ -2630,7 +2618,7 @@ class FunctionLiteral FINAL : public Expression {
   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, 5> {};
+  class FunctionKindBits : public BitField<FunctionKind, 6, 6> {};
 };
 
 
index 2edeb8f39f890b44be8e701329e299dcedc51201..f284a344c950cc88b7742b9bf527e77a3054612b 100644 (file)
@@ -587,15 +587,11 @@ class FastNewClosureStub : public HydrogenCodeStub {
   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()); }
-  bool is_default_constructor() const { return IsDefaultConstructor(kind()); }
 
  private:
   STATIC_ASSERT(LANGUAGE_END == 3);
   class LanguageModeBits : public BitField<LanguageMode, 0, 2> {};
-  class FunctionKindBits : public BitField<FunctionKind, 2, 4> {};
+  class FunctionKindBits : public BitField<FunctionKind, 2, 6> {};
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
   DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
index 9aab688c6a0492ecabd546c95969e7168437ce67..e9cc11172664b92470eb0a9d0c530b4cbd3e303f 100644 (file)
@@ -804,7 +804,7 @@ static bool CheckSuperConstructorCall(CompilationInfo* info) {
   FunctionLiteral* function = info->function();
   if (FLAG_experimental_classes) return true;
   if (!function->uses_super_constructor_call()) return true;
-  if (function->is_default_constructor()) return true;
+  if (IsDefaultConstructor(function->kind())) return true;
 
   ZoneList<Statement*>* body = function->body();
   CHECK(body->length() > 0);
index 83510e93c94afff1923c3c75284ab2e0a7a76761..f932c60092dcba78b2b3818422bc20ef044769ea 100644 (file)
@@ -574,7 +574,8 @@ class Context: public FixedArray {
                                       : SLOPPY_GENERATOR_FUNCTION_MAP_INDEX;
     }
 
-    if (IsArrowFunction(kind) || IsConciseMethod(kind)) {
+    if (IsArrowFunction(kind) || IsConciseMethod(kind) ||
+        IsAccessorFunction(kind)) {
       return is_strict(language_mode)
                  ? STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX
                  : SLOPPY_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX;
index 761a85d011f10a43c15d0e3ef2bd1ba5d38c4eb0..3f2c33593b012acabb7c9102cf269f51a26ee55d 100644 (file)
@@ -814,12 +814,13 @@ enum Signedness { kSigned, kUnsigned };
 
 enum FunctionKind {
   kNormalFunction = 0,
-  kArrowFunction = 1,
-  kGeneratorFunction = 2,
-  kConciseMethod = 4,
+  kArrowFunction = 1 << 0,
+  kGeneratorFunction = 1 << 1,
+  kConciseMethod = 1 << 2,
   kConciseGeneratorMethod = kGeneratorFunction | kConciseMethod,
-  kDefaultConstructor = 8,
-  kSubclassConstructor = 16
+  kAccessorFunction = 1 << 3,
+  kDefaultConstructor = 1 << 4,
+  kSubclassConstructor = 1 << 5
 };
 
 
@@ -829,6 +830,7 @@ inline bool IsValidFunctionKind(FunctionKind kind) {
          kind == FunctionKind::kGeneratorFunction ||
          kind == FunctionKind::kConciseMethod ||
          kind == FunctionKind::kConciseGeneratorMethod ||
+         kind == FunctionKind::kAccessorFunction ||
          kind == FunctionKind::kDefaultConstructor ||
          kind == FunctionKind::kSubclassConstructor;
 }
@@ -852,11 +854,18 @@ inline bool IsConciseMethod(FunctionKind kind) {
 }
 
 
+inline bool IsAccessorFunction(FunctionKind kind) {
+  DCHECK(IsValidFunctionKind(kind));
+  return kind & FunctionKind::kAccessorFunction;
+}
+
+
 inline bool IsDefaultConstructor(FunctionKind kind) {
   DCHECK(IsValidFunctionKind(kind));
   return kind & FunctionKind::kDefaultConstructor;
 }
 
+
 inline bool IsSubclassConstructor(FunctionKind kind) {
   DCHECK(IsValidFunctionKind(kind));
   return kind & FunctionKind::kSubclassConstructor;
index dd7bbfdb28460f825e7982f69aad9f618073bbfe..1c54fa5ba6464f7cc052bf5ee356ebb565635e8e 100644 (file)
@@ -7591,10 +7591,6 @@ class HFunctionLiteral FINAL : public HTemplateInstruction<1> {
   bool has_no_literals() const {
     return HasNoLiteralsField::decode(bit_field_);
   }
-  bool is_arrow() const { return IsArrowFunction(kind()); }
-  bool is_generator() const { return IsGeneratorFunction(kind()); }
-  bool is_concise_method() const { return IsConciseMethod(kind()); }
-  bool is_default_constructor() const { return IsDefaultConstructor(kind()); }
   FunctionKind kind() const { return FunctionKindField::decode(bit_field_); }
   LanguageMode language_mode() const {
     return LanguageModeField::decode(bit_field_);
@@ -7616,11 +7612,11 @@ class HFunctionLiteral FINAL : public HTemplateInstruction<1> {
 
   bool IsDeletable() const OVERRIDE { return true; }
 
-  class FunctionKindField : public BitField<FunctionKind, 0, 4> {};
-  class PretenureField : public BitField<bool, 5, 1> {};
-  class HasNoLiteralsField : public BitField<bool, 6, 1> {};
+  class FunctionKindField : public BitField<FunctionKind, 0, 6> {};
+  class PretenureField : public BitField<bool, 6, 1> {};
+  class HasNoLiteralsField : public BitField<bool, 7, 1> {};
   STATIC_ASSERT(LANGUAGE_END == 3);
-  class LanguageModeField : public BitField<LanguageMode, 7, 2> {};
+  class LanguageModeField : public BitField<LanguageMode, 8, 2> {};
 
   Handle<SharedFunctionInfo> shared_info_;
   uint32_t bit_field_;
index 611a2c5c38eb0c59c6f5851b8f6a812316c5eab8..8ab3763e7c584a40e1eda68db5d508ea0c8d739f 100644 (file)
@@ -143,7 +143,7 @@ void FullCodeGenerator::Generate() {
   { Comment cmnt(masm_, "[ Allocate locals");
     int locals_count = info->scope()->num_stack_slots();
     // Generators allocate locals, if any, in context slots.
-    DCHECK(!info->function()->is_generator() || locals_count == 0);
+    DCHECK(!IsGeneratorFunction(info->function()->kind()) || locals_count == 0);
     if (locals_count == 1) {
       __ push(Immediate(isolate()->factory()->undefined_value()));
     } else if (locals_count > 1) {
index 2909655c0a4ca11b290ede2635f026e632f36f13..7fc5e5c22e93b2f9b8739b00e0354f4d0eb26826 100644 (file)
@@ -161,7 +161,7 @@ void FullCodeGenerator::Generate() {
   { Comment cmnt(masm_, "[ Allocate locals");
     int locals_count = info->scope()->num_stack_slots();
     // Generators allocate locals, if any, in context slots.
-    DCHECK(!info->function()->is_generator() || locals_count == 0);
+    DCHECK(!IsGeneratorFunction(info->function()->kind()) || locals_count == 0);
     if (locals_count > 0) {
       if (locals_count >= 128) {
         Label ok;
index 9f4be7036c38ba90eaa9d72a12114465ebcf4fe8..79052b958c71af7b3e089f0eaa23e42f92e281df 100644 (file)
@@ -158,7 +158,7 @@ void FullCodeGenerator::Generate() {
   { Comment cmnt(masm_, "[ Allocate locals");
     int locals_count = info->scope()->num_stack_slots();
     // Generators allocate locals, if any, in context slots.
-    DCHECK(!info->function()->is_generator() || locals_count == 0);
+    DCHECK(!IsGeneratorFunction(info->function()->kind()) || locals_count == 0);
     if (locals_count > 0) {
       if (locals_count >= 128) {
         Label ok;
index 13f8427c3e3ea86b7c2ad232d9a53a6f5899776f..31439039de15f1506e13b117c2a56dd0b6109ac4 100644 (file)
@@ -5871,6 +5871,8 @@ 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)
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_accessor_function,
+               kIsAccessorFunction)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_default_constructor,
                kIsDefaultConstructor)
 
index 06c490cfe946cfb9edcfd97ab754e35f6fb8b341..61daada4b9ae57c13bb34bd15d84d6fab5ff5025 100644 (file)
@@ -6940,6 +6940,9 @@ class SharedFunctionInfo: public HeapObject {
   // Indicates that this function is a concise method.
   DECL_BOOLEAN_ACCESSORS(is_concise_method)
 
+  // Indicates that this function is an accessor (getter or setter).
+  DECL_BOOLEAN_ACCESSORS(is_accessor_function)
+
   // Indicates that this function is a default constructor.
   DECL_BOOLEAN_ACCESSORS(is_default_constructor)
 
@@ -7190,6 +7193,7 @@ class SharedFunctionInfo: public HeapObject {
     kIsArrow,
     kIsGenerator,
     kIsConciseMethod,
+    kIsAccessorFunction,
     kIsDefaultConstructor,
     kIsSubclassConstructor,
     kIsAsmFunction,
@@ -7199,7 +7203,7 @@ class SharedFunctionInfo: public HeapObject {
   // Add hints for other modes when they're added.
   STATIC_ASSERT(LANGUAGE_END == 3);
 
-  class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 5> {};
+  class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 6> {};
 
   class DeoptCountBits : public BitField<int, 0, 4> {};
   class OptReenableTriesBits : public BitField<int, 4, 18> {};
index b7a5d3e33c5c023365816e742b1e8cbd7f714e4c..45133617e07c511cda63c8159fbb65a01b0a3adb 100644 (file)
@@ -158,7 +158,7 @@ void FullCodeGenerator::Generate() {
     Comment cmnt(masm_, "[ Allocate locals");
     int locals_count = info->scope()->num_stack_slots();
     // Generators allocate locals, if any, in context slots.
-    DCHECK(!info->function()->is_generator() || locals_count == 0);
+    DCHECK(!IsGeneratorFunction(info->function()->kind()) || locals_count == 0);
     if (locals_count > 0) {
       if (locals_count >= 128) {
         Label ok;
index 5be009d66a39c5227795067b53e183cf3dd268aa..29a2b55e83e89719ee6472c35f9826765adb5be6 100644 (file)
@@ -2194,7 +2194,7 @@ ParserBase<Traits>::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker,
     typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral(
         name, scanner()->location(),
         false,  // reserved words are allowed here
-        FunctionKind::kNormalFunction, RelocInfo::kNoPosition,
+        FunctionKind::kAccessorFunction, RelocInfo::kNoPosition,
         FunctionLiteral::ANONYMOUS_EXPRESSION,
         is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY,
         CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
index 917764bd9a1af09f57ce06915156d43c313b36ed..b248dd1ebbf88f200e6ac44acdf87683e402f47c 100644 (file)
@@ -143,7 +143,7 @@ void FullCodeGenerator::Generate() {
   { Comment cmnt(masm_, "[ Allocate locals");
     int locals_count = info->scope()->num_stack_slots();
     // Generators allocate locals, if any, in context slots.
-    DCHECK(!info->function()->is_generator() || locals_count == 0);
+    DCHECK(!IsGeneratorFunction(info->function()->kind()) || locals_count == 0);
     if (locals_count == 1) {
       __ PushRoot(Heap::kUndefinedValueRootIndex);
     } else if (locals_count > 1) {
index 84df83b1bcb82269dc21b33678fa6390c20ca608..7cd503e58c506862d80c3da17390631a8cb69060 100644 (file)
@@ -143,7 +143,7 @@ void FullCodeGenerator::Generate() {
   { Comment cmnt(masm_, "[ Allocate locals");
     int locals_count = info->scope()->num_stack_slots();
     // Generators allocate locals, if any, in context slots.
-    DCHECK(!info->function()->is_generator() || locals_count == 0);
+    DCHECK(!IsGeneratorFunction(info->function()->kind()) || locals_count == 0);
     if (locals_count == 1) {
       __ push(Immediate(isolate()->factory()->undefined_value()));
     } else if (locals_count > 1) {
diff --git a/test/mjsunit/accessors-no-prototype.js b/test/mjsunit/accessors-no-prototype.js
new file mode 100644 (file)
index 0000000..9c429fc
--- /dev/null
@@ -0,0 +1,51 @@
+// 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.
+
+
+(function TestGetter() {
+  var o = {
+    get x() {}
+  };
+  var desc = Object.getOwnPropertyDescriptor(o, 'x');
+  assertEquals('function', typeof desc.get);
+  assertFalse('prototype' in desc.get);
+
+  assertThrows(function() {
+    new desc.get();
+  }, TypeError);
+})();
+
+
+(function TestSetter() {
+  var o = {
+    set x(_) {}
+  };
+  var desc = Object.getOwnPropertyDescriptor(o, 'x');
+  assertEquals('function', typeof desc.set);
+  assertFalse('prototype' in desc.set);
+
+  assertThrows(function() {
+    new desc.set();
+  }, TypeError);
+})();
+
+
+(function TestBoth() {
+  var o = {
+    get x() {},
+    set x(_) {}
+  };
+  var desc = Object.getOwnPropertyDescriptor(o, 'x');
+  assertEquals('function', typeof desc.get);
+  assertEquals('function', typeof desc.set);
+  assertFalse('prototype' in desc.get);
+  assertFalse('prototype' in desc.set);
+
+  assertThrows(function() {
+    new desc.get();
+  }, TypeError);
+  assertThrows(function() {
+    new desc.set();
+  }, TypeError);
+})();
index f57a1bad1c6e21e51f7b4343cd180595e9f4c860..a28cddf4dc41a24f883b95a29c90d760b2b7e522 100644 (file)
@@ -198,6 +198,7 @@ function assertGetterDescriptor(object, name) {
   assertTrue(descr.configurable);
   assertFalse(descr.enumerable);
   assertEquals('function', typeof descr.get);
+  assertFalse('prototype' in descr.get);
   assertEquals(undefined, descr.set);
 }
 
@@ -208,6 +209,7 @@ function assertSetterDescriptor(object, name) {
   assertFalse(descr.enumerable);
   assertEquals(undefined, descr.get);
   assertEquals('function', typeof descr.set);
+  assertFalse('prototype' in descr.set);
 }
 
 
@@ -217,6 +219,8 @@ function assertAccessorDescriptor(object, name) {
   assertFalse(descr.enumerable);
   assertEquals('function', typeof descr.get);
   assertEquals('function', typeof descr.set);
+  assertFalse('prototype' in descr.get);
+  assertFalse('prototype' in descr.set);
 }