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

Changeset 286635 in webkit


Ignore:
Timestamp:
Dec 7, 2021, 5:43:22 PM (5 years ago)
Author:
Ross Kirsling
Message:

[JSC] Add LLInt IC for try_get_by_id of own cacheable value
https://bugs.webkit.org/show_bug.cgi?id=233830

Reviewed by Yusuke Suzuki.

This patch adds an LLInt IC for the "own cacheable value" path of try_get_by_id;
this is the simplest case and basically the same as get_by_id_direct.

Performance is neutral with JIT enabled as well as on current uses of try_get_by_id in JSC
(e.g. hasObservableSideEffectsForRegexpSplit), but microbenchmarks of try_get_by_id itself see a 2x speedup:

Before After

try-get-by-id-polymorphic 123.8361+-0.4562 61.7586+-0.3770 definitely 2.0052x faster
try-get-by-id-basic 124.4437+-0.6091 61.0340+-0.1924 definitely 2.0389x faster

<geometric> 124.1207+-0.3130 61.3865+-0.2019 definitely 2.0220x faster

  • bytecode/BytecodeList.rb:
  • bytecode/CodeBlock.cpp:
  • bytecode/GetByStatus.cpp:
  • llint/LLIntSlowPaths.cpp:
  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
Location:
trunk/Source/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r286597 r286635  
     12021-12-07  Ross Kirsling  <ross.kirsling@sony.com>
     2
     3        [JSC] Add LLInt IC for try_get_by_id of own cacheable value
     4        https://bugs.webkit.org/show_bug.cgi?id=233830
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        This patch adds an LLInt IC for the "own cacheable value" path of try_get_by_id;
     9        this is the simplest case and basically the same as get_by_id_direct.
     10
     11        Performance is neutral with JIT enabled as well as on current uses of try_get_by_id in JSC
     12        (e.g. hasObservableSideEffectsForRegexpSplit), but microbenchmarks of try_get_by_id itself see a 2x speedup:
     13
     14                                             Before                    After
     15
     16        try-get-by-id-polymorphic      123.8361+-0.4562     ^     61.7586+-0.3770        ^ definitely 2.0052x faster
     17        try-get-by-id-basic            124.4437+-0.6091     ^     61.0340+-0.1924        ^ definitely 2.0389x faster
     18
     19        <geometric>                    124.1207+-0.3130     ^     61.3865+-0.2019        ^ definitely 2.0220x faster
     20
     21
     22        * bytecode/BytecodeList.rb:
     23        * bytecode/CodeBlock.cpp:
     24        * bytecode/GetByStatus.cpp:
     25        * llint/LLIntSlowPaths.cpp:
     26        * llint/LowLevelInterpreter.asm:
     27        * llint/LowLevelInterpreter32_64.asm:
     28        * llint/LowLevelInterpreter64.asm:
     29
    1302021-12-07  Commit Queue  <commit-queue@webkit.org>
    231
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb

    r285795 r286635  
    524524    metadata: {
    525525        profile: ValueProfile,
     526        structureID: StructureID,
     527        offset: unsigned,
    526528    }
    527529
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r286345 r286635  
    13871387        });
    13881388
     1389        m_metadata->forEach<OpTryGetById>([&] (auto& metadata) {
     1390            StructureID oldStructureID = metadata.m_structureID;
     1391            if (!oldStructureID || vm.heap.isMarked(oldStructureID.decode()))
     1392                return;
     1393            dataLogLnIf(Options::verboseOSR(), "Clearing try_get_by_id LLInt property access.");
     1394            metadata.m_structureID = StructureID();
     1395            metadata.m_offset = 0;
     1396        });
     1397
    13891398        m_metadata->forEach<OpGetByIdDirect>([&] (auto& metadata) {
    13901399            StructureID oldStructureID = metadata.m_structureID;
    13911400            if (!oldStructureID || vm.heap.isMarked(oldStructureID.decode()))
    13921401                return;
    1393             dataLogLnIf(Options::verboseOSR(), "Clearing LLInt property access.");
     1402            dataLogLnIf(Options::verboseOSR(), "Clearing get_by_id_direct LLInt property access.");
    13941403            metadata.m_structureID = StructureID();
    13951404            metadata.m_offset = 0;
     
    14621471                return;
    14631472
    1464             dataLogLnIf(Options::verboseOSR(), "Clearing LLInt set_private_brand transition.");
     1473            dataLogLnIf(Options::verboseOSR(), "Clearing LLInt check_private_brand transition.");
    14651474            metadata.m_structureID = StructureID();
    14661475            metadata.m_brand.clear();
  • trunk/Source/JavaScriptCore/bytecode/GetByStatus.cpp

    r286345 r286635  
    7171        break;
    7272    }
     73
     74    case op_try_get_by_id:
     75        structureID = instruction->as<OpTryGetById>().metadata(profiledBlock).m_structureID;
     76        identifier = &(profiledBlock->identifier(instruction->as<OpTryGetById>().m_property));
     77        break;
    7378    case op_get_by_id_direct:
    7479        structureID = instruction->as<OpGetByIdDirect>().metadata(profiledBlock).m_structureID;
    7580        identifier = &(profiledBlock->identifier(instruction->as<OpGetByIdDirect>().m_property));
    7681        break;
    77     case op_try_get_by_id: {
    78         // FIXME: We should not just bail if we see a try_get_by_id.
    79         // https://bugs.webkit.org/show_bug.cgi?id=158039
    80         return GetByStatus(NoInformation, false);
    81     }
    8282
    8383    case op_get_by_val:
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r286345 r286635  
    665665    JSValue result = slot.getPureResult();
    666666
     667    if (!LLINT_ALWAYS_ACCESS_SLOW && slot.isCacheable() && !slot.isUnset()) {
     668        ASSERT(!slot.isTaintedByOpaqueObject());
     669        ASSERT(baseValue.isCell());
     670
     671        auto& metadata = bytecode.metadata(codeBlock);
     672        {
     673            StructureID oldStructureID = metadata.m_structureID;
     674            if (oldStructureID) {
     675                Structure* a = oldStructureID.decode();
     676                Structure* b = baseValue.asCell()->structure(vm);
     677
     678                if (Structure::shouldConvertToPolyProto(a, b)) {
     679                    ASSERT(a->rareData()->sharedPolyProtoWatchpoint().get() == b->rareData()->sharedPolyProtoWatchpoint().get());
     680                    a->rareData()->sharedPolyProtoWatchpoint()->invalidate(vm, StringFireDetail("Detected poly proto opportunity."));
     681                }
     682            }
     683        }
     684
     685        JSCell* baseCell = baseValue.asCell();
     686        Structure* structure = baseCell->structure(vm);
     687        if (slot.isValue() && slot.slotBase() == baseValue) {
     688            // Start out by clearing out the old cache.
     689            metadata.m_structureID = StructureID();
     690            metadata.m_offset = 0;
     691
     692            if (structure->propertyAccessesAreCacheable() && !structure->needImpurePropertyWatchpoint()) {
     693                {
     694                    ConcurrentJSLocker locker(codeBlock->m_lock);
     695                    metadata.m_structureID = structure->id();
     696                    metadata.m_offset = slot.cachedOffset();
     697                }
     698                vm.writeBarrier(codeBlock);
     699            }
     700        }
     701    }
     702
    667703    LLINT_RETURN_PROFILED(result);
    668704}
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r286345 r286635  
    21812181llintSlowPathOp(super_sampler_end)
    21822182llintSlowPathOp(throw)
    2183 llintSlowPathOp(try_get_by_id)
    21842183llintSlowPathOp(get_by_id_with_this)
    21852184
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r285795 r286635  
    14221422# execution counter hits zero.
    14231423
     1424llintOpWithMetadata(op_try_get_by_id, OpTryGetById, macro (size, get, dispatch, metadata, return)
     1425    metadata(t5, t0)
     1426    get(m_base, t0)
     1427    loadi OpTryGetById::Metadata::m_structureID[t5], t1
     1428    loadConstantOrVariablePayload(size, t0, CellTag, t3, .opTryGetByIdSlow)
     1429    loadi OpTryGetById::Metadata::m_offset[t5], t2
     1430    bineq JSCell::m_structureID[t3], t1, .opTryGetByIdSlow
     1431    loadPropertyAtVariableOffset(t2, t3, t0, t1)
     1432    valueProfile(OpTryGetById, m_profile, t5, t0, t1)
     1433    return(t0, t1)
     1434
     1435.opTryGetByIdSlow:
     1436    callSlowPath(_llint_slow_path_try_get_by_id)
     1437    dispatch()
     1438end)
     1439
    14241440llintOpWithMetadata(op_get_by_id_direct, OpGetByIdDirect, macro (size, get, dispatch, metadata, return)
    14251441    metadata(t5, t0)
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r286372 r286635  
    15331533end
    15341534
     1535
     1536llintOpWithMetadata(op_try_get_by_id, OpTryGetById, macro (size, get, dispatch, metadata, return)
     1537    metadata(t2, t0)
     1538    get(m_base, t0)
     1539    loadConstantOrVariableCell(size, t0, t3, .opTryGetByIdSlow)
     1540    loadi JSCell::m_structureID[t3], t1
     1541    loadi OpTryGetById::Metadata::m_structureID[t2], t0
     1542    bineq t0, t1, .opTryGetByIdSlow
     1543    loadi OpTryGetById::Metadata::m_offset[t2], t1
     1544    loadPropertyAtVariableOffset(t1, t3, t0)
     1545    valueProfile(OpTryGetById, m_profile, t2, t0)
     1546    return(t0)
     1547
     1548.opTryGetByIdSlow:
     1549    callSlowPath(_llint_slow_path_try_get_by_id)
     1550    dispatch()
     1551end)
    15351552
    15361553llintOpWithMetadata(op_get_by_id_direct, OpGetByIdDirect, macro (size, get, dispatch, metadata, return)
Note: See TracChangeset for help on using the changeset viewer.