Ignore:
Timestamp:
Jun 5, 2020, 4:25:43 AM (5 years ago)
Author:
[email protected]
Message:

[JSC] Add support for private class fields
https://bugs.webkit.org/show_bug.cgi?id=206431

Reviewed by Saam Barati.

JSTests:

Expands upon the earlier public fields patch, adding a number of private
field tests.

  • stress/class-fields-private-as-function.js: Added.
  • stress/class-fields-private-cached-bytecode.js: Added.
  • stress/class-fields-private-freeze-out-of-line.js: Added.
  • stress/class-fields-private-freeze.js: Added.
  • stress/class-fields-private-on-proxy.js: Added.
  • stress/class-fields-private-out-of-line.js: Added.
  • stress/class-fields-private-prevent-extensions-out-of-line.js: Added.
  • stress/class-fields-private-prevent-extensions.js: Added.
  • stress/class-fields-private-seal-out-of-line.js: Added.
  • stress/class-fields-private-seal.js: Added.
  • stress/class-fields-private-use-eval.js: Added.
  • stress/class-fields-stress-instance.js:
  • stress/optional-chaining-and-private-fields.js: Added.
  • stress/private-name-access-in-computed-property.js: Added.
  • stress/put-by-val-direct-addprivate.js: Added.
  • stress/put-by-val-direct-putprivate.js: Added.
  • test262/config.yaml:

Source/JavaScriptCore:

Expanding upon the earlier public class fields patch, we implement the remaining (and
significant parts) of the instance fields (https://tc39.es/proposal-class-fields/).

There are a variety of key changes here:

  • Parser now understands the concept of private names (Token PRIVATENAME).
  • 1 new opcode (op_get_private_name), one changed opcode (op_put_by_val_direct).
  • A method for creating Symbol objects with a null PrivateSymbolImpl is exposed as a LinkTimeConstant (@createPrivateSymbol).
  • Null Private Symbols are stored by name (not a valid identifier) in a JSScope, and are loaded from the outer scope whenever they are used by the modified opcodes.

The changes to op_put_by_val_direct include a new bytecode operand (PutByValFlags) which are
used to distinguish between overwriting or defining a new private field. Specifically, when it
comes to private field accesses, it's necessary to throw an exception when accessing a field
which does not exist, or when attempting to define a private field which has already been
defined.

During the evaluation of a class expression, before the class element list is evaluated (in case
any computed property names expressions refer to a new private field), a new PrivateSymbol is
created for each individual private field name, and stored in the class lexical scope.

Private field names are loaded from scope before their use. This prevents multiple evaluations
of the same class source from accessing each other's private fields, because the values of the
symbols loaded from the class scope would be distinct. This is required by the proposal text,
and is the key reason why we use ByVal lookups rather than ById lookups.

To illustrate, typical private field access will look like:

<Field Reads>
resolve_scope <scope=>, <currentScope>, "#x", GlobalProperty, 0
get_from_scope <symbol=>, <scope>, "#x", 1050624<DoNotThrowIfNotFound|GlobalProperty|NotInitialization>, 0, 0
get_private_name <value=>, <receiver --- probably 'this'>, <symbol>

<Field Writes>
resolve_scope <scope=>, <currentScope>, "#x", GlobalProperty, 0
get_from_scope <symbol=>, <scope>, "#x", 1050624<DoNotThrowIfNotFound|GlobalProperty|NotInitialization>, 0, 0
put_by_val_direct <receiver, probably 'this'>, <symbol>, <value>, <PutByValPrivateName>

<Field Definition>
resolve_scope <scope=>, <currentScope>, "#x", GlobalProperty, 0
get_from_scope <symbol=>, <scope>, "#x", 1050624<DoNotThrowIfNotFound|GlobalProperty|NotInitialization>, 0, 0
put_by_val_direct <receiver, probably 'this'>, <symbol>, <value>, <PutByValPrivateName|PutByValThrowIfExists>

The feature is currently hidden behind the feature flag JSC::Options::usePrivateClassFields.

  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • builtins/BuiltinNames.h:
  • bytecode/BytecodeList.rb:
  • bytecode/BytecodeUseDef.cpp:

(JSC::computeUsesForBytecodeIndexImpl):
(JSC::computeDefsForBytecodeIndexImpl):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::finalizeLLIntInlineCaches):

  • bytecode/Fits.h:
  • bytecode/LinkTimeConstant.h:
  • bytecode/PutByValFlags.cpp: Copied from Source/JavaScriptCore/bytecode/PutKind.h.

(WTF::printInternal):

  • bytecode/PutByValFlags.h: Added.

(JSC::PutByValFlags::create):
(JSC::PutByValFlags::createDirect):
(JSC::PutByValFlags::createDefinePrivateField):
(JSC::PutByValFlags::createPutPrivateField):
(JSC::PutByValFlags::isDirect const):
(JSC::PutByValFlags::ecmaMode const):
(JSC::PutByValFlags::privateFieldAccessKind const):
(JSC::PutByValFlags::isPrivateFieldAccess const):
(JSC::PutByValFlags::isPrivateFieldPut const):
(JSC::PutByValFlags::isPrivateFieldAdd const):
(JSC::PutByValFlags::PutByValFlags):

  • bytecode/PutKind.h:
  • bytecode/UnlinkedFunctionExecutable.cpp:

(JSC::generateUnlinkedFunctionCodeBlock):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::instantiateLexicalVariables):
(JSC::BytecodeGenerator::emitDirectGetByVal):
(JSC::BytecodeGenerator::emitDirectPutByVal):
(JSC::BytecodeGenerator::emitDefinePrivateField):
(JSC::BytecodeGenerator::emitPrivateFieldPut):

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

(JSC::PropertyListNode::emitDeclarePrivateFieldNames):
(JSC::PropertyListNode::emitBytecode):
(JSC::PropertyListNode::emitPutConstantProperty):
(JSC::DotAccessorNode::emitBytecode):
(JSC::BaseDotNode::emitGetPropertyValue):
(JSC::BaseDotNode::emitPutProperty):
(JSC::FunctionCallDotNode::emitBytecode):
(JSC::PostfixNode::emitDot):
(JSC::PrefixNode::emitDot):
(JSC::AssignDotNode::emitBytecode):
(JSC::ReadModifyDotNode::emitBytecode):
(JSC::DefineFieldNode::emitBytecode):
(JSC::ClassExprNode::emitBytecode):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ecmaMode):
(JSC::DFG::ecmaMode<OpPutByValDirect>):
(JSC::DFG::ByteCodeParser::handlePutByVal):

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::cachedPutById):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compilePutById):

  • generator/DSL.rb:
  • jit/ICStats.h:
  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):

  • jit/JIT.h:
  • jit/JITInlineCacheGenerator.cpp:

(JSC::JITPutByIdGenerator::JITPutByIdGenerator):
(JSC::JITPutByIdGenerator::slowPathFunction):

  • jit/JITInlineCacheGenerator.h:

(JSC::JITPutByIdGenerator::JITPutByIdGenerator):

  • jit/JITInlines.h:

(JSC::JIT::ecmaMode):
(JSC::JIT::ecmaMode<OpPutById>):
(JSC::JIT::ecmaMode<OpPutByValDirect>):
(JSC::JIT::privateFieldAccessKind):
(JSC::JIT::privateFieldAccessKind<OpPutByValDirect>):

  • jit/JITOperations.cpp:

(JSC::putPrivateField):
(JSC::definePrivateField):

  • jit/JITOperations.h:
  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emitPutByValWithCachedId):
(JSC::JIT::emitSlow_op_put_by_val):
(JSC::JIT::emit_op_put_by_id):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emitSlow_op_put_by_val):
(JSC::JIT::emit_op_put_by_id):

  • jit/Repatch.cpp:

(JSC::appropriateGenericPutByIdFunction):
(JSC::appropriateOptimizingPutByIdFunction):
(JSC::tryCachePutByID):

  • llint/LLIntOffsetsExtractor.cpp:
  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • llint/LLIntSlowPaths.h:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • parser/ASTBuilder.h:

(JSC::ASTBuilder::createDotAccess):
(JSC::ASTBuilder::isPrivateLocation):
(JSC::ASTBuilder::makeFunctionCallNode):
(JSC::ASTBuilder::makeAssignNode):

  • parser/Lexer.cpp:

(JSC::Lexer<LChar>::parseIdentifier):
(JSC::Lexer<UChar>::parseIdentifier):
(JSC::Lexer<CharacterType>::parseIdentifierSlowCase):
(JSC::Lexer<T>::lexWithoutClearingLineTerminator):

  • parser/NodeConstructors.h:

(JSC::BaseDotNode::BaseDotNode):
(JSC::DotAccessorNode::DotAccessorNode):
(JSC::FunctionCallDotNode::FunctionCallDotNode):
(JSC::CallFunctionCallDotNode::CallFunctionCallDotNode):
(JSC::ApplyFunctionCallDotNode::ApplyFunctionCallDotNode):
(JSC::HasOwnPropertyFunctionCallDotNode::HasOwnPropertyFunctionCallDotNode):
(JSC::AssignDotNode::AssignDotNode):
(JSC::ReadModifyDotNode::ReadModifyDotNode):

  • parser/Nodes.cpp:

(JSC::PropertyListNode::shouldCreateLexicalScopeForClass):

  • parser/Nodes.h:

(JSC::ExpressionNode::isPrivateLocation const):
(JSC::BaseDotNode::base const):
(JSC::BaseDotNode::identifier const):
(JSC::BaseDotNode::type const):
(JSC::BaseDotNode::isPrivateField const):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseVariableDeclarationList):
(JSC::Parser<LexerType>::parseDestructuringPattern):
(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parseInstanceFieldInitializerSourceElements):
(JSC::Parser<LexerType>::usePrivateName):
(JSC::Parser<LexerType>::parseMemberExpression):
(JSC::Parser<LexerType>::parseUnaryExpression):
(JSC::Parser<LexerType>::printUnexpectedTokenText):

  • parser/Parser.h:

(JSC::Scope::isPrivateNameScope const):
(JSC::Scope::setIsPrivateNameScope):
(JSC::Scope::hasPrivateName):
(JSC::Scope::copyUndeclaredPrivateNamesTo):
(JSC::Scope::hasUsedButUndeclaredPrivateNames const):
(JSC::Scope::usePrivateName):
(JSC::Scope::declarePrivateName):
(JSC::Parser::findPrivateNameScope):
(JSC::Parser::privateNameScope):
(JSC::Parser::copyUndeclaredPrivateNamesToOuterScope):
(JSC::Parser::matchAndUpdate):
(JSC::Parser<LexerType>::parse):
(JSC::parse):

  • parser/ParserTokens.h:
  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::createDotAccess):
(JSC::SyntaxChecker::operatorStackPop):

  • parser/VariableEnvironment.cpp:

(JSC::VariableEnvironment::operator=):
(JSC::VariableEnvironment::swap):
(JSC::CompactVariableEnvironment::CompactVariableEnvironment):

  • parser/VariableEnvironment.h:

(JSC::VariableEnvironmentEntry::isPrivateName const):
(JSC::VariableEnvironmentEntry::setIsPrivateName):
(JSC::PrivateNameEntry::PrivateNameEntry):
(JSC::PrivateNameEntry::isUsed const):
(JSC::PrivateNameEntry::isDeclared const):
(JSC::PrivateNameEntry::setIsUsed):
(JSC::PrivateNameEntry::setIsDeclared):
(JSC::PrivateNameEntry::bits const):
(JSC::PrivateNameEntry::operator== const):
(JSC::VariableEnvironment::VariableEnvironment):
(JSC::VariableEnvironment::size const):
(JSC::VariableEnvironment::mapSize const):
(JSC::VariableEnvironment::declarePrivateName):
(JSC::VariableEnvironment::usePrivateName):
(JSC::VariableEnvironment::privateNames const):
(JSC::VariableEnvironment::privateNamesSize const):
(JSC::VariableEnvironment::hasPrivateName):
(JSC::VariableEnvironment::copyPrivateNamesTo const):
(JSC::VariableEnvironment::copyUndeclaredPrivateNamesTo const):
(JSC::VariableEnvironment::RareData::RareData):
(JSC::VariableEnvironment::getOrAddPrivateName):

  • runtime/CachedTypes.cpp:

(JSC::CachedOptional::decodeAsPtr const):
(JSC::CachedVariableEnvironmentRareData::encode):
(JSC::CachedVariableEnvironmentRareData::decode const):
(JSC::CachedVariableEnvironment::encode):
(JSC::CachedVariableEnvironment::decode const):
(JSC::CachedSymbolTableRareData::encode):
(JSC::CachedSymbolTableRareData::decode const):
(JSC::CachedSymbolTable::encode):
(JSC::CachedSymbolTable::decode const):

  • runtime/CodeCache.cpp:

(JSC::generateUnlinkedCodeBlockImpl):

  • runtime/CommonIdentifiers.cpp:

(JSC::CommonIdentifiers::CommonIdentifiers):

  • runtime/CommonIdentifiers.h:
  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/CommonSlowPaths.h:
  • runtime/ExceptionHelpers.cpp:

(JSC::createInvalidPrivateNameError):
(JSC::createRedefinedPrivateNameError):

  • runtime/ExceptionHelpers.h:
  • runtime/JSGlobalObject.cpp:

(JSC::createPrivateSymbol):
(JSC::JSGlobalObject::init):

  • runtime/JSObject.h:
  • runtime/JSObjectInlines.h:

(JSC::JSObject::getPrivateFieldSlot):
(JSC::JSObject::getPrivateField):
(JSC::JSObject::putPrivateField):
(JSC::JSObject::definePrivateField):

  • runtime/JSScope.cpp:

(JSC::JSScope::collectClosureVariablesUnderTDZ):

  • runtime/OptionsList.h:
  • runtime/SymbolTable.cpp:

(JSC::SymbolTable::cloneScopePart):

  • runtime/SymbolTable.h:
Location:
trunk/Source/JavaScriptCore/bytecompiler
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r262567 r262613  
    18931893            SymbolTableEntry newEntry(varOffset, static_cast<unsigned>(entry.value.isConst() ? PropertyAttribute::ReadOnly : PropertyAttribute::None));
    18941894            symbolTable->add(NoLockingNecessary, entry.key.get(), newEntry);
     1895
     1896            // FIXME: only do this if there is an eval() within a nested scope --- otherwise it isn't needed.
     1897            // https://bugs.webkit.org/show_bug.cgi?id=206663
     1898            if (entry.value.isPrivateName())
     1899                symbolTable->addPrivateName(entry.key.get());
    18951900        }
    18961901    }
     
    26942699}
    26952700
     2701RegisterID* BytecodeGenerator::emitDirectGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
     2702{
     2703    OpGetPrivateName::emit(this, dst, base, property);
     2704    return dst;
     2705}
     2706
    26962707RegisterID* BytecodeGenerator::emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
    26972708{
    2698     OpPutByValDirect::emit(this, base, property, value, ecmaMode());
     2709    OpPutByValDirect::emit(this, base, property, value, PutByValFlags::createDirect(ecmaMode()));
    26992710    return value;
    27002711}
     
    27152726{
    27162727    OpPutInternalField::emit(this, base, index, value);
     2728    return value;
     2729}
     2730
     2731RegisterID* BytecodeGenerator::emitDefinePrivateField(RegisterID* base, RegisterID* property, RegisterID* value)
     2732{
     2733    OpPutByValDirect::emit(this, base, property, value, PutByValFlags::createDefinePrivateField(ecmaMode()));
     2734    return value;
     2735}
     2736
     2737RegisterID* BytecodeGenerator::emitPrivateFieldPut(RegisterID* base, RegisterID* property, RegisterID* value)
     2738{
     2739    OpPutByValDirect::emit(this, base, property, value, PutByValFlags::createPutPrivateField(ecmaMode()));
    27172740    return value;
    27182741}
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r262354 r262613  
    814814        RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
    815815        RegisterID* emitPutByVal(RegisterID* base, RegisterID* thisValue, RegisterID* property, RegisterID* value);
     816        RegisterID* emitDirectGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
    816817        RegisterID* emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
    817818        RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
     
    819820        RegisterID* emitGetInternalField(RegisterID* dst, RegisterID* base, unsigned index);
    820821        RegisterID* emitPutInternalField(RegisterID* base, unsigned index, RegisterID* value);
     822        RegisterID* emitDefinePrivateField(RegisterID* base, RegisterID* property, RegisterID* value);
     823        RegisterID* emitPrivateFieldPut(RegisterID* base, RegisterID* property, RegisterID* value);
    821824
    822825        void emitSuperSamplerBegin();
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r262354 r262613  
    545545}
    546546
     547void PropertyListNode::emitDeclarePrivateFieldNames(BytecodeGenerator& generator, RegisterID* scope)
     548{
     549    // Walk the list and declare any Private property names (e.g. `#foo`) in the provided scope.
     550    RefPtr<RegisterID> createPrivateSymbol;
     551    for (PropertyListNode* p = this; p; p = p->m_next) {
     552        const PropertyNode& node = *p->m_node;
     553        if (node.type() & PropertyNode::Private) {
     554            if (!createPrivateSymbol)
     555                createPrivateSymbol = generator.moveLinkTimeConstant(nullptr, LinkTimeConstant::createPrivateSymbol);
     556
     557            CallArguments arguments(generator, nullptr, 0);
     558            generator.emitLoad(arguments.thisRegister(), jsUndefined());
     559            RefPtr<RegisterID> symbol = generator.emitCall(generator.finalDestination(nullptr, createPrivateSymbol.get()), createPrivateSymbol.get(), NoExpectedFunction, arguments, position(), position(), position(), DebuggableCall::No);
     560
     561            Variable var = generator.variable(*node.name());
     562            generator.emitPutToScope(scope, var, symbol.get(), DoNotThrowIfNotFound, InitializationMode::ConstInitialization);
     563        }
     564    }
     565}
     566
    547567RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dstOrConstructor, RegisterID* prototype, Vector<JSTextPosition>* instanceFieldLocations)
    548568{
    549     // Fast case: this loop just handles regular value properties.
    550569    PropertyListNode* p = this;
    551570    RegisterID* dst = nullptr;
     571
     572    // Fast case: this loop just handles regular value properties.
    552573    for (; p && (p->m_node->m_type & PropertyNode::Constant); p = p->m_next) {
    553574        dst = p->m_node->isInstanceClassProperty() ? prototype : dstOrConstructor;
     
    711732void PropertyListNode::emitPutConstantProperty(BytecodeGenerator& generator, RegisterID* newObj, PropertyNode& node)
    712733{
     734    // Private fields are handled in the synthetic instanceFieldInitializer function, not here.
     735    ASSERT(!(node.type() & PropertyNode::Private));
     736
    713737    bool shouldSetFunctionName = generator.shouldSetFunctionName(node.m_assign);
    714738
     
    841865
    842866    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    843     RegisterID* ret;
    844     if (baseIsSuper) {
    845         RefPtr<RegisterID> thisValue = generator.ensureThis();
    846         ret = generator.emitGetById(finalDest.get(), base.get(), thisValue.get(), m_ident);
    847     } else
    848         ret = generator.emitGetById(finalDest.get(), base.get(), m_ident);
     867    RegisterID* ret = emitGetPropertyValue(generator, finalDest.get(), base.get());
     868
    849869    generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
    850870    return ret;
     871}
     872
     873RegisterID* BaseDotNode::emitGetPropertyValue(BytecodeGenerator& generator, RegisterID* dst, RegisterID* base, RefPtr<RegisterID>& thisValue)
     874{
     875    if (isPrivateField()) {
     876        Variable var = generator.variable(m_ident);
     877        ASSERT_WITH_MESSAGE(!var.local(), "Private Field names must be stored in captured variables");
     878
     879        RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     880        RefPtr<RegisterID> privateName = generator.newTemporary();
     881        generator.emitGetFromScope(privateName.get(), scope.get(), var, DoNotThrowIfNotFound);
     882        return generator.emitDirectGetByVal(dst, base, privateName.get());
     883    }
     884
     885    if (m_base->isSuperNode()) {
     886        if (!thisValue)
     887            thisValue = generator.ensureThis();
     888        return generator.emitGetById(dst, base, thisValue.get(), m_ident);
     889    }
     890
     891    return generator.emitGetById(dst, base, m_ident);
     892}
     893
     894RegisterID* BaseDotNode::emitGetPropertyValue(BytecodeGenerator& generator, RegisterID* dst, RegisterID* base)
     895{
     896    RefPtr<RegisterID> thisValue;
     897    return emitGetPropertyValue(generator, dst, base, thisValue);
     898}
     899
     900RegisterID* BaseDotNode::emitPutProperty(BytecodeGenerator& generator, RegisterID* base, RegisterID* value, RefPtr<RegisterID>& thisValue)
     901{
     902    if (isPrivateField()) {
     903        Variable var = generator.variable(m_ident);
     904        ASSERT_WITH_MESSAGE(!var.local(), "Private Field names must be stored in captured variables");
     905
     906        RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     907        RefPtr<RegisterID> privateName = generator.newTemporary();
     908        generator.emitGetFromScope(privateName.get(), scope.get(), var, DoNotThrowIfNotFound);
     909        return generator.emitPrivateFieldPut(base, privateName.get(), value);
     910    }
     911
     912    if (m_base->isSuperNode()) {
     913        if (!thisValue)
     914            thisValue = generator.ensureThis();
     915        return generator.emitPutById(base, thisValue.get(), m_ident, value);
     916    }
     917
     918    return generator.emitPutById(base, m_ident, value);
     919}
     920
     921RegisterID* BaseDotNode::emitPutProperty(BytecodeGenerator& generator, RegisterID* base, RegisterID* value)
     922{
     923    RefPtr<RegisterID> thisValue;
     924    return emitPutProperty(generator, base, value, thisValue);
    851925}
    852926
     
    17351809    }
    17361810    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
    1737     if (baseIsSuper) {
    1738         RefPtr<RegisterID> superBase = emitSuperBaseForCallee(generator);
    1739         generator.emitGetById(function.get(), superBase.get(), callArguments.thisRegister(), m_ident);
    1740     } else
    1741         generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
     1811
     1812    RefPtr<RegisterID> base = baseIsSuper ? emitSuperBaseForCallee(generator) : callArguments.thisRegister();
     1813    emitGetPropertyValue(generator, function.get(), base.get());
    17421814
    17431815    if (isOptionalChainBase())
     
    21292201
    21302202    generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
     2203
     2204    if (dotAccessor->isPrivateField()) {
     2205        ASSERT(!baseIsSuper);
     2206        Variable var = generator.variable(ident);
     2207        RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     2208        RefPtr<RegisterID> privateName = generator.newTemporary();
     2209        generator.emitGetFromScope(privateName.get(), scope.get(), var, DoNotThrowIfNotFound);
     2210
     2211        RefPtr<RegisterID> value = generator.emitDirectGetByVal(generator.newTemporary(), base.get(), privateName.get());
     2212        RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
     2213        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     2214        generator.emitPrivateFieldPut(base.get(), privateName.get(), value.get());
     2215        generator.emitProfileType(value.get(), divotStart(), divotEnd());
     2216        return generator.move(dst, oldValue.get());
     2217    }
     2218
    21312219    RefPtr<RegisterID> value;
    21322220    RefPtr<RegisterID> thisValue;
     
    23522440    generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
    23532441    RegisterID* value;
     2442    if (dotAccessor->isPrivateField()) {
     2443        ASSERT(!baseNode->isSuperNode());
     2444        Variable var = generator.variable(ident);
     2445        RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     2446        RefPtr<RegisterID> privateName = generator.newTemporary();
     2447        generator.emitGetFromScope(privateName.get(), scope.get(), var, DoNotThrowIfNotFound);
     2448
     2449        value = generator.emitDirectGetByVal(propDst.get(), base.get(), privateName.get());
     2450        emitIncOrDec(generator, value, m_operator);
     2451        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     2452        generator.emitPrivateFieldPut(base.get(), privateName.get(), value);
     2453        generator.emitProfileType(value, divotStart(), divotEnd());
     2454        return generator.move(dst, propDst.get());
     2455    }
     2456
    23542457    RefPtr<RegisterID> thisValue;
    23552458    if (baseNode->isSuperNode()) {
     
    31943297    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    31953298    RefPtr<RegisterID> forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.move(generator.tempDestination(result.get()), result.get());
    3196     if (m_base->isSuperNode()) {
    3197         RefPtr<RegisterID> thisValue = generator.ensureThis();
    3198         generator.emitPutById(base.get(), thisValue.get(), m_ident, forwardResult.get());
    3199     } else
    3200         generator.emitPutById(base.get(), m_ident, forwardResult.get());
     3299    emitPutProperty(generator, base.get(), forwardResult.get());
    32013300    generator.emitProfileType(forwardResult.get(), divotStart(), divotEnd());
    32023301    return generator.move(dst, forwardResult.get());
     
    32103309
    32113310    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
    3212     RefPtr<RegisterID> value;
    32133311    RefPtr<RegisterID> thisValue;
    3214     if (m_base->isSuperNode()) {
    3215         thisValue = generator.ensureThis();
    3216         value = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), m_ident);
    3217     } else
    3218         value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
     3312    RefPtr<RegisterID> value = emitGetPropertyValue(generator, generator.tempDestination(dst), base.get(), thisValue);
     3313
    32193314    RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    32203315
    32213316    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    3222     RegisterID* ret;
    3223     if (m_base->isSuperNode())
    3224         ret = generator.emitPutById(base.get(), thisValue.get(), m_ident, updatedValue);
    3225     else
    3226         ret = generator.emitPutById(base.get(), m_ident, updatedValue);
     3317    RefPtr<RegisterID> ret = emitPutProperty(generator, base.get(), updatedValue, thisValue);
    32273318    generator.emitProfileType(updatedValue, divotStart(), divotEnd());
    3228     return ret;
     3319    return ret.get();
    32293320}
    32303321
     
    46994790        break;
    47004791    }
     4792    case DefineFieldNode::Type::PrivateName: {
     4793        Variable var = generator.variable(*m_ident);
     4794        ASSERT_WITH_MESSAGE(!var.local(), "Private Field names must be stored in captured variables");
     4795
     4796        generator.emitExpressionInfo(position(), position(), position() + m_ident->length());
     4797        RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     4798        RefPtr<RegisterID> privateName = generator.newTemporary();
     4799        generator.emitGetFromScope(privateName.get(), scope.get(), var, DoNotThrowIfNotFound);
     4800        generator.emitDefinePrivateField(generator.thisRegister(), privateName.get(), value.get());
     4801        break;
     4802    }
    47014803    case DefineFieldNode::Type::ComputedName: {
    47024804        // FIXME: Improve performance of public class fields
     
    47094811
    47104812        generator.emitExpressionInfo(position(), position(), position() + 1);
    4711         RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), var);
     4813        RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    47124814        RefPtr<RegisterID> privateName = generator.newTemporary();
    47134815        generator.emitGetFromScope(privateName.get(), scope.get(), var, ThrowIfNotFound);
     
    48014903
    48024904    if (m_classElements) {
     4905        m_classElements->emitDeclarePrivateFieldNames(generator, generator.scopeRegister());
     4906
    48034907        Vector<JSTextPosition> instanceFieldLocations;
    48044908        generator.emitDefineClassElements(m_classElements, constructor.get(), prototype.get(), instanceFieldLocations);
Note: See TracChangeset for help on using the changeset viewer.