Changeset 262562 in webkit


Ignore:
Timestamp:
Jun 4, 2020 12:54:17 PM (4 years ago)
Author:
mark.lam@apple.com
Message:

Reduce DFGDoesGCCheck to only storing a uint32_t.
https://bugs.webkit.org/show_bug.cgi?id=212734

Reviewed by Saam Barati and Caio Lima.

This patch changes the encoding of DoesGCCheck so that it will fit better in a
uint32_t. This has the following benefits:

  1. speed improvement for debug builds because it now takes less instructions (especially in JITted code) to store to DoesGCCheck::m_value.
  2. enables this check for 32-bit platforms as well.

Fun fact: we currently have 373 DFG::NodeTypes. Hence, 9 bits for nodeOp.

The new encoding provides 21 bis for the nodeIndex. This gives us up to 2097152
node indexes. In my experience, I've never seen more than 3 decimal digits for
the nodeIndex so far. If we ever find that we need more than 21 bits of nodeIndex,
we have 2 options to deal with it:

  1. We can just ignore the high bits. After all, it is the nodeOp that is the most interesting piece of data we need to debug doesGC issues.
  1. We can make DoesGCCheck use uint64_t for storage. This encoding automatically scales to 64-bit, while still allowing the more efficient form of storing a 32-bit immediate to be used for the common cases.

This patch also makes ENABLE_DFG_DOES_GC_VALIDATION dependent on ENABLE(DFG_JIT).
DoesGC is only relevant for the DFG and FTL JITs.

  • dfg/DFGDoesGCCheck.cpp:

(JSC::DFG::DoesGCCheck::verifyCanGC):

  • dfg/DFGDoesGCCheck.h:

(JSC::DFG::DoesGCCheck::encode):
(JSC::DFG::DoesGCCheck::expectDoesGC const):
(JSC::DFG::DoesGCCheck::isSpecial const):
(JSC::DFG::DoesGCCheck::special):
(JSC::DFG::DoesGCCheck::nodeOp):
(JSC::DFG::DoesGCCheck::nodeIndex):
(JSC::DFG::DoesGCCheck::expectDoesGC): Deleted.
(JSC::DFG::DoesGCCheck::isSpecial): Deleted.
(JSC::DFG::DoesGCCheck::specialIndex): Deleted.
(JSC::DFG::DoesGCCheck::bits): Deleted.

  • dfg/DFGNodeType.h:
  • dfg/DFGOSRExit.cpp:

(JSC::DFG::OSRExit::compileExit):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):

  • ftl/FTLOSRExitCompiler.cpp:

(JSC::FTL::compileStub):

  • heap/Heap.h:
Location:
trunk/Source/JavaScriptCore
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r262542 r262562  
     12020-06-04  Mark Lam  <mark.lam@apple.com>
     2
     3        Reduce DFGDoesGCCheck to only storing a uint32_t.
     4        https://bugs.webkit.org/show_bug.cgi?id=212734
     5
     6        Reviewed by Saam Barati and Caio Lima.
     7
     8        This patch changes the encoding of DoesGCCheck so that it will fit better in a
     9        uint32_t.  This has the following benefits:
     10        1. speed improvement for debug builds because it now takes less instructions
     11           (especially in JITted code) to store to DoesGCCheck::m_value.
     12        2. enables this check for 32-bit platforms as well.
     13
     14        Fun fact: we currently have 373 DFG::NodeTypes.  Hence, 9 bits for nodeOp.
     15
     16        The new encoding provides 21 bis for the nodeIndex.  This gives us up to 2097152
     17        node indexes.  In my experience, I've never seen more than 3 decimal digits for
     18        the nodeIndex so far.  If we ever find that we need more than 21 bits of nodeIndex,
     19        we have 2 options to deal with it:
     20
     21        1. We can just ignore the high bits.  After all, it is the nodeOp that is the
     22           most interesting piece of data we need to debug doesGC issues.
     23
     24        2. We can make DoesGCCheck use uint64_t for storage.  This encoding automatically
     25           scales to 64-bit, while still allowing the more efficient form of storing a
     26           32-bit immediate to be used for the common cases.
     27
     28        This patch also makes ENABLE_DFG_DOES_GC_VALIDATION dependent on ENABLE(DFG_JIT).
     29        DoesGC is only relevant for the DFG and FTL JITs.
     30
     31        * dfg/DFGDoesGCCheck.cpp:
     32        (JSC::DFG::DoesGCCheck::verifyCanGC):
     33        * dfg/DFGDoesGCCheck.h:
     34        (JSC::DFG::DoesGCCheck::encode):
     35        (JSC::DFG::DoesGCCheck::expectDoesGC const):
     36        (JSC::DFG::DoesGCCheck::isSpecial const):
     37        (JSC::DFG::DoesGCCheck::special):
     38        (JSC::DFG::DoesGCCheck::nodeOp):
     39        (JSC::DFG::DoesGCCheck::nodeIndex):
     40        (JSC::DFG::DoesGCCheck::expectDoesGC): Deleted.
     41        (JSC::DFG::DoesGCCheck::isSpecial): Deleted.
     42        (JSC::DFG::DoesGCCheck::specialIndex): Deleted.
     43        (JSC::DFG::DoesGCCheck::bits): Deleted.
     44        * dfg/DFGNodeType.h:
     45        * dfg/DFGOSRExit.cpp:
     46        (JSC::DFG::OSRExit::compileExit):
     47        * dfg/DFGSpeculativeJIT32_64.cpp:
     48        (JSC::DFG::SpeculativeJIT::compile):
     49        * dfg/DFGSpeculativeJIT64.cpp:
     50        (JSC::DFG::SpeculativeJIT::compile):
     51        * ftl/FTLLowerDFGToB3.cpp:
     52        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     53        * ftl/FTLOSRExitCompiler.cpp:
     54        (JSC::FTL::compileStub):
     55        * heap/Heap.h:
     56
    1572020-06-04  Tim Horton  <timothy_horton@apple.com>
    258
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGCCheck.cpp

    r262517 r262562  
    2929#include "CallFrame.h"
    3030#include "CodeBlock.h"
     31#include "DFGNodeType.h"
    3132#include "Heap.h"
    3233#include "VMInspector.h"
     
    4243void DoesGCCheck::verifyCanGC(VM& vm)
    4344{
     45    // We do this check here just so we don't have to #include DFGNodeType.h
     46    // in the header file.
     47    static_assert(numberOfNodeTypes <= (1 << nodeOpBits));
     48
    4449    if (!expectDoesGC()) {
    4550        dataLog("Error: DoesGC failed");
     
    5459                dataLog(" @ FTL osr exit");
    5560                break;
    56             case Special::ReservedUnused:
    5761            case Special::NumberOfSpecials:
    5862                RELEASE_ASSERT_NOT_REACHED();
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGCCheck.h

    r262517 r262562  
    3737struct DoesGCCheck {
    3838    enum class Special {
    39         ReservedUnused, // so that specials start with 1. isSpecial() relies on this.
    4039        Uninitialized,
    4140        DFGOSRExit,
     
    4847    { }
    4948
    50     static uint64_t encode(bool expectDoesGC, unsigned nodeIndex, unsigned nodeOp)
     49    static uint32_t encode(bool expectDoesGC, unsigned nodeIndex, unsigned nodeOp)
    5150    {
    52         uint64_t result = bits(nodeIndex) << nodeIndexShift;
    53         result |= bits(nodeOp) << nodeOpShift;
    54         result |= bits(expectDoesGC) << expectDoesGCShift;
    55         return result;
     51        // We know nodeOp always fits because of the static_assert in DFGDoesGCCheck.cpp.
     52        ASSERT((nodeIndex << nodeIndexShift) >> nodeIndexShift == nodeIndex);
     53        return nodeIndex << nodeIndexShift | nodeOp << nodeOpShift | bits(expectDoesGC);
    5654    }
    5755
    58     static uint64_t encode(bool expectDoesGC, Special special)
     56    static uint32_t encode(bool expectDoesGC, Special special)
    5957    {
    60         ASSERT(bits(special) < numberOfSpecials);
    61         uint64_t result = bits(special) << specialShift;
    62         result |= bits(expectDoesGC) << expectDoesGCShift;
    63         return result;
     58        return bits(special) << specialShift | isSpecialBit | bits(expectDoesGC);
    6459    }
    6560
     
    7469    }
    7570
    76     bool expectDoesGC() { return m_value & expectDoesGCMask; }
    77     Special special() { return static_cast<Special>(specialIndex()); }
     71    bool expectDoesGC() const { return m_value & expectDoesGCBit; }
     72    bool isSpecial() const { return m_value & isSpecialBit; }
     73
     74    Special special() { return static_cast<Special>(m_value >> specialShift); }
     75
     76    unsigned nodeOp() { return (m_value >> nodeOpShift) & nodeOpMask; }
    7877    unsigned nodeIndex() { return m_value >> nodeIndexShift; }
    79     unsigned nodeOp() { return (m_value >> nodeOpShift) & nodeOpMask; }
    80 
    81     bool isSpecial() { return specialIndex(); }
    8278
    8379    JS_EXPORT_PRIVATE void verifyCanGC(VM&);
    8480
    8581private:
    86     unsigned specialIndex() { return (m_value >> specialShift) & specialMask; }
     82    template<typename T> static uint32_t bits(T value) { return static_cast<uint32_t>(value); }
    8783
    88     template<typename T> static uint64_t bits(T value) { return static_cast<uint64_t>(value); }
     84    // The value cannot be both a Special and contain node information at the
     85    // time. Hence, the 2 can have separate encodings. The isSpecial bit
     86    // determines which encoding is in use.
    8987
    90     static constexpr uint64_t numberOfSpecials = static_cast<uint64_t>(Special::NumberOfSpecials);
     88    static constexpr unsigned expectDoesGCBit = 1 << 0;
     89    static constexpr unsigned isSpecialBit = 1 << 1;
     90    static constexpr unsigned commonBits = 2;
     91    static_assert((expectDoesGCBit | isSpecialBit) == (1 << commonBits) - 1);
    9192
    92     static constexpr unsigned expectDoesGCShift = 0;
    93     static constexpr unsigned specialShift = 1;
    94     static constexpr unsigned nodeOpShift = 16;
    95     static constexpr unsigned nodeIndexShift = 32;
     93    static constexpr unsigned specialShift = commonBits;
    9694
    97     static constexpr unsigned expectDoesGCMask = 0x1;
    98     static constexpr unsigned specialMask = 0x7fff;
    99     static constexpr unsigned nodeOpMask = 0xffff;
     95    static constexpr unsigned nodeOpBits = 9;
     96    static constexpr unsigned nodeOpMask = (1 << nodeOpBits) - 1;
     97    static constexpr unsigned nodeOpShift = commonBits;
    10098
    101     uint64_t m_value { 0 };
     99    static constexpr unsigned nodeIndexBits = 21;
     100    static constexpr unsigned nodeIndexShift = nodeOpShift + nodeOpBits;
     101    static_assert(nodeIndexShift + nodeIndexBits == 32);
     102
     103    uint32_t m_value { 0 };
    102104};
    103105
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r262252 r262562  
    11/*
    2  * Copyright (C) 2012-2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012-2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    553553};
    554554
     555#define DFG_OP_COUNT(opcode, flags) + 1
     556constexpr unsigned numberOfNodeTypes = FOR_EACH_DFG_OP(DFG_OP_COUNT);
     557#undef DFG_OP_COUNT
     558
    555559// Specifies the default flags for each node.
    556560inline NodeFlags defaultFlags(NodeType op)
  • trunk/Source/JavaScriptCore/dfg/DFGOSRExit.cpp

    r262534 r262562  
    561561        // we exit from this site, but all subsequent exits will take this compiled
    562562        // ramp without calling compileOSRExit() first.
    563         jit.store64(CCallHelpers::TrustedImm64(DoesGCCheck::encode(true, DoesGCCheck::Special::DFGOSRExit)), vm.heap.addressOfDoesGC());
     563        jit.store32(CCallHelpers::TrustedImm32(DoesGCCheck::encode(true, DoesGCCheck::Special::DFGOSRExit)), vm.heap.addressOfDoesGC());
    564564    }
    565565#endif
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r262252 r262562  
    11/*
    2  * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
    33 * Copyright (C) 2011 Intel Corporation. All rights reserved.
    44 *
     
    3434#include "DFGAbstractInterpreterInlines.h"
    3535#include "DFGCallArrayAllocatorSlowPathGenerator.h"
     36#include "DFGDoesGC.h"
    3637#include "DFGOperations.h"
    3738#include "DFGSlowPathGenerator.h"
     
    18061807{
    18071808    NodeType op = node->op();
     1809
     1810    if (validateDFGDoesGC) {
     1811        bool expectDoesGC = doesGC(m_jit.graph(), node);
     1812        m_jit.store32(TrustedImm32(DoesGCCheck::encode(expectDoesGC, node->index(), node->op())), vm().heap.addressOfDoesGC());
     1813    }
    18081814
    18091815#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r262535 r262562  
    21392139    if (validateDFGDoesGC) {
    21402140        bool expectDoesGC = doesGC(m_jit.graph(), node);
    2141         m_jit.store64(TrustedImm64(DoesGCCheck::encode(expectDoesGC, node->index(), node->op())), vm().heap.addressOfDoesGC());
     2141        m_jit.store32(TrustedImm32(DoesGCCheck::encode(expectDoesGC, node->index(), node->op())), vm().heap.addressOfDoesGC());
    21422142    }
    21432143
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r262513 r262562  
    705705        if (validateDFGDoesGC) {
    706706            bool expectDoesGC = doesGC(m_graph, m_node);
    707             m_out.store(m_out.constInt64(DoesGCCheck::encode(expectDoesGC, m_node->index(), m_node->op())), m_out.absolute(vm().heap.addressOfDoesGC()));
     707            m_out.store(m_out.constInt32(DoesGCCheck::encode(expectDoesGC, m_node->index(), m_node->op())), m_out.absolute(vm().heap.addressOfDoesGC()));
    708708        }
    709709
  • trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp

    r262513 r262562  
    216216        // we exit from this site, but all subsequent exits will take this compiled
    217217        // ramp without calling compileFTLOSRExit() first.
    218         jit.store64(CCallHelpers::TrustedImm64(DoesGCCheck::encode(true, DoesGCCheck::Special::FTLOSRExit)), vm.heap.addressOfDoesGC());
     218        jit.store32(CCallHelpers::TrustedImm32(DoesGCCheck::encode(true, DoesGCCheck::Special::FTLOSRExit)), vm.heap.addressOfDoesGC());
    219219    }
    220220
  • trunk/Source/JavaScriptCore/heap/Heap.h

    r262513 r262562  
    9999}
    100100
    101 #define ENABLE_DFG_DOES_GC_VALIDATION ASSERT_ENABLED
     101#if ENABLE(DFG_JIT) && ASSERT_ENABLED
     102#define ENABLE_DFG_DOES_GC_VALIDATION 1
     103#else
     104#define ENABLE_DFG_DOES_GC_VALIDATION 0
     105#endif
     106
    102107constexpr bool validateDFGDoesGC = ENABLE_DFG_DOES_GC_VALIDATION;
    103108
Note: See TracChangeset for help on using the changeset viewer.