⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 268794 in webkit


Ignore:
Timestamp:
Oct 21, 2020, 7:06:02 AM (6 years ago)
Author:
caitp@igalia.com
Message:

[JSC] support op_get_private_name in DFG and FTL
https://bugs.webkit.org/show_bug.cgi?id=214861

Reviewed by Filip Pizlo.

JSTests:

  • microbenchmarks/class-fields-private/monomorphic-get-private-field.js: Added.
  • microbenchmarks/class-fields-private/polymorphic-get-private-field.js: Added.
  • stress/dfg-get-private-name-by-id-generic.js: Added.
  • stress/dfg-get-private-name-by-id-osr-bad-identifier.js: Added.
  • stress/dfg-get-private-name-by-id.js: Added.
  • stress/dfg-get-private-name-by-offset-osr-bad-identifier.js: Added.
  • stress/dfg-get-private-name-by-offset-osr-bad-structure.js: Added.
  • stress/dfg-get-private-name-by-offset.js: Added.
  • stress/dfg-get-private-name-by-val-generic.js: Added.
  • stress/ftl-get-private-name-by-id.js: Added.
  • stress/ftl-get-private-name-by-offset-multi.js: Added.
  • stress/get-private-name-with-constant-ident.js: Added.
  • stress/get-private-name-with-constant-symbol.js: Added.
  • stress/get-private-name-with-different-symbol.js: Added.

Source/JavaScriptCore:

Adds DFG/FTL support for op_get_private_name.

During DFG bytecode parsing, we will attempt, if deemed possible by
the information available, to output a GetByOffset operation. If a
single private field identifier is used in all cases (the common case),
but there are too many structure variants, a GetPrivateNameById
operation is emitted instead. Failing that, the GetPrivateName
operation is produced, which produces a GetByVal IC like in the
baseline JIT.

In FTL, GetPrivateNameByID can be reduced to [Multi]GetByOffset in the
DFGConstantFoldingPhase, or a GetByID IC when lowering to B3.

  • bytecode/GetByStatus.cpp:

(JSC::GetByStatus::computeFromLLInt):

  • bytecode/StructureStubInfo.h:

(JSC::appropriateOptimizingGetByIdFunction):
(JSC::appropriateGenericGetByIdFunction):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::simplifyGetByStatus):
(JSC::DFG::ByteCodeParser::handleGetById):
(JSC::DFG::ByteCodeParser::handleGetPrivateNameById):
(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGNode.h:

(JSC::DFG::Node::convertToGetByOffset):
(JSC::DFG::Node::convertToMultiGetByOffset):
(JSC::DFG::Node::hasCacheableIdentifier):
(JSC::DFG::Node::hasHeapPrediction):

  • dfg/DFGNodeType.h:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileGetPrivateName):
(JSC::DFG::SpeculativeJIT::compileGetPrivateNameByVal):
(JSC::DFG::SpeculativeJIT::compileGetPrivateNameById):

  • dfg/DFGSpeculativeJIT.h:
  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::getPrivateName):
(JSC::FTL::DFG::LowerDFGToB3::compileGetPrivateName):
(JSC::FTL::DFG::LowerDFGToB3::compileGetPrivateNameById):

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

(JSC::getPrivateName):
(JSC::JSC_DEFINE_JIT_OPERATION):

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

(JSC::appropriateOptimizingGetByFunction):
(JSC::appropriateGetByFunction):
(JSC::tryCacheGetBy):

  • jit/Repatch.h:
  • runtime/OptionsList.h:
Location:
trunk
Files:
14 added
26 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r268783 r268794  
     12020-10-21  Caitlin Potter  <caitp@igalia.com>
     2
     3        [JSC] support op_get_private_name in DFG and FTL
     4        https://bugs.webkit.org/show_bug.cgi?id=214861
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * microbenchmarks/class-fields-private/monomorphic-get-private-field.js: Added.
     9        * microbenchmarks/class-fields-private/polymorphic-get-private-field.js: Added.
     10        * stress/dfg-get-private-name-by-id-generic.js: Added.
     11        * stress/dfg-get-private-name-by-id-osr-bad-identifier.js: Added.
     12        * stress/dfg-get-private-name-by-id.js: Added.
     13        * stress/dfg-get-private-name-by-offset-osr-bad-identifier.js: Added.
     14        * stress/dfg-get-private-name-by-offset-osr-bad-structure.js: Added.
     15        * stress/dfg-get-private-name-by-offset.js: Added.
     16        * stress/dfg-get-private-name-by-val-generic.js: Added.
     17        * stress/ftl-get-private-name-by-id.js: Added.
     18        * stress/ftl-get-private-name-by-offset-multi.js: Added.
     19        * stress/get-private-name-with-constant-ident.js: Added.
     20        * stress/get-private-name-with-constant-symbol.js: Added.
     21        * stress/get-private-name-with-different-symbol.js: Added.
     22
    1232020-10-20  Saam Barati  <sbarati@apple.com>
    224
  • trunk/Source/JavaScriptCore/ChangeLog

    r268783 r268794  
     12020-10-21  Caitlin Potter  <caitp@igalia.com>
     2
     3        [JSC] support op_get_private_name in DFG and FTL
     4        https://bugs.webkit.org/show_bug.cgi?id=214861
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Adds DFG/FTL support for op_get_private_name.
     9
     10        During DFG bytecode parsing, we will attempt, if deemed possible by
     11        the information available, to output a GetByOffset operation. If a
     12        single private field identifier is used in all cases (the common case),
     13        but there are too many structure variants, a GetPrivateNameById
     14        operation is emitted instead. Failing that, the GetPrivateName
     15        operation is produced, which produces a GetByVal IC like in the
     16        baseline JIT.
     17
     18        In FTL, GetPrivateNameByID can be reduced to [Multi]GetByOffset in the
     19        DFGConstantFoldingPhase, or a GetByID IC when lowering to B3.
     20
     21        * bytecode/GetByStatus.cpp:
     22        (JSC::GetByStatus::computeFromLLInt):
     23        * bytecode/StructureStubInfo.h:
     24        (JSC::appropriateOptimizingGetByIdFunction):
     25        (JSC::appropriateGenericGetByIdFunction):
     26        * dfg/DFGAbstractInterpreterInlines.h:
     27        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     28        * dfg/DFGByteCodeParser.cpp:
     29        (JSC::DFG::ByteCodeParser::simplifyGetByStatus):
     30        (JSC::DFG::ByteCodeParser::handleGetById):
     31        (JSC::DFG::ByteCodeParser::handleGetPrivateNameById):
     32        (JSC::DFG::ByteCodeParser::parseBlock):
     33        * dfg/DFGClobberize.h:
     34        (JSC::DFG::clobberize):
     35        * dfg/DFGConstantFoldingPhase.cpp:
     36        (JSC::DFG::ConstantFoldingPhase::foldConstants):
     37        * dfg/DFGDoesGC.cpp:
     38        (JSC::DFG::doesGC):
     39        * dfg/DFGFixupPhase.cpp:
     40        (JSC::DFG::FixupPhase::fixupNode):
     41        * dfg/DFGNode.h:
     42        (JSC::DFG::Node::convertToGetByOffset):
     43        (JSC::DFG::Node::convertToMultiGetByOffset):
     44        (JSC::DFG::Node::hasCacheableIdentifier):
     45        (JSC::DFG::Node::hasHeapPrediction):
     46        * dfg/DFGNodeType.h:
     47        * dfg/DFGPredictionPropagationPhase.cpp:
     48        * dfg/DFGSafeToExecute.h:
     49        (JSC::DFG::safeToExecute):
     50        * dfg/DFGSpeculativeJIT.cpp:
     51        (JSC::DFG::SpeculativeJIT::compileGetPrivateName):
     52        (JSC::DFG::SpeculativeJIT::compileGetPrivateNameByVal):
     53        (JSC::DFG::SpeculativeJIT::compileGetPrivateNameById):
     54        * dfg/DFGSpeculativeJIT.h:
     55        * dfg/DFGSpeculativeJIT32_64.cpp:
     56        (JSC::DFG::SpeculativeJIT::compile):
     57        * dfg/DFGSpeculativeJIT64.cpp:
     58        (JSC::DFG::SpeculativeJIT::compile):
     59        * ftl/FTLCapabilities.cpp:
     60        (JSC::FTL::canCompile):
     61        * ftl/FTLLowerDFGToB3.cpp:
     62        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     63        (JSC::FTL::DFG::LowerDFGToB3::getPrivateName):
     64        (JSC::FTL::DFG::LowerDFGToB3::compileGetPrivateName):
     65        (JSC::FTL::DFG::LowerDFGToB3::compileGetPrivateNameById):
     66        * jit/ICStats.h:
     67        * jit/JITOperations.cpp:
     68        (JSC::getPrivateName):
     69        (JSC::JSC_DEFINE_JIT_OPERATION):
     70        * jit/JITOperations.h:
     71        * jit/Repatch.cpp:
     72        (JSC::appropriateOptimizingGetByFunction):
     73        (JSC::appropriateGetByFunction):
     74        (JSC::tryCacheGetBy):
     75        * jit/Repatch.h:
     76        * runtime/OptionsList.h:
     77
    1782020-10-20  Saam Barati  <sbarati@apple.com>
    279
  • trunk/Source/JavaScriptCore/bytecode/GetByStatus.cpp

    r261755 r268794  
    108108        break;
    109109    }
     110
     111    case op_get_private_name:
     112        // FIXME: Consider using LLInt caches or IC information to populate GetByStatus
     113        // https://bugs.webkit.org/show_bug.cgi?id=217245
     114        return GetByStatus(NoInformation, false);
    110115
    111116    default: {
  • trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h

    r266359 r268794  
    405405    case AccessType::GetByIdDirect:
    406406        return operationGetByIdDirectOptimize;
     407    case AccessType::GetPrivateName:
     408        return operationGetPrivateNameByIdOptimize;
    407409    case AccessType::GetByIdWithThis:
    408410    default:
     
    421423    case AccessType::GetByIdDirect:
    422424        return operationGetByIdDirectGeneric;
     425    case AccessType::GetPrivateName:
     426        return operationGetPrivateNameByIdGeneric;
    423427    case AccessType::GetByIdWithThis:
    424428    default:
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r267754 r268794  
    33493349        break;
    33503350
     3351    case GetPrivateNameById:
    33513352    case GetByIdDirect:
    33523353    case GetByIdDirectFlush:
     
    33843385    }
    33853386
     3387    case GetPrivateName:
    33863388    case GetByValWithThis:
    33873389    case GetByIdWithThis:
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r267754 r268794  
    245245    template<typename Op>
    246246    void parseGetById(const Instruction*);
     247    void simplifyGetByStatus(Node* base, GetByStatus&);
    247248    void handleGetById(
    248249        VirtualRegister destination, SpeculatedType, Node* base, CacheableIdentifier, unsigned identifierNumber, GetByStatus, AccessType, BytecodeIndex osrExitIndex);
     250    void handleGetPrivateNameById(
     251        VirtualRegister destination, SpeculatedType prediction, Node* base, CacheableIdentifier, unsigned identifierNumber, GetByStatus);
    249252    void emitPutById(
    250253        Node* base, CacheableIdentifier, Node* value,  const PutByIdStatus&, bool isDirect, ECMAMode);
     
    45314534}
    45324535
    4533 void ByteCodeParser::handleGetById(
    4534     VirtualRegister destination, SpeculatedType prediction, Node* base, CacheableIdentifier identifier, unsigned identifierNumber,
    4535     GetByStatus getByStatus, AccessType type, BytecodeIndex osrExitIndex)
     4536void ByteCodeParser::simplifyGetByStatus(Node* base, GetByStatus& getByStatus)
    45364537{
    45374538    // Attempt to reduce the set of things in the GetByStatus.
     
    45504551            getByStatus.filter(base->structure().get());
    45514552    }
     4553}
     4554
     4555void ByteCodeParser::handleGetById(
     4556    VirtualRegister destination, SpeculatedType prediction, Node* base, CacheableIdentifier identifier, unsigned identifierNumber,
     4557    GetByStatus getByStatus, AccessType type, BytecodeIndex osrExitIndex)
     4558{
     4559    simplifyGetByStatus(base, getByStatus);
    45524560   
    45534561    NodeType getById;
     
    47154723        destination, Call, InlineCallFrame::GetterCall, osrExitIndex,
    47164724        getter, numberOfParameters - 1, registerOffset, *variant.callLinkStatus(), prediction);
     4725}
     4726
     4727// A variant on handleGetById which is more limited in scope
     4728void ByteCodeParser::handleGetPrivateNameById(
     4729    VirtualRegister destination, SpeculatedType prediction, Node* base, CacheableIdentifier identifier, unsigned identifierNumber, GetByStatus getByStatus)
     4730{
     4731    simplifyGetByStatus(base, getByStatus);
     4732
     4733    ASSERT(!getByStatus.isCustom());
     4734    ASSERT(!getByStatus.makesCalls());
     4735    if (!getByStatus.isSimple() || !getByStatus.numVariants() || !Options::useAccessInlining()) {
     4736        set(destination,
     4737            addToGraph(GetPrivateNameById, OpInfo(identifier), OpInfo(prediction), base, nullptr));
     4738        return;
     4739    }
     4740
     4741    if (getByStatus.numVariants() > 1) {
     4742        if (!m_graph.m_plan.isFTL()
     4743            || !Options::usePolymorphicAccessInlining()
     4744            || getByStatus.numVariants() > Options::maxPolymorphicAccessInliningListSize()) {
     4745            set(destination,
     4746                addToGraph(GetPrivateNameById, OpInfo(identifier), OpInfo(prediction), base, nullptr));
     4747            return;
     4748        }
     4749
     4750        addToGraph(FilterGetByStatus, OpInfo(m_graph.m_plan.recordedStatuses().addGetByStatus(currentCodeOrigin(), getByStatus)), base);
     4751
     4752        Vector<MultiGetByOffsetCase, 2> cases;
     4753
     4754        for (const GetByIdVariant& variant : getByStatus.variants()) {
     4755            ASSERT(variant.intrinsic() == NoIntrinsic);
     4756            ASSERT(variant.conditionSet().isEmpty());
     4757
     4758            GetByOffsetMethod method = GetByOffsetMethod::load(variant.offset());
     4759            cases.append(MultiGetByOffsetCase(*m_graph.addStructureSet(variant.structureSet()), method));
     4760        }
     4761
     4762        if (UNLIKELY(m_graph.compilation()))
     4763            m_graph.compilation()->noticeInlinedGetById();
     4764
     4765        // 2) Emit a MultiGetByOffset
     4766        MultiGetByOffsetData* data = m_graph.m_multiGetByOffsetData.add();
     4767        data->cases = cases;
     4768        data->identifierNumber = identifierNumber;
     4769        set(destination,
     4770            addToGraph(MultiGetByOffset, OpInfo(data), OpInfo(prediction), base));
     4771        return;
     4772    }
     4773
     4774    // FIXME: If we use the GetByStatus for anything then we should record it and insert a node
     4775    // after everything else (like the GetByOffset or whatever) that will filter the recorded
     4776    // GetByStatus. That means that the constant folder also needs to do the same!
     4777    addToGraph(FilterGetByStatus, OpInfo(m_graph.m_plan.recordedStatuses().addGetByStatus(currentCodeOrigin(), getByStatus)), base);
     4778
     4779    ASSERT(getByStatus.numVariants() == 1);
     4780    GetByIdVariant variant = getByStatus[0];
     4781
     4782    Node* loadedValue = load(prediction, base, identifierNumber, variant);
     4783    if (!loadedValue) {
     4784        set(destination,
     4785            addToGraph(GetPrivateNameById, OpInfo(identifier), OpInfo(prediction), base, nullptr));
     4786        return;
     4787    }
     4788
     4789    if (UNLIKELY(m_graph.compilation()))
     4790        m_graph.compilation()->noticeInlinedGetById();
     4791
     4792    ASSERT(!variant.callLinkStatus());
     4793    if (variant.intrinsic() == NoIntrinsic)
     4794        set(destination, loadedValue);
    47174795}
    47184796
     
    63446422            handlePutAccessorByVal(PutSetterByVal, currentInstruction->as<OpPutSetterByVal>());
    63456423            NEXT_OPCODE(op_put_setter_by_val);
     6424        }
     6425
     6426        case op_get_private_name: {
     6427            auto bytecode = currentInstruction->as<OpGetPrivateName>();
     6428            SpeculatedType prediction = getPredictionWithoutOSRExit();
     6429            Node* base = get(bytecode.m_base);
     6430            Node* property = get(bytecode.m_property);
     6431            bool compileSingleIdentifier = false;
     6432
     6433            GetByStatus getByStatus = GetByStatus::computeFor(m_inlineStackTop->m_profiledBlock, m_inlineStackTop->m_baselineMap, m_icContextStack, currentCodeOrigin());
     6434
     6435            CacheableIdentifier identifier;
     6436            unsigned identifierNumber = 0;
     6437            if (!m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent)
     6438                && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType)
     6439                && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantValue)) {
     6440
     6441                identifier = getByStatus.singleIdentifier();
     6442                if (identifier) {
     6443                    identifierNumber = m_graph.identifiers().ensure(identifier.uid());
     6444                    ASSERT(identifier.isSymbolCell());
     6445                    FrozenValue* frozen = m_graph.freezeStrong(identifier.cell());
     6446                    addToGraph(CheckIsConstant, OpInfo(frozen), property);
     6447                    compileSingleIdentifier = true;
     6448                }
     6449            }
     6450
     6451            if (compileSingleIdentifier)
     6452                handleGetPrivateNameById(bytecode.m_dst, prediction, base, identifier, identifierNumber, getByStatus);
     6453            else {
     6454                Node* node = addToGraph(GetPrivateName, OpInfo(), OpInfo(prediction), base, property);
     6455                m_exitOK = false;
     6456                set(bytecode.m_dst, node);
     6457            }
     6458            NEXT_OPCODE(op_get_private_name);
    63466459        }
    63476460
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r267726 r268794  
    674674    case PutPrivateName:
    675675    case PutPrivateNameById:
     676    case GetPrivateName:
     677    case GetPrivateNameById:
    676678    case DefineDataProperty:
    677679    case DefineAccessorProperty:
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r267624 r268794  
    600600            case GetByIdDirectFlush:
    601601            case GetById:
    602             case GetByIdFlush: {
     602            case GetByIdFlush:
     603            case GetPrivateNameById: {
    603604                Edge childEdge = node->child1();
    604605                Node* child = childEdge.node();
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r267726 r268794  
    325325    case PutPrivateName:
    326326    case PutPrivateNameById:
     327    case GetPrivateName:
     328    case GetPrivateNameById:
    327329    case PutStack:
    328330    case PutToArguments:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r268656 r268794  
    17801780            break;
    17811781        }
     1782
     1783        case GetPrivateName:
     1784        case GetPrivateNameById:
     1785            if (node->child1()->shouldSpeculateCell())
     1786                fixEdge<CellUse>(node->child1());
     1787            else
     1788                fixEdge<UntypedUse>(node->child1());
     1789
     1790            if (!node->hasCacheableIdentifier())
     1791                fixEdge<SymbolUse>(node->child2());
     1792            break;
    17821793
    17831794        case DeleteByVal: {
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r267489 r268794  
    598598    void convertToGetByOffset(StorageAccessData& data, Edge storage, Edge base)
    599599    {
    600         ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == GetByIdDirect || m_op == GetByIdDirectFlush || m_op == MultiGetByOffset);
     600        ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == GetByIdDirect || m_op == GetByIdDirectFlush || m_op == GetPrivateNameById || m_op == MultiGetByOffset);
    601601        m_opInfo = &data;
    602602        children.setChild1(storage);
     
    608608    void convertToMultiGetByOffset(MultiGetByOffsetData* data)
    609609    {
    610         RELEASE_ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == GetByIdDirect || m_op == GetByIdDirectFlush);
     610        RELEASE_ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == GetByIdDirect || m_op == GetByIdDirectFlush || m_op == GetPrivateNameById);
    611611        m_opInfo = data;
    612612        child1().setUseKind(CellUse);
     
    10831083        case GetByIdDirect:
    10841084        case GetByIdDirectFlush:
     1085        case GetPrivateNameById:
    10851086        case DeleteById:
    10861087        case InById:
     
    17671768        case GetByVal:
    17681769        case GetByValWithThis:
     1770        case GetPrivateName:
     1771        case GetPrivateNameById:
    17691772        case Call:
    17701773        case DirectCall:
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r267726 r268794  
    243243    macro(CheckArray, NodeMustGenerate) \
    244244    macro(CheckArrayOrEmpty, NodeMustGenerate) \
     245    macro(GetPrivateName, NodeResultJS | NodeMustGenerate) \
     246    macro(GetPrivateNameById, NodeResultJS | NodeMustGenerate) \
    245247    /* This checks if the edge is a typed array and if it is neutered. */ \
    246248    macro(CheckNeutered, NodeMustGenerate) \
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r267726 r268794  
    876876        case GetByValWithThis:
    877877        case GetByOffset:
     878        case GetPrivateName:
     879        case GetPrivateNameById:
    878880        case MultiGetByOffset:
    879881        case GetDirectPname:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r267726 r268794  
    530530    case PutPrivateName:
    531531    case PutPrivateNameById:
     532    case GetPrivateName:
     533    case GetPrivateNameById:
    532534    case DefineDataProperty:
    533535    case DefineAccessorProperty:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r268656 r268794  
    34673467
    34683468    jsValueResult(resultRegs, node);
     3469}
     3470
     3471void SpeculativeJIT::compileGetPrivateName(Node* node)
     3472{
     3473    if (node->hasCacheableIdentifier())
     3474        return compileGetPrivateNameById(node);
     3475
     3476    switch (m_graph.child(node, 0).useKind()) {
     3477    case CellUse: {
     3478        SpeculateCellOperand base(this, m_graph.child(node, 0));
     3479        SpeculateCellOperand property(this, m_graph.child(node, 1));
     3480
     3481        compileGetPrivateNameByVal(node, JSValueRegs::payloadOnly(base.gpr()), JSValueRegs::payloadOnly(property.gpr()));
     3482        break;
     3483    }
     3484    case UntypedUse: {
     3485        JSValueOperand base(this, m_graph.child(node, 0));
     3486        SpeculateCellOperand property(this, m_graph.child(node, 1));
     3487
     3488        compileGetPrivateNameByVal(node, base.jsValueRegs(), JSValueRegs::payloadOnly(property.gpr()));
     3489        break;
     3490    }
     3491    default:
     3492        DFG_CRASH(m_jit.graph(), node, "Bad use kind");
     3493    }
     3494}
     3495
     3496void SpeculativeJIT::compileGetPrivateNameByVal(Node* node, JSValueRegs base, JSValueRegs property)
     3497{
     3498    DFG_ASSERT(m_jit.graph(), node, node->op() == GetPrivateName);
     3499    DFG_ASSERT(m_jit.graph(), node, m_graph.child(node, 1).useKind() == SymbolUse);
     3500    speculateSymbol(m_graph.child(node, 1));
     3501
     3502    JSValueRegsTemporary result(this);
     3503    CodeOrigin codeOrigin = node->origin.semantic;
     3504    CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
     3505    RegisterSet usedRegisters = this->usedRegisters();
     3506
     3507    JITCompiler::JumpList slowCases;
     3508    const bool baseIsKnownCell = m_state.forNode(m_graph.child(node, 0)).isType(SpecCell);
     3509    if (!baseIsKnownCell)
     3510        slowCases.append(m_jit.branchIfNotCell(base));
     3511
     3512    JITGetByValGenerator gen(
     3513        m_jit.codeBlock(), codeOrigin, callSite, AccessType::GetPrivateName, usedRegisters,
     3514        base, property, result.regs());
     3515    gen.stubInfo()->propertyIsSymbol = true;
     3516    gen.generateFastPath(m_jit);
     3517
     3518    slowCases.append(gen.slowPathJump());
     3519
     3520    auto makeSlowPathCall = [&](auto base) {
     3521        return slowPathCall(
     3522            slowCases, this, operationGetPrivateNameOptimize,
     3523            result.regs(), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(),
     3524            base, CCallHelpers::CellValue(property.payloadGPR()));
     3525    };
     3526
     3527    std::unique_ptr<SlowPathGenerator> slowPath = baseIsKnownCell
     3528        ? makeSlowPathCall(CCallHelpers::CellValue(base.payloadGPR()))
     3529        : makeSlowPathCall(base);
     3530
     3531    m_jit.addGetByVal(gen, slowPath.get());
     3532    addSlowPathGenerator(WTFMove(slowPath));
     3533
     3534    jsValueResult(result.regs(), node, DataFormatJS);
     3535}
     3536
     3537void SpeculativeJIT::compileGetPrivateNameById(Node* node)
     3538{
     3539    switch (m_graph.child(node, 0).useKind()) {
     3540    case CellUse: {
     3541        SpeculateCellOperand base(this, m_graph.child(node, 0));
     3542        JSValueRegsTemporary result(this, Reuse, base);
     3543
     3544        JSValueRegs baseRegs = JSValueRegs::payloadOnly(base.gpr());
     3545        JSValueRegs resultRegs = result.regs();
     3546
     3547        cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->cacheableIdentifier(), JITCompiler::Jump(), NeedToSpill, AccessType::GetPrivateName);
     3548
     3549        jsValueResult(resultRegs, node, DataFormatJS);
     3550        break;
     3551    }
     3552
     3553    case UntypedUse: {
     3554        JSValueOperand base(this, m_graph.child(node, 0));
     3555        JSValueRegsTemporary result(this, Reuse, base);
     3556
     3557        JSValueRegs baseRegs = base.jsValueRegs();
     3558        JSValueRegs resultRegs = result.regs();
     3559
     3560        JITCompiler::Jump notCell = m_jit.branchIfNotCell(baseRegs);
     3561
     3562        cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->cacheableIdentifier(), notCell, NeedToSpill, AccessType::GetPrivateName);
     3563
     3564        jsValueResult(resultRegs, node, DataFormatJS);
     3565        break;
     3566    }
     3567
     3568    default:
     3569        DFG_CRASH(m_jit.graph(), node, "Bad use kind");
     3570        break;
     3571    }
    34693572}
    34703573
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r267489 r268794  
    12831283    void compileGetByValOnDirectArguments(Node*);
    12841284    void compileGetByValOnScopedArguments(Node*);
    1285    
     1285
     1286    void compileGetPrivateName(Node*);
     1287    void compileGetPrivateNameById(Node*);
     1288    void compileGetPrivateNameByVal(Node*, JSValueRegs base, JSValueRegs property);
     1289
    12861290    void compileGetScope(Node*);
    12871291    void compileSkipScope(Node*);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r267726 r268794  
    22392239    case ArrayifyToStructure: {
    22402240        arrayify(node);
     2241        break;
     2242    }
     2243
     2244    case GetPrivateName:
     2245    case GetPrivateNameById: {
     2246        compileGetPrivateName(node);
    22412247        break;
    22422248    }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r267726 r268794  
    26152615    case ArrayifyToStructure: {
    26162616        arrayify(node);
     2617        break;
     2618    }
     2619
     2620    case GetPrivateName:
     2621    case GetPrivateNameById: {
     2622        compileGetPrivateName(node);
    26172623        break;
    26182624    }
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r267726 r268794  
    398398    case PutPrivateName:
    399399    case PutPrivateNameById:
     400    case GetPrivateName:
     401    case GetPrivateNameById:
    400402    case MatchStructure:
    401403    case FilterCallLinkStatus:
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r268783 r268794  
    949949            compileGetById(AccessType::GetByIdDirect);
    950950            break;
     951        case GetPrivateName:
     952            compileGetPrivateName();
     953            break;
     954        case GetPrivateNameById:
     955            compileGetPrivateNameById();
     956            break;
    951957        case InById:
    952958            compileInById();
     
    39403946        LValue result = vmCall(Int64, operationGetByValWithThis, weakPointer(globalObject), base, thisValue, subscript);
    39413947        setJSValue(result);
     3948    }
     3949
     3950    LValue getPrivateName(LValue base, LValue property)
     3951    {
     3952        Node* node = m_node;
     3953        PatchpointValue* patchpoint = m_out.patchpoint(Int64);
     3954        patchpoint->appendSomeRegister(base);
     3955        patchpoint->appendSomeRegister(property);
     3956        patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister));
     3957        patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister));
     3958        patchpoint->clobber(RegisterSet::macroScratchRegisters());
     3959
     3960        RefPtr<PatchpointExceptionHandle> exceptionHandle = preparePatchpointForExceptions(patchpoint);
     3961
     3962        State* state = &m_ftlState;
     3963        bool baseIsCell = abstractValue(node->child1()).isType(SpecCell);
     3964        patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
     3965                AllowMacroScratchRegisterUsage allowScratch(jit);
     3966
     3967                CallSiteIndex callSiteIndex = state->jitCode->common.codeOrigins->addUniqueCallSiteIndex(node->origin.semantic);
     3968
     3969                // This is the direct exit target for operation calls.
     3970                Box<CCallHelpers::JumpList> exceptions = exceptionHandle->scheduleExitCreation(params)->jumps(jit);
     3971
     3972                // This is the exit for call IC's created by the IC for getters. We don't have
     3973                // to do anything weird other than call this, since it will associate the exit with
     3974                // the callsite index.
     3975                exceptionHandle->scheduleExitCreationForUnwind(params, callSiteIndex);
     3976
     3977                GPRReg resultGPR = params[0].gpr();
     3978                GPRReg baseGPR = params[1].gpr();
     3979                GPRReg propertyGPR = params[2].gpr();
     3980
     3981                auto generator = Box<JITGetByValGenerator>::create(
     3982                    jit.codeBlock(), node->origin.semantic, callSiteIndex, AccessType::GetPrivateName,
     3983                    params.unavailableRegisters(), JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(resultGPR));
     3984
     3985                CCallHelpers::Jump notCell;
     3986                if (!baseIsCell)
     3987                    notCell = jit.branchIfNotCell(baseGPR);
     3988
     3989                generator->generateFastPath(jit);
     3990                CCallHelpers::Label done = jit.label();
     3991
     3992                params.addLatePath([=] (CCallHelpers& jit) {
     3993                    AllowMacroScratchRegisterUsage allowScratch(jit);
     3994
     3995                    if (notCell.isSet())
     3996                        notCell.link(&jit);
     3997                    generator->slowPathJump().link(&jit);
     3998                    CCallHelpers::Label slowPathBegin = jit.label();
     3999                    CCallHelpers::Call slowPathCall = callOperation(
     4000                        *state, params.unavailableRegisters(), jit, node->origin.semantic,
     4001                        exceptions.get(), operationGetPrivateNameOptimize, resultGPR,
     4002                        jit.codeBlock()->globalObjectFor(node->origin.semantic),
     4003                        CCallHelpers::TrustedImmPtr(generator->stubInfo()), baseGPR, propertyGPR).call();
     4004                    jit.jump().linkTo(done, &jit);
     4005
     4006                    generator->reportSlowPathCall(slowPathBegin, slowPathCall);
     4007
     4008                    jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
     4009                        generator->finalize(linkBuffer, linkBuffer);
     4010                    });
     4011                });
     4012            });
     4013       
     4014        return patchpoint;
     4015    }
     4016
     4017    void compileGetPrivateName()
     4018    {
     4019        if (m_node->child1().useKind() == CellUse)
     4020            setJSValue(getPrivateName(lowCell(m_node->child1()), lowSymbol(m_node->child2())));
     4021        else {
     4022            LValue base = lowJSValue(m_node->child1());
     4023            LValue property = lowSymbol(m_node->child2());
     4024
     4025            LBasicBlock baseCellCase = m_out.newBlock();
     4026            LBasicBlock notCellCase = m_out.newBlock();
     4027            LBasicBlock continuation = m_out.newBlock();
     4028
     4029            m_out.branch(
     4030                isCell(base, provenType(m_node->child1())), unsure(baseCellCase), unsure(notCellCase));
     4031
     4032            LBasicBlock lastNext = m_out.appendTo(baseCellCase, notCellCase);
     4033
     4034            ValueFromBlock cellResult = m_out.anchor(getPrivateName(base, property));
     4035            m_out.jump(continuation);
     4036
     4037            m_out.appendTo(notCellCase, continuation);
     4038            JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
     4039            ValueFromBlock notCellResult = m_out.anchor(vmCall(
     4040                Int64, operationGetPrivateName,
     4041                weakPointer(globalObject), m_out.constIntPtr(0), base,
     4042                property));
     4043            m_out.jump(continuation);
     4044
     4045            m_out.appendTo(continuation, lastNext);
     4046            setJSValue(m_out.phi(Int64, cellResult, notCellResult));
     4047        }
     4048    }
     4049
     4050    void compileGetPrivateNameById()
     4051    {
     4052        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
     4053        if (m_node->child1().useKind() == CellUse)
     4054            setJSValue(getById(lowCell(m_node->child1()), AccessType::GetPrivateName));
     4055        else {
     4056            LValue base = lowJSValue(m_node->child1());
     4057
     4058            LBasicBlock baseCellCase = m_out.newBlock();
     4059            LBasicBlock notCellCase = m_out.newBlock();
     4060            LBasicBlock continuation = m_out.newBlock();
     4061
     4062            m_out.branch(
     4063                isCell(base, provenType(m_node->child1())), unsure(baseCellCase), unsure(notCellCase));
     4064
     4065            LBasicBlock lastNext = m_out.appendTo(baseCellCase, notCellCase);
     4066
     4067            ValueFromBlock cellResult = m_out.anchor(getById(base, AccessType::GetPrivateName));
     4068            m_out.jump(continuation);
     4069
     4070            m_out.appendTo(notCellCase, continuation);
     4071            ValueFromBlock notCellResult = m_out.anchor(vmCall(
     4072                Int64, operationGetPrivateNameByIdGeneric,
     4073                weakPointer(globalObject), base,
     4074                m_out.constIntPtr(m_node->cacheableIdentifier().rawBits())));
     4075            m_out.jump(continuation);
     4076
     4077            m_out.appendTo(continuation, lastNext);
     4078            setJSValue(m_out.phi(Int64, cellResult, notCellResult));
     4079        }
    39424080    }
    39434081
  • trunk/Source/JavaScriptCore/jit/ICStats.h

    r268077 r268794  
    7373    macro(DelByReplaceWithJump) \
    7474    macro(DelByReplaceWithGeneric) \
    75     macro(OperationGetPrivateNameOptimize)
     75    macro(OperationGetPrivateNameOptimize) \
     76    macro(OperationGetPrivateNameById) \
     77    macro(OperationGetPrivateNameByIdOptimize) \
     78    macro(OperationGetPrivateNameByIdGeneric)
    7679
    7780class ICEvent {
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r268656 r268794  
    22622262}
    22632263
     2264ALWAYS_INLINE static JSValue getPrivateName(JSGlobalObject* globalObject, CallFrame* callFrame, JSValue baseValue, Identifier fieldName)
     2265{
     2266    ASSERT(fieldName.isPrivateName());
     2267    UNUSED_PARAM(callFrame);
     2268    VM& vm = globalObject->vm();
     2269    auto scope = DECLARE_THROW_SCOPE(vm);
     2270
     2271    baseValue.requireObjectCoercible(globalObject);
     2272    RETURN_IF_EXCEPTION(scope, JSValue());
     2273
     2274    JSObject* base = baseValue.toObject(globalObject);
     2275    PropertySlot slot(base, PropertySlot::InternalMethodType::GetOwnProperty);
     2276    base->getPrivateField(globalObject, fieldName, slot);
     2277    RETURN_IF_EXCEPTION(scope, JSValue());
     2278
     2279    return slot.getValue(globalObject, fieldName);
     2280}
     2281
    22642282JSC_DEFINE_JIT_OPERATION(operationGetPrivateNameOptimize, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedBase, EncodedJSValue encodedFieldName))
    22652283{
     
    22812299
    22822300        JSObject* base = jsCast<JSObject*>(baseValue.asCell());
    2283         RETURN_IF_EXCEPTION(scope, encodedJSValue());
    22842301
    22852302        PropertySlot slot(base, PropertySlot::InternalMethodType::GetOwnProperty);
     
    23072324    JSValue fieldNameValue = JSValue::decode(encodedFieldName);
    23082325
     2326    if (stubInfo)
     2327        stubInfo->tookSlowPath = true;
     2328
     2329    return JSValue::encode(getPrivateName(globalObject, callFrame, baseValue, fieldNameValue));
     2330}
     2331
     2332JSC_DEFINE_JIT_OPERATION(operationGetPrivateNameById, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
     2333{
     2334    SuperSamplerScope superSamplerScope(false);
     2335
     2336    VM& vm = globalObject->vm();
     2337    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     2338    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     2339
    23092340    stubInfo->tookSlowPath = true;
    23102341
    2311     return JSValue::encode(getPrivateName(globalObject, callFrame, baseValue, fieldNameValue));
     2342    JSValue baseValue = JSValue::decode(base);
     2343    CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
     2344    Identifier fieldName = Identifier::fromUid(vm, identifier.uid());
     2345
     2346    JSValue result = getPrivateName(globalObject, callFrame, baseValue, fieldName);
     2347
     2348    LOG_IC((ICEvent::OperationGetPrivateNameById, baseValue.classInfoOrNull(vm), fieldName, true));
     2349
     2350    return JSValue::encode(result);
     2351}
     2352
     2353JSC_DEFINE_JIT_OPERATION(operationGetPrivateNameByIdOptimize, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
     2354{
     2355    SuperSamplerScope superSamplerScope(false);
     2356
     2357    VM& vm = globalObject->vm();
     2358    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     2359    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     2360    CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
     2361    auto scope = DECLARE_THROW_SCOPE(vm);
     2362
     2363    JSValue baseValue = JSValue::decode(base);
     2364    auto fieldName = Identifier::fromUid(vm, identifier.uid());
     2365
     2366    if (baseValue.isObject()) {
     2367        JSObject* base = jsCast<JSObject*>(baseValue.asCell());
     2368
     2369        PropertySlot slot(base, PropertySlot::InternalMethodType::GetOwnProperty);
     2370        base->getPrivateField(globalObject, fieldName, slot);
     2371        RETURN_IF_EXCEPTION(scope, encodedJSValue());
     2372
     2373        LOG_IC((ICEvent::OperationGetPrivateNameOptimize, baseValue.classInfoOrNull(vm), fieldName, true));
     2374
     2375        CodeBlock* codeBlock = callFrame->codeBlock();
     2376        if (stubInfo->considerCachingBy(vm, codeBlock, baseValue.structureOrNull(vm), identifier))
     2377            repatchGetBy(globalObject, codeBlock, baseValue, identifier, slot, *stubInfo, GetByKind::PrivateNameById);
     2378        return JSValue::encode(slot.getValue(globalObject, fieldName));
     2379    }
     2380
     2381    return JSValue::encode(getPrivateName(globalObject, callFrame, baseValue, fieldName));
     2382}
     2383
     2384JSC_DEFINE_JIT_OPERATION(operationGetPrivateNameByIdGeneric, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
     2385{
     2386    SuperSamplerScope superSamplerScope(false);
     2387
     2388    VM& vm = globalObject->vm();
     2389    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     2390    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     2391
     2392    JSValue baseValue = JSValue::decode(base);
     2393    CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
     2394    Identifier fieldName = Identifier::fromUid(vm, identifier.uid());
     2395
     2396    JSValue result = getPrivateName(globalObject, callFrame, baseValue, fieldName);
     2397
     2398    LOG_IC((ICEvent::OperationGetPrivateNameByIdGeneric, baseValue.classInfoOrNull(vm), fieldName, true));
     2399
     2400    return JSValue::encode(result);
    23122401}
    23132402
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r268385 r268794  
    270270JSC_DECLARE_JIT_OPERATION(operationGetPrivateName, EncodedJSValue, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedBase, EncodedJSValue encodedFieldName));
    271271JSC_DECLARE_JIT_OPERATION(operationGetPrivateNameOptimize, EncodedJSValue, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedBase, EncodedJSValue encodedFieldName));
     272JSC_DECLARE_JIT_OPERATION(operationGetPrivateNameById, EncodedJSValue, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue, uintptr_t));
     273JSC_DECLARE_JIT_OPERATION(operationGetPrivateNameByIdOptimize, EncodedJSValue, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue, uintptr_t));
     274JSC_DECLARE_JIT_OPERATION(operationGetPrivateNameByIdGeneric, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, uintptr_t));
    272275
    273276JSC_DECLARE_JIT_OPERATION(operationSwitchCharWithUnknownKeyType, char*, (JSGlobalObject*, EncodedJSValue key, size_t tableIndex));
  • trunk/Source/JavaScriptCore/jit/Repatch.cpp

    r268247 r268794  
    166166    case GetByKind::PrivateName:
    167167        return operationGetPrivateNameOptimize;
     168    case GetByKind::PrivateNameById:
     169        return operationGetPrivateNameByIdOptimize;
    168170    }
    169171    RELEASE_ASSERT_NOT_REACHED();
     
    185187    case GetByKind::PrivateName:
    186188        return operationGetPrivateName;
     189    case GetByKind::PrivateNameById:
     190        return operationGetPrivateNameById;
    187191    }
    188192    RELEASE_ASSERT_NOT_REACHED();
     
    204208            return GiveUpOnCache;
    205209        JSCell* baseCell = baseValue.asCell();
    206         const bool isPrivate = kind == GetByKind::PrivateName;
     210        const bool isPrivate = kind == GetByKind::PrivateName || kind == GetByKind::PrivateNameById;
    207211
    208212        std::unique_ptr<AccessCase> newCase;
  • trunk/Source/JavaScriptCore/jit/Repatch.h

    r265000 r268794  
    4141    Direct,
    4242    PrivateName,
     43    PrivateNameById,
    4344};
    4445
  • trunk/Source/JavaScriptCore/runtime/OptionsList.h

    r268760 r268794  
    572572
    573573#define FOR_EACH_JSC_EXPERIMENTAL_OPTION(v) \
    574     v(usePrivateClassFields, LLIntAndBaselineOnly, "https://bugs.webkit.org/show_bug.cgi?id=212781", "https://bugs.webkit.org/show_bug.cgi?id=212784")
     574    v(usePrivateClassFields, SupportsFTL | SupportsDFG, "https://bugs.webkit.org/show_bug.cgi?id=212781", "https://bugs.webkit.org/show_bug.cgi?id=212784")
    575575
    576576constexpr size_t countNumberOfJSCOptions()
Note: See TracChangeset for help on using the changeset viewer.