Changeset 242096 in webkit


Ignore:
Timestamp:
Feb 26, 2019 11:41:21 AM (5 years ago)
Author:
mark.lam@apple.com
Message:

[Re-landing] Add some randomness into the StructureID.
https://bugs.webkit.org/show_bug.cgi?id=194989
<rdar://problem/47975563>

Reviewed by Yusuke Suzuki.

  1. On 64-bit, the StructureID will now be encoded as:

----------------------------------------------------------------
| 1 Nuke Bit | 24 StructureIDTable index bits | 7 entropy bits |
----------------------------------------------------------------

The entropy bits are chosen at random and assigned when a StructureID is
allocated.

  1. Instead of Structure pointers, the StructureIDTable will now contain encodedStructureBits, which is encoded as such:

----------------------------------------------------------------
| 7 entropy bits | 57 structure pointer bits |
----------------------------------------------------------------

The entropy bits here are the same 7 bits used in the encoding of the
StructureID for this structure entry in the StructureIDTable.

  1. Retrieval of the structure pointer given a StructureID is now computed as follows:

index = structureID >> 7; with arithmetic shift.
encodedStructureBits = structureIDTable[index];
structure = encodedStructureBits (structureID << 57);

We use an arithmetic shift for the right shift because that will preserve
the nuke bit in the high bit of the index if the StructureID was not
decontaminated before use as expected.

  1. Remove unused function loadArgumentWithSpecificClass() in SpecializedThunkJIT.
  1. Define StructureIDTable::m_size to be the number of allocated StructureIDs instead of always being the same as m_capacity.
  1. Change StructureIDTable::s_unusedID's value to 0.

Its previous value of unusedPointer i.e. 0xd1e7beef, does not make sense for
StructureID on 64-bit. Also, there was never any code that initializes unused
IDs to the s_unusedID. The only meaningful value for s_unusedID is 0, which
is the ID we'll get when the freelist is empty, prompting a resize of the
structureIDTable.

This patch appears to be perf neutral on JetStream 2 run via the cli on a
11" MacBook Air, 13" MacBook Pro, iPhone 6S, and iPhone XR.

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::loadStructure):

  • heap/SlotVisitor.cpp:

(JSC::SlotVisitor::appendJSCellOrAuxiliary):

  • jit/AssemblyHelpers.cpp:

(JSC::AssemblyHelpers::emitLoadStructure):

  • jit/AssemblyHelpers.h:
  • jit/SpecializedThunkJIT.h:

(JSC::SpecializedThunkJIT::loadArgumentWithSpecificClass): Deleted.

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/StructureIDTable.cpp:

(JSC::StructureIDTable::StructureIDTable):
(JSC::StructureIDTable::makeFreeListFromRange):
(JSC::StructureIDTable::resize):
(JSC::StructureIDTable::allocateID):
(JSC::StructureIDTable::deallocateID):

  • runtime/StructureIDTable.h:

(JSC::StructureIDTable::decode):
(JSC::StructureIDTable::encode):
(JSC::StructureIDTable::get):
(JSC::StructureIDTable::isValid):

Location:
trunk/Source/JavaScriptCore
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r242087 r242096  
     12019-02-26  Mark Lam  <mark.lam@apple.com>
     2
     3        [Re-landing] Add some randomness into the StructureID.
     4        https://bugs.webkit.org/show_bug.cgi?id=194989
     5        <rdar://problem/47975563>
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        1. On 64-bit, the StructureID will now be encoded as:
     10
     11            ----------------------------------------------------------------
     12            | 1 Nuke Bit | 24 StructureIDTable index bits | 7 entropy bits |
     13            ----------------------------------------------------------------
     14
     15           The entropy bits are chosen at random and assigned when a StructureID is
     16           allocated.
     17
     18        2. Instead of Structure pointers, the StructureIDTable will now contain
     19           encodedStructureBits, which is encoded as such:
     20
     21            ----------------------------------------------------------------
     22            | 7 entropy bits |                   57 structure pointer bits |
     23            ----------------------------------------------------------------
     24
     25           The entropy bits here are the same 7 bits used in the encoding of the
     26           StructureID for this structure entry in the StructureIDTable.
     27
     28        3. Retrieval of the structure pointer given a StructureID is now computed as
     29           follows:
     30
     31                index = structureID >> 7; // with arithmetic shift.
     32                encodedStructureBits = structureIDTable[index];
     33                structure = encodedStructureBits ^ (structureID << 57);
     34
     35            We use an arithmetic shift for the right shift because that will preserve
     36            the nuke bit in the high bit of the index if the StructureID was not
     37            decontaminated before use as expected.
     38
     39        4. Remove unused function loadArgumentWithSpecificClass() in SpecializedThunkJIT.
     40
     41        5. Define StructureIDTable::m_size to be the number of allocated StructureIDs
     42           instead of always being the same as m_capacity.
     43
     44        6. Change StructureIDTable::s_unusedID's value to 0.
     45
     46           Its previous value of unusedPointer i.e. 0xd1e7beef, does not make sense for
     47           StructureID on 64-bit.  Also, there was never any code that initializes unused
     48           IDs to the s_unusedID.  The only meaningful value for s_unusedID is 0, which
     49           is the ID we'll get when the freelist is empty, prompting a resize of the
     50           structureIDTable.
     51
     52        This patch appears to be perf neutral on JetStream 2 run via the cli on a
     53        11" MacBook Air, 13" MacBook Pro, iPhone 6S, and iPhone XR.
     54
     55        * ftl/FTLLowerDFGToB3.cpp:
     56        (JSC::FTL::DFG::LowerDFGToB3::loadStructure):
     57        * heap/SlotVisitor.cpp:
     58        (JSC::SlotVisitor::appendJSCellOrAuxiliary):
     59        * jit/AssemblyHelpers.cpp:
     60        (JSC::AssemblyHelpers::emitLoadStructure):
     61        * jit/AssemblyHelpers.h:
     62        * jit/SpecializedThunkJIT.h:
     63        (JSC::SpecializedThunkJIT::loadArgumentWithSpecificClass): Deleted.
     64        * llint/LowLevelInterpreter.asm:
     65        * llint/LowLevelInterpreter64.asm:
     66        * runtime/StructureIDTable.cpp:
     67        (JSC::StructureIDTable::StructureIDTable):
     68        (JSC::StructureIDTable::makeFreeListFromRange):
     69        (JSC::StructureIDTable::resize):
     70        (JSC::StructureIDTable::allocateID):
     71        (JSC::StructureIDTable::deallocateID):
     72        * runtime/StructureIDTable.h:
     73        (JSC::StructureIDTable::decode):
     74        (JSC::StructureIDTable::encode):
     75        (JSC::StructureIDTable::get):
     76        (JSC::StructureIDTable::isValid):
     77
    1782019-02-26  Ryan Haddad  <ryanhaddad@apple.com>
    279
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r242087 r242096  
    1694516945    LValue loadStructure(LValue value)
    1694616946    {
    16947         LValue tableIndex = m_out.load32(value, m_heaps.JSCell_structureID);
    16948         LValue tableBase = m_out.loadPtr(
    16949             m_out.absolute(vm().heap.structureIDTable().base()));
    16950         TypedPointer address = m_out.baseIndex(
    16951             m_heaps.structureTable, tableBase, m_out.zeroExtPtr(tableIndex));
    16952         return m_out.loadPtr(address);
     16947        LValue structureID = m_out.load32(value, m_heaps.JSCell_structureID);
     16948        LValue tableBase = m_out.loadPtr(m_out.absolute(vm().heap.structureIDTable().base()));
     16949        LValue tableIndex = m_out.aShr(structureID, m_out.constInt32(StructureIDTable::s_numberOfEntropyBits));
     16950        LValue entropyBits = m_out.shl(m_out.zeroExtPtr(structureID), m_out.constInt32(StructureIDTable::s_entropyBitsShiftForStructurePointer));
     16951        TypedPointer address = m_out.baseIndex(m_heaps.structureTable, tableBase, m_out.zeroExtPtr(tableIndex));
     16952        LValue encodedStructureBits = m_out.loadPtr(address);
     16953        return m_out.bitXor(encodedStructureBits, entropyBits);
    1695316954    }
    1695416955
  • trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp

    r242087 r242096  
    11/*
    2  * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    199199#if USE(JSVALUE64)
    200200        // This detects the worst of the badness.
    201         if (structureID >= heap()->structureIDTable().size())
    202             die("GC scan found corrupt object: structureID is out of bounds!\n");
     201        if (!heap()->structureIDTable().isValid(structureID))
     202            die("GC scan found corrupt object: structureID is invalid!\n");
    203203#endif
    204204    };
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp

    r242087 r242096  
    11/*
    2  * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    370370{
    371371#if USE(JSVALUE64)
     372#if CPU(ARM64)
     373    RegisterID scratch2 = dataTempRegister;
     374#elif CPU(X86_64)
     375    RegisterID scratch2 = scratchRegister();
     376#else
     377#error "Unsupported cpu"
     378#endif
     379
    372380    ASSERT(dest != scratch);
    373     load32(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest);
     381    ASSERT(dest != scratch2);
     382    ASSERT(scratch != scratch2);
     383
     384    load32(MacroAssembler::Address(source, JSCell::structureIDOffset()), scratch2);
    374385    loadPtr(vm.heap.structureIDTable().base(), scratch);
     386    rshift32(scratch2, TrustedImm32(StructureIDTable::s_numberOfEntropyBits), dest);
    375387    loadPtr(MacroAssembler::BaseIndex(scratch, dest, MacroAssembler::TimesEight), dest);
    376 #else
     388    lshiftPtr(TrustedImm32(StructureIDTable::s_entropyBitsShiftForStructurePointer), scratch2);
     389    xorPtr(scratch2, dest);
     390#else // not USE(JSVALUE64)
    377391    UNUSED_PARAM(scratch);
     392    UNUSED_PARAM(scratch2);
    378393    UNUSED_PARAM(vm);
    379394    loadPtr(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest);
    380 #endif
     395#endif // not USE(JSVALUE64)
    381396}
    382397
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h

    r242087 r242096  
    11/*
    2  * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    17831783    }
    17841784
    1785     JumpList branchIfValue(VM&, JSValueRegs value, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg, FPRReg, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject*, bool negateResult);
     1785    JumpList branchIfValue(VM&, JSValueRegs, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg, FPRReg, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject*, bool negateResult);
    17861786    JumpList branchIfTruthy(VM& vm, JSValueRegs value, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg scratchFPR0, FPRReg scratchFPR1, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject* globalObject)
    17871787    {
     
    17921792        return branchIfValue(vm, value, scratch, scratchIfShouldCheckMasqueradesAsUndefined, scratchFPR0, scratchFPR1, shouldCheckMasqueradesAsUndefined, globalObject, true);
    17931793    }
    1794     void emitConvertValueToBoolean(VM&, JSValueRegs value, GPRReg result, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg, FPRReg, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject*, bool negateResult = false);
     1794    void emitConvertValueToBoolean(VM&, JSValueRegs, GPRReg result, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg, FPRReg, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject*, bool negateResult = false);
    17951795   
    17961796    template<typename ClassType>
  • trunk/Source/JavaScriptCore/jit/SpecializedThunkJIT.h

    r242087 r242096  
    11/*
    2  * Copyright (C) 2010-2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2010-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    7272        }
    7373       
    74         void loadArgumentWithSpecificClass(const ClassInfo* classInfo, int argument, RegisterID dst, RegisterID scratch)
    75         {
    76             loadCellArgument(argument, dst);
    77             emitLoadStructure(*vm(), dst, scratch, dst);
    78             appendFailure(branchPtr(NotEqual, Address(scratch, Structure::classInfoOffset()), TrustedImmPtr(PoisonedClassInfoPtr(classInfo).bits())));
    79             // We have to reload the argument since emitLoadStructure clobbered it.
    80             loadCellArgument(argument, dst);
    81         }
    82        
    8374        void loadInt32Argument(int argument, RegisterID dst, Jump& failTarget)
    8475        {
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r242087 r242096  
    203203    const DeletedValueTag = constexpr JSValue::DeletedValueTag
    204204    const LowestTag = constexpr JSValue::LowestTag
     205end
     206
     207if JSVALUE64
     208    const NumberOfStructureIDEntropyBits = constexpr StructureIDTable::s_numberOfEntropyBits
     209    const StructureEntropyBitsShift = constexpr StructureIDTable::s_entropyBitsShiftForStructurePointer
    205210end
    206211
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r242087 r242096  
    531531end
    532532
    533 macro structureIDToStructureWithScratch(structureIDThenStructure, scratch)
     533macro structureIDToStructureWithScratch(structureIDThenStructure, scratch, scratch2)
    534534    loadp CodeBlock[cfr], scratch
     535    move structureIDThenStructure, scratch2
    535536    loadp CodeBlock::m_vm[scratch], scratch
     537    rshifti NumberOfStructureIDEntropyBits, scratch2
    536538    loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[scratch], scratch
    537     loadp [scratch, structureIDThenStructure, PtrSize], structureIDThenStructure
    538 end
    539 
    540 macro loadStructureWithScratch(cell, structure, scratch)
     539    loadp [scratch, scratch2, PtrSize], scratch2
     540    lshiftp StructureEntropyBitsShift, structureIDThenStructure
     541    xorp scratch2, structureIDThenStructure
     542end
     543
     544macro loadStructureWithScratch(cell, structure, scratch, scratch2)
    541545    loadi JSCell::m_structureID[cell], structure
    542     structureIDToStructureWithScratch(structure, scratch)
     546    structureIDToStructureWithScratch(structure, scratch, scratch2)
    543547end
    544548
     
    695699    btqnz t0, tagMask, .opToThisSlow
    696700    bbneq JSCell::m_type[t0], FinalObjectType, .opToThisSlow
    697     loadStructureWithScratch(t0, t1, t2)
     701    loadStructureWithScratch(t0, t1, t2, t3)
    698702    metadata(t2, t3)
    699703    loadp OpToThis::Metadata::m_cachedStructure[t2], t2
     
    765769        jmp .done
    766770    .masqueradesAsUndefined:
    767         loadStructureWithScratch(t0, t2, t1)
     771        loadStructureWithScratch(t0, t2, t1, t3)
    768772        loadp CodeBlock[cfr], t0
    769773        loadp CodeBlock::m_globalObject[t0], t0
     
    11831187    return(t1)
    11841188.masqueradesAsUndefined:
    1185     loadStructureWithScratch(t0, t3, t1)
     1189    loadStructureWithScratch(t0, t3, t1, t2)
    11861190    loadp CodeBlock[cfr], t1
    11871191    loadp CodeBlock::m_globalObject[t1], t1
     
    13541358    btpz t3, .opPutByIdTransitionDirect
    13551359
    1356     structureIDToStructureWithScratch(t2, t1)
     1360    structureIDToStructureWithScratch(t2, t1, t3)
    13571361
    13581362    # reload the StructureChain since we used t3 as a scratch above
     
    16921696        loadq [cfr, t0, 8], t0
    16931697        btqnz t0, tagMask, .immediate
    1694         loadStructureWithScratch(t0, t2, t1)
     1698        loadStructureWithScratch(t0, t2, t1, t3)
    16951699        cellHandler(t2, JSCell::m_flags[t0], .target)
    16961700        dispatch()
     
    22152219    get(m_scope, t0)
    22162220    loadq [cfr, t0, 8], t0
    2217     loadStructureWithScratch(t0, t2, t1)
     2221    loadStructureWithScratch(t0, t2, t1, t3)
    22182222    loadp %opcodeStruct%::Metadata::m_structure[t5], t1
    22192223    bpneq t2, t1, slowPath
  • trunk/Source/JavaScriptCore/runtime/StructureIDTable.cpp

    r242087 r242096  
    3636StructureIDTable::StructureIDTable()
    3737    : m_table(makeUniqueArray<StructureOrOffset>(s_initialSize))
     38    , m_size(1)
    3839    , m_capacity(s_initialSize)
    3940{
    4041    // We pre-allocate the first offset so that the null Structure
    4142    // can still be represented as the StructureID '0'.
    42     table()[0].structure = nullptr;
     43    table()[0].encodedStructureBits = 0;
    4344
    4445    makeFreeListFromRange(1, m_capacity - 1);
    45     ASSERT(m_size == m_capacity);
    4646}
    4747
     
    9696    m_firstFreeOffset = head;
    9797    m_lastFreeOffset = tail;
    98     m_size = m_capacity;
    9998}
    10099
    101100void StructureIDTable::resize(size_t newCapacity)
    102101{
     102    if (newCapacity > s_maximumNumberOfStructures)
     103        newCapacity = s_maximumNumberOfStructures;
     104
    103105    // Create the new table.
    104106    auto newTable = makeUniqueArray<StructureOrOffset>(newCapacity);
     
    129131StructureID StructureIDTable::allocateID(Structure* structure)
    130132{
    131     if (!m_firstFreeOffset) {
    132         RELEASE_ASSERT(m_capacity <= UINT_MAX);
    133         if (m_size == m_capacity)
    134             resize(m_capacity * 2);
     133    if (UNLIKELY(!m_firstFreeOffset)) {
     134        RELEASE_ASSERT(m_capacity <= s_maximumNumberOfStructures);
    135135        ASSERT(m_size == m_capacity);
     136        resize(m_capacity * 2);
     137        ASSERT(m_size < m_capacity);
    136138        ASSERT(m_firstFreeOffset);
    137139    }
     
    139141    ASSERT(m_firstFreeOffset != s_unusedID);
    140142
    141     StructureID result = m_firstFreeOffset;
     143    // entropyBits must not be zero. This ensures that if a corrupted
     144    // structureID is encountered (with incorrect entropyBits), the decoded
     145    // structure pointer for that ID will be always be a bad pointer with
     146    // high bits set.
     147    constexpr uint32_t entropyBitsMask = (1 << s_numberOfEntropyBits) - 1;
     148    uint32_t entropyBits = m_weakRandom.getUint32() & entropyBitsMask;
     149    if (UNLIKELY(!entropyBits)) {
     150        constexpr uint32_t numberOfValuesToPickFrom = entropyBitsMask;
     151        entropyBits = (m_weakRandom.getUint32() % numberOfValuesToPickFrom) + 1;
     152    }
     153
     154    uint32_t structureIndex = m_firstFreeOffset;
    142155    m_firstFreeOffset = table()[m_firstFreeOffset].offset;
    143156    if (!m_firstFreeOffset)
    144157        m_lastFreeOffset = 0;
    145158
    146     table()[result].structure = structure;
     159    StructureID result = (structureIndex << s_numberOfEntropyBits) | entropyBits;
     160    table()[structureIndex].encodedStructureBits = encode(structure, result);
     161    m_size++;
    147162    ASSERT(!isNuked(result));
    148163    return result;
     
    152167{
    153168    ASSERT(structureID != s_unusedID);
    154     RELEASE_ASSERT(table()[structureID].structure == structure);
    155 
     169    uint32_t structureIndex = structureID >> s_numberOfEntropyBits;
     170    ASSERT(structureIndex && structureIndex < s_maximumNumberOfStructures);
     171    RELEASE_ASSERT(table()[structureIndex].encodedStructureBits == encode(structure, structureID));
     172    m_size--;
    156173    if (!m_firstFreeOffset) {
    157         table()[structureID].offset = 0;
    158         m_firstFreeOffset = structureID;
    159         m_lastFreeOffset = structureID;
     174        table()[structureIndex].offset = 0;
     175        m_firstFreeOffset = structureIndex;
     176        m_lastFreeOffset = structureIndex;
    160177        return;
    161178    }
     
    163180    bool insertAtHead = m_weakRandom.getUint32() & 1;
    164181    if (insertAtHead) {
    165         table()[structureID].offset = m_firstFreeOffset;
    166         m_firstFreeOffset = structureID;
     182        table()[structureIndex].offset = m_firstFreeOffset;
     183        m_firstFreeOffset = structureIndex;
    167184    } else {
    168         table()[structureID].offset = 0;
    169         table()[m_lastFreeOffset].offset = structureID;
    170         m_lastFreeOffset = structureID;
     185        table()[structureIndex].offset = 0;
     186        table()[m_lastFreeOffset].offset = structureIndex;
     187        m_lastFreeOffset = structureIndex;
    171188    }
    172189}
  • trunk/Source/JavaScriptCore/runtime/StructureIDTable.h

    r242087 r242096  
    8383#if USE(JSVALUE64)
    8484
     85using EncodedStructureBits = uintptr_t;
     86
    8587class StructureIDTable {
    8688    friend class LLIntOffsetsExtractor;
     
    9092    void** base() { return reinterpret_cast<void**>(&m_table); }
    9193
     94    bool isValid(StructureID);
    9295    Structure* get(StructureID);
    9396    void deallocateID(Structure*, StructureID);
     
    105108        WTF_MAKE_FAST_ALLOCATED;
    106109    public:
    107         Structure* structure;
     110        EncodedStructureBits encodedStructureBits;
    108111        StructureID offset;
    109112    };
    110113
    111114    StructureOrOffset* table() const { return m_table.get(); }
    112    
     115    static Structure* decode(EncodedStructureBits, StructureID);
     116    static EncodedStructureBits encode(Structure*, StructureID);
     117
    113118    static constexpr size_t s_initialSize = 512;
    114119
     
    124129    WeakRandom m_weakRandom;
    125130
    126     static const StructureID s_unusedID = unusedPointer;
     131    static constexpr StructureID s_unusedID = 0;
     132
     133public:
     134    static constexpr uint32_t s_numberOfNukeBits = 1;
     135    static constexpr uint32_t s_numberOfEntropyBits = 7;
     136    static constexpr uint32_t s_entropyBitsShiftForStructurePointer = (sizeof(intptr_t) * 8) - s_numberOfEntropyBits;
     137
     138    static constexpr uint32_t s_maximumNumberOfStructures = 1 << (32 - s_numberOfEntropyBits - s_numberOfNukeBits);
    127139};
     140
     141ALWAYS_INLINE Structure* StructureIDTable::decode(EncodedStructureBits bits, StructureID structureID)
     142{
     143    return reinterpret_cast<Structure*>(bits ^ (static_cast<uintptr_t>(structureID) << s_entropyBitsShiftForStructurePointer));
     144}
     145
     146ALWAYS_INLINE EncodedStructureBits StructureIDTable::encode(Structure* structure, StructureID structureID)
     147{
     148    return reinterpret_cast<EncodedStructureBits>(structure) ^ (static_cast<EncodedStructureBits>(structureID) << s_entropyBitsShiftForStructurePointer);
     149}
    128150
    129151inline Structure* StructureIDTable::get(StructureID structureID)
     
    131153    ASSERT_WITH_SECURITY_IMPLICATION(structureID);
    132154    ASSERT_WITH_SECURITY_IMPLICATION(!isNuked(structureID));
    133     ASSERT_WITH_SECURITY_IMPLICATION(structureID < m_capacity);
    134     return table()[structureID].structure;
     155    uint32_t structureIndex = structureID >> s_numberOfEntropyBits;
     156    ASSERT_WITH_SECURITY_IMPLICATION(structureIndex < m_capacity);
     157    return decode(table()[structureIndex].encodedStructureBits, structureID);
     158}
     159
     160inline bool StructureIDTable::isValid(StructureID structureID)
     161{
     162    if (!structureID)
     163        return false;
     164    uint32_t structureIndex = structureID >> s_numberOfEntropyBits;
     165    if (structureIndex >= m_capacity)
     166        return false;
     167#if CPU(ADDRESS64)
     168    Structure* structure = decode(table()[structureIndex].encodedStructureBits, structureID);
     169    if (reinterpret_cast<uintptr_t>(structure) >> s_entropyBitsShiftForStructurePointer)
     170        return false;
     171#endif
     172    return true;
    135173}
    136174
Note: See TracChangeset for help on using the changeset viewer.