Ignore:
Timestamp:
Jul 28, 2020, 12:28:16 PM (5 years ago)
Author:
[email protected]
Message:

[JSC] add IC support for op_get_private_name
https://bugs.webkit.org/show_bug.cgi?id=213545

Reviewed by Saam Barati.

JSTests:

Add a crashtest for a crash in an earlier edition of the GPN IC patch.

  • stress/get-private-name-cache-failure.js: Added.

Source/JavaScriptCore:

The baseline JIT now supports a fast path for op_private_name,
using a variant of GetByVal IC.

The generated AccessCase has the following qualities:

  • Always "direct", relying only on the current structure for cachebility
  • Never impure (DOM properties are not supported at this time, ProxyObjects are treated as JSObjects)

Based on the microbenchmark reviewed on https://bugs.webkit.org/show_bug.cgi?id=213544, this sees
an improvement of roughly 50% on average.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::finishCreation):

  • bytecode/StructureStubInfo.cpp:

(JSC::StructureStubInfo::reset):

  • bytecode/StructureStubInfo.h:
  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):

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

(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):

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

(JSC::JITGetByValGenerator::JITGetByValGenerator):

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

(JSC::getPrivateName):

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

(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emit_op_get_private_name):
(JSC::JIT::emitSlow_op_get_private_name):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emit_op_get_private_name):
(JSC::JIT::emitSlow_op_get_private_name):

  • jit/Repatch.cpp:

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

  • jit/Repatch.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/jit/Repatch.cpp

    r264388 r265000  
    163163    case GetByKind::NormalByVal:
    164164        return operationGetByValOptimize;
     165    case GetByKind::PrivateName:
     166        return operationGetPrivateNameOptimize;
    165167    }
    166168    RELEASE_ASSERT_NOT_REACHED();
     
    180182    case GetByKind::NormalByVal:
    181183        return operationGetByValGeneric;
     184    case GetByKind::PrivateName:
     185        return operationGetPrivateName;
    182186    }
    183187    RELEASE_ASSERT_NOT_REACHED();
     
    199203            return GiveUpOnCache;
    200204        JSCell* baseCell = baseValue.asCell();
     205        const bool isPrivate = kind == GetByKind::PrivateName;
    201206
    202207        std::unique_ptr<AccessCase> newCase;
     
    254259            bool loadTargetFromProxy = false;
    255260            if (baseCell->type() == PureForwardingProxyType) {
     261                if (isPrivate)
     262                    return GiveUpOnCache;
    256263                baseValue = jsCast<JSProxy*>(baseCell)->target();
    257264                baseCell = baseValue.asCell();
     
    309316                    return GiveUpOnCache;
    310317
    311                 // If a kind is GetByKind::Direct, we do not need to investigate prototype chains further.
     318                // If a kind is GetByKind::Direct or GetByKind::PrivateName, we do not need to investigate prototype chains further.
    312319                // Cacheability just depends on the head structure.
    313                 if (kind != GetByKind::Direct) {
     320                if (kind != GetByKind::Direct && !isPrivate) {
    314321                    auto cacheStatus = prepareChainForCaching(globalObject, baseCell, slot);
    315322                    if (!cacheStatus)
     
    375382                newCase = IntrinsicGetterAccessCase::create(vm, codeBlock, propertyName, slot.cachedOffset(), structure, conditionSet, getter, WTFMove(prototypeAccessChain));
    376383            else {
    377                 if (slot.isCacheableValue() || slot.isUnset()) {
     384                if (isPrivate) {
     385                    RELEASE_ASSERT(!slot.isUnset());
     386                    constexpr bool isProxy = false;
     387                    if (!slot.isCacheable())
     388                        return GiveUpOnCache;
     389                    newCase = ProxyableAccessCase::create(vm, codeBlock, AccessCase::Load, propertyName, offset, structure,
     390                        conditionSet, isProxy, slot.watchpointSet(), WTFMove(prototypeAccessChain));
     391                } else if (slot.isCacheableValue() || slot.isUnset()) {
    378392                    newCase = ProxyableAccessCase::create(vm, codeBlock, slot.isUnset() ? AccessCase::Miss : AccessCase::Load,
    379393                        propertyName, offset, structure, conditionSet, loadTargetFromProxy, slot.watchpointSet(), WTFMove(prototypeAccessChain));
Note: See TracChangeset for help on using the changeset viewer.