Ignore:
Timestamp:
Feb 18, 2021, 3:48:28 PM (4 years ago)
Author:
Caio Lima
Message:

[JSC] Implement private static method
https://bugs.webkit.org/show_bug.cgi?id=219181

Reviewed by Yusuke Suzuki.

JSTests:

  • stress/class-private-method-access.js: Added.
  • stress/private-accessor-static-non-static.js: Added.
  • stress/private-getter-inner-class.js:
  • stress/static-private-methods-and-accessor-inner-class.js: Added.
  • stress/static-private-methods-and-accessor-multiple-evaluation.js: Added.
  • stress/static-private-methods-and-accessors-postfix-node.js: Added.
  • stress/static-private-methods-and-accessors-prefix-node.js: Added.
  • test262/config.yaml:

Source/JavaScriptCore:

This patch is implementing static private methods and accessors
proposal based on https://github.com/tc39/proposal-static-class-features.
This implementation diverge a bit from private methods&accessors on the
brand check, because we are using a simpler way to perform static
brand checks. Since only the class constructor is allowed to access
its private methods and accessors, we save it on @privateClassBrand
on class lexical scope and compare it with the receiver of the static
private method (and accessors) using === operation.
While this genenrates more bytecodes than check_private_brand, we
don't need to perform a Structure transition to install a brand,
and avoid allocation of a private symbol. Since each evaluation of a
class generates a different constructor object, we preserve the semantics
that private methods are lexically scoped.

  • builtins/BuiltinNames.h:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitCreatePrivateBrand):
(JSC::BytecodeGenerator::emitInstallPrivateBrand):
(JSC::BytecodeGenerator::emitInstallPrivateClassBrand):
(JSC::BytecodeGenerator::emitGetPrivateBrand):
(JSC::BytecodeGenerator::emitCheckPrivateBrand):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::BaseDotNode::emitGetPropertyValue):
(JSC::BaseDotNode::emitPutProperty):
(JSC::PostfixNode::emitDot):
(JSC::PrefixNode::emitDot):
(JSC::ClassExprNode::emitBytecode):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parseGetterSetter):

  • parser/Parser.h:

(JSC::Scope::declarePrivateMethod):
(JSC::Scope::declarePrivateAccessor):
(JSC::Scope::declarePrivateSetter):
(JSC::Scope::declarePrivateGetter):

  • parser/VariableEnvironment.cpp:

(JSC::VariableEnvironment::declarePrivateAccessor):
(JSC::VariableEnvironment::declarePrivateSetter):
(JSC::VariableEnvironment::declarePrivateGetter):
(JSC::VariableEnvironment::declarePrivateMethod):

  • parser/VariableEnvironment.h:

(JSC::PrivateNameEntry::isStatic const):
(JSC::VariableEnvironment::isEmpty const):
(JSC::VariableEnvironment::declareStaticPrivateMethod):
(JSC::VariableEnvironment::declarePrivateSetter):
(JSC::VariableEnvironment::declareStaticPrivateSetter):
(JSC::VariableEnvironment::declarePrivateGetter):
(JSC::VariableEnvironment::declareStaticPrivateGetter):
(JSC::VariableEnvironment::hasStaticPrivateMethodOrAccessor const):
(JSC::VariableEnvironment::hasInstancePrivateMethodOrAccessor const):
(JSC::VariableEnvironment::hasPrivateMethodOrAccessor const): Deleted.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/parser/VariableEnvironment.h

    r272883 r273107  
    111111    ALWAYS_INLINE bool isGetter() const { return m_bits & IsGetter; }
    112112    ALWAYS_INLINE bool isField() const { return !isPrivateMethodOrAcessor(); }
     113    ALWAYS_INLINE bool isStatic() const { return m_bits & IsStatic; }
    113114
    114115    bool isPrivateMethodOrAcessor() const { return isMethod() || isSetter() || isGetter(); }
     
    131132        IsGetter = 1 << 3,
    132133        IsSetter = 1 << 4,
     134        IsStatic = 1 << 5,
    133135    };
    134136
     
    197199
    198200    bool isEverythingCaptured() const { return m_isEverythingCaptured; }
    199     bool isEmpty() const { return !m_map.size(); }
     201    bool isEmpty() const { return !m_map.size() && !privateNamesSize(); }
    200202
    201203    using PrivateNamesRange = WTF::IteratorRange<PrivateNameEnvironment::iterator>;
     
    205207
    206208    bool declarePrivateMethod(const Identifier& identifier) { return declarePrivateMethod(identifier.impl()); }
    207     bool declarePrivateMethod(const RefPtr<UniquedStringImpl>& identifier);
    208 
    209     bool declarePrivateAccessor(const RefPtr<UniquedStringImpl>&, PrivateNameEntry::Traits);
    210 
    211     bool declarePrivateSetter(const Identifier& identifier) { return declarePrivateSetter(identifier.impl()); }
    212     bool declarePrivateSetter(const RefPtr<UniquedStringImpl>& identifier);
    213 
    214     bool declarePrivateGetter(const Identifier& identifier) { return declarePrivateGetter(identifier.impl()); }
    215     bool declarePrivateGetter(const RefPtr<UniquedStringImpl>& identifier);
     209    bool declarePrivateMethod(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits addionalTraits = PrivateNameEntry::Traits::None);
     210
     211    enum class PrivateDeclarationResult {
     212        Success,
     213        DuplicatedName,
     214        InvalidStaticNonStatic
     215    };
     216
     217    PrivateDeclarationResult declarePrivateAccessor(const RefPtr<UniquedStringImpl>&, PrivateNameEntry accessorTraits);
     218   
     219    bool declareStaticPrivateMethod(const Identifier& identifier)
     220    {
     221        return declarePrivateMethod(identifier.impl(), static_cast<PrivateNameEntry::Traits>(PrivateNameEntry::Traits::IsMethod | PrivateNameEntry::Traits::IsStatic));
     222    }
     223
     224    PrivateDeclarationResult declarePrivateSetter(const Identifier& identifier) { return declarePrivateSetter(identifier.impl()); }
     225    PrivateDeclarationResult declareStaticPrivateSetter(const Identifier& identifier) { return declarePrivateSetter(identifier.impl(), PrivateNameEntry::Traits::IsStatic); }
     226    PrivateDeclarationResult declarePrivateSetter(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits modifierTraits = PrivateNameEntry::Traits::None);
     227
     228    PrivateDeclarationResult declarePrivateGetter(const Identifier& identifier) { return declarePrivateGetter(identifier.impl()); }
     229    PrivateDeclarationResult declareStaticPrivateGetter(const Identifier& identifier) { return declarePrivateGetter(identifier.impl(), PrivateNameEntry::Traits::IsStatic); }
     230    PrivateDeclarationResult declarePrivateGetter(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits modifierTraits = PrivateNameEntry::Traits::None);
    216231
    217232    Map::AddResult declarePrivateField(const RefPtr<UniquedStringImpl>& identifier)
     
    254269    }
    255270
    256     ALWAYS_INLINE bool hasPrivateMethodOrAccessor() const
     271    ALWAYS_INLINE bool hasStaticPrivateMethodOrAccessor() const
    257272    {
    258273        if (!m_rareData)
     
    260275
    261276        for (auto entry : privateNames()) {
    262             if (entry.value.isPrivateMethodOrAcessor())
     277            if (entry.value.isPrivateMethodOrAcessor() && entry.value.isStatic())
    263278                return true;
    264279        }
    265 
     280       
     281        return false;
     282    }
     283   
     284    ALWAYS_INLINE bool hasInstancePrivateMethodOrAccessor() const
     285    {
     286        if (!m_rareData)
     287            return false;
     288       
     289        for (auto entry : privateNames()) {
     290            if (entry.value.isPrivateMethodOrAcessor() && !entry.value.isStatic())
     291                return true;
     292        }
     293       
    266294        return false;
    267295    }
Note: See TracChangeset for help on using the changeset viewer.