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

Changeset 246423 in webkit


Ignore:
Timestamp:
Jun 13, 2019, 7:59:16 PM (7 years ago)
Author:
Kocsen Chung
Message:

Apply patch. rdar://problem/51656841

Location:
branches/safari-607-branch/Source/JavaScriptCore
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • branches/safari-607-branch/Source/JavaScriptCore/ChangeLog

    r246420 r246423  
     12019-06-13  Kocsen Chung  <kocsen_chung@apple.com>
     2
     3        Apply patch. rdar://problem/51656841
     4
     5    2019-06-13  Mark Lam  <mark.lam@apple.com>
     6
     7            Misc cleanup in StructureIDTable after r242096.
     8            https://bugs.webkit.org/show_bug.cgi?id=195063
     9
     10            Reviewed by Saam Barati.
     11
     12            * runtime/StructureIDTable.cpp:
     13            (JSC::StructureIDTable::allocateID):
     14            - RELEASE_ASSERT that the StructureID allocation will succeed.
     15
     16            * runtime/StructureIDTable.h:
     17            (JSC::StructureIDTable::decode):
     18            (JSC::StructureIDTable::encode):
     19            - Add back a comment that Yusuke requested but was lost when the patch was rolled
     20              out and relanded.
     21            - Applied bitwise_casts that Saam requested.
     22
     232019-02-26  Mark Lam  <mark.lam@apple.com>
     24
     25        [Re-landing] Add some randomness into the StructureID.
     26        https://bugs.webkit.org/show_bug.cgi?id=194989
     27        <rdar://problem/47975563>
     28
     29        Reviewed by Yusuke Suzuki.
     30
     31        1. On 64-bit, the StructureID will now be encoded as:
     32
     33            ----------------------------------------------------------------
     34            | 1 Nuke Bit | 24 StructureIDTable index bits | 7 entropy bits |
     35            ----------------------------------------------------------------
     36
     37           The entropy bits are chosen at random and assigned when a StructureID is
     38           allocated.
     39
     40        2. Instead of Structure pointers, the StructureIDTable will now contain
     41           encodedStructureBits, which is encoded as such:
     42
     43            ----------------------------------------------------------------
     44            | 7 entropy bits |                   57 structure pointer bits |
     45            ----------------------------------------------------------------
     46
     47           The entropy bits here are the same 7 bits used in the encoding of the
     48           StructureID for this structure entry in the StructureIDTable.
     49
     50        3. Retrieval of the structure pointer given a StructureID is now computed as
     51           follows:
     52
     53                index = structureID >> 7; // with arithmetic shift.
     54                encodedStructureBits = structureIDTable[index];
     55                structure = encodedStructureBits ^ (structureID << 57);
     56
     57            We use an arithmetic shift for the right shift because that will preserve
     58            the nuke bit in the high bit of the index if the StructureID was not
     59            decontaminated before use as expected.
     60
     61        4. Remove unused function loadArgumentWithSpecificClass() in SpecializedThunkJIT.
     62
     63        5. Define StructureIDTable::m_size to be the number of allocated StructureIDs
     64           instead of always being the same as m_capacity.
     65
     66        6. Change StructureIDTable::s_unusedID's value to 0.
     67
     68           Its previous value of unusedPointer i.e. 0xd1e7beef, does not make sense for
     69           StructureID on 64-bit.  Also, there was never any code that initializes unused
     70           IDs to the s_unusedID.  The only meaningful value for s_unusedID is 0, which
     71           is the ID we'll get when the freelist is empty, prompting a resize of the
     72           structureIDTable.
     73
     74        This patch appears to be perf neutral on JetStream 2 run via the cli on a
     75        11" MacBook Air, 13" MacBook Pro, iPhone 6S, and iPhone XR.
     76
     77        * ftl/FTLLowerDFGToB3.cpp:
     78        (JSC::FTL::DFG::LowerDFGToB3::loadStructure):
     79        * heap/SlotVisitor.cpp:
     80        (JSC::SlotVisitor::appendJSCellOrAuxiliary):
     81        * jit/AssemblyHelpers.cpp:
     82        (JSC::AssemblyHelpers::emitLoadStructure):
     83        * jit/AssemblyHelpers.h:
     84        * jit/SpecializedThunkJIT.h:
     85        (JSC::SpecializedThunkJIT::loadArgumentWithSpecificClass): Deleted.
     86        * llint/LowLevelInterpreter.asm:
     87        * llint/LowLevelInterpreter64.asm:
     88        * runtime/StructureIDTable.cpp:
     89        (JSC::StructureIDTable::StructureIDTable):
     90        (JSC::StructureIDTable::makeFreeListFromRange):
     91        (JSC::StructureIDTable::resize):
     92        (JSC::StructureIDTable::allocateID):
     93        (JSC::StructureIDTable::deallocateID):
     94        * runtime/StructureIDTable.h:
     95        (JSC::StructureIDTable::decode):
     96        (JSC::StructureIDTable::encode):
     97        (JSC::StructureIDTable::get):
     98        (JSC::StructureIDTable::isValid):
     99
     1002019-02-13  Mark Lam  <mark.lam@apple.com>
     101
     102        Create a randomized free list for new StructureIDs on StructureIDTable resize.
     103        https://bugs.webkit.org/show_bug.cgi?id=194566
     104        <rdar://problem/47975502>
     105
     106        Reviewed by Michael Saboff.
     107
     108        Also isolate 32-bit implementation of StructureIDTable out more so the 64-bit
     109        implementation is a little easier to read.
     110
     111        This patch appears to be perf neutral on JetStream2 (as run from the command line).
     112
     113        * runtime/StructureIDTable.cpp:
     114        (JSC::StructureIDTable::StructureIDTable):
     115        (JSC::StructureIDTable::makeFreeListFromRange):
     116        (JSC::StructureIDTable::resize):
     117        (JSC::StructureIDTable::allocateID):
     118        (JSC::StructureIDTable::deallocateID):
     119        * runtime/StructureIDTable.h:
     120        (JSC::StructureIDTable::get):
     121        (JSC::StructureIDTable::deallocateID):
     122        (JSC::StructureIDTable::allocateID):
     123        (JSC::StructureIDTable::flushOldTables):
     124
     1252019-02-11  Mark Lam  <mark.lam@apple.com>
     126
     127        Randomize insertion of deallocated StructureIDs into the StructureIDTable's free list.
     128        https://bugs.webkit.org/show_bug.cgi?id=194512
     129        <rdar://problem/47975465>
     130
     131        Reviewed by Yusuke Suzuki.
     132
     133        * runtime/StructureIDTable.cpp:
     134        (JSC::StructureIDTable::StructureIDTable):
     135        (JSC::StructureIDTable::allocateID):
     136        (JSC::StructureIDTable::deallocateID):
     137        * runtime/StructureIDTable.h:
     138
    11392019-06-13  Kocsen Chung  <kocsen_chung@apple.com>
    2140
  • branches/safari-607-branch/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r246379 r246423  
    1692916929    LValue loadStructure(LValue value)
    1693016930    {
    16931         LValue tableIndex = m_out.load32(value, m_heaps.JSCell_structureID);
    16932         LValue tableBase = m_out.loadPtr(
    16933             m_out.absolute(vm().heap.structureIDTable().base()));
    16934         TypedPointer address = m_out.baseIndex(
    16935             m_heaps.structureTable, tableBase, m_out.zeroExtPtr(tableIndex));
    16936         return m_out.loadPtr(address);
     16931        LValue structureID = m_out.load32(value, m_heaps.JSCell_structureID);
     16932        LValue tableBase = m_out.loadPtr(m_out.absolute(vm().heap.structureIDTable().base()));
     16933        LValue tableIndex = m_out.aShr(structureID, m_out.constInt32(StructureIDTable::s_numberOfEntropyBits));
     16934        LValue entropyBits = m_out.shl(m_out.zeroExtPtr(structureID), m_out.constInt32(StructureIDTable::s_entropyBitsShiftForStructurePointer));
     16935        TypedPointer address = m_out.baseIndex(m_heaps.structureTable, tableBase, m_out.zeroExtPtr(tableIndex));
     16936        LValue encodedStructureBits = m_out.loadPtr(address);
     16937        return m_out.bitXor(encodedStructureBits, entropyBits);
    1693716938    }
    1693816939
  • branches/safari-607-branch/Source/JavaScriptCore/heap/SlotVisitor.cpp

    r240564 r246423  
    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    };
  • branches/safari-607-branch/Source/JavaScriptCore/jit/AssemblyHelpers.cpp

    r240375 r246423  
    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
  • branches/safari-607-branch/Source/JavaScriptCore/jit/AssemblyHelpers.h

    r240375 r246423  
    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
     
    17821782    }
    17831783
    1784     JumpList branchIfValue(VM&, JSValueRegs value, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg, FPRReg, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject*, bool negateResult);
     1784    JumpList branchIfValue(VM&, JSValueRegs, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg, FPRReg, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject*, bool negateResult);
    17851785    JumpList branchIfTruthy(VM& vm, JSValueRegs value, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg scratchFPR0, FPRReg scratchFPR1, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject* globalObject)
    17861786    {
     
    17911791        return branchIfValue(vm, value, scratch, scratchIfShouldCheckMasqueradesAsUndefined, scratchFPR0, scratchFPR1, shouldCheckMasqueradesAsUndefined, globalObject, true);
    17921792    }
    1793     void emitConvertValueToBoolean(VM&, JSValueRegs value, GPRReg result, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg, FPRReg, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject*, bool negateResult = false);
     1793    void emitConvertValueToBoolean(VM&, JSValueRegs, GPRReg result, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg, FPRReg, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject*, bool negateResult = false);
    17941794   
    17951795    template<typename ClassType>
  • branches/safari-607-branch/Source/JavaScriptCore/jit/SpecializedThunkJIT.h

    r232105 r246423  
    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        {
  • branches/safari-607-branch/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r240399 r246423  
    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
  • branches/safari-607-branch/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r240501 r246423  
    536536    loadp CodeBlock::m_poisonedVM[scratch], scratch
    537537    unpoison(_g_CodeBlockPoison, scratch, scratch2)
     538    move structureIDThenStructure, scratch2
     539    rshifti NumberOfStructureIDEntropyBits, scratch2
    538540    loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[scratch], scratch
    539     loadp [scratch, structureIDThenStructure, PtrSize], structureIDThenStructure
     541    loadp [scratch, scratch2, PtrSize], scratch2
     542    lshiftp StructureEntropyBitsShift, structureIDThenStructure
     543    xorp scratch2, structureIDThenStructure
    540544end
    541545
     
    11761180    return(t1)
    11771181.masqueradesAsUndefined:
    1178     loadStructureWithScratch(t0, t3, t1, t5)
     1182    loadStructureWithScratch(t0, t3, t1, t2)
    11791183    loadp CodeBlock[cfr], t1
    11801184    loadp CodeBlock::m_globalObject[t1], t1
  • branches/safari-607-branch/Source/JavaScriptCore/runtime/StructureIDTable.cpp

    r229309 r246423  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3232namespace JSC {
    3333
     34#if USE(JSVALUE64)
     35
    3436StructureIDTable::StructureIDTable()
    35     : m_firstFreeOffset(0)
    36     , m_table(makeUniqueArray<StructureOrOffset>(s_initialSize))
    37     , m_size(0)
     37    : 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     allocateID(0);
     43    table()[0].encodedStructureBits = 0;
     44
     45    makeFreeListFromRange(1, m_capacity - 1);
     46}
     47
     48void StructureIDTable::makeFreeListFromRange(uint32_t first, uint32_t last)
     49{
     50    ASSERT(!m_firstFreeOffset);
     51    ASSERT(!m_lastFreeOffset);
     52
     53    // Put all the new IDs on the free list sequentially.
     54    uint32_t head = first;
     55    uint32_t tail = last;
     56    for (uint32_t i = first; i < last; ++i)
     57        table()[i].offset = i + 1;
     58    table()[last].offset = 0;
     59
     60    // Randomize the free list.
     61    uint32_t size = last - first + 1;
     62    uint32_t maxIterations = (size * 2) / 3;
     63    for (uint32_t count = 0; count < maxIterations; ++count) {
     64        // Move a random pick either to the head or the tail of the free list.
     65        uint32_t random = m_weakRandom.getUint32();
     66        uint32_t nodeBefore = first + (random % size);
     67        uint32_t pick = table()[nodeBefore].offset;
     68        if (pick) {
     69            uint32_t nodeAfter = table()[pick].offset;
     70            table()[nodeBefore].offset = nodeAfter;
     71            if ((random & 1) || !nodeAfter) {
     72                // Move to the head.
     73                table()[pick].offset = head;
     74                head = pick;
     75                if (!nodeAfter)
     76                    tail = nodeBefore;
     77            } else {
     78                // Move to the tail.
     79                table()[pick].offset = 0;
     80                table()[tail].offset = pick;
     81                tail = pick;
     82            }
     83        }
     84    }
     85
     86    // Cut list in half and swap halves.
     87    uint32_t cut = first + (m_weakRandom.getUint32() % size);
     88    uint32_t afterCut = table()[cut].offset;
     89    if (afterCut) {
     90        table()[tail].offset = head;
     91        tail = cut;
     92        head = afterCut;
     93        table()[cut].offset = 0;
     94    }
     95
     96    m_firstFreeOffset = head;
     97    m_lastFreeOffset = tail;
    4398}
    4499
    45100void StructureIDTable::resize(size_t newCapacity)
    46101{
     102    if (newCapacity > s_maximumNumberOfStructures)
     103        newCapacity = s_maximumNumberOfStructures;
     104
    47105    // Create the new table.
    48106    auto newTable = makeUniqueArray<StructureOrOffset>(newCapacity);
     
    62120    // Update the capacity.
    63121    m_capacity = newCapacity;
     122
     123    makeFreeListFromRange(m_size, m_capacity - 1);
    64124}
    65125
     
    71131StructureID StructureIDTable::allocateID(Structure* structure)
    72132{
    73 #if USE(JSVALUE64)
    74     if (!m_firstFreeOffset) {
    75         RELEASE_ASSERT(m_capacity <= UINT_MAX);
    76         if (m_size == m_capacity)
    77             resize(m_capacity * 2);
     133    if (UNLIKELY(!m_firstFreeOffset)) {
     134        RELEASE_ASSERT(m_capacity <= s_maximumNumberOfStructures);
     135        ASSERT(m_size == m_capacity);
     136        resize(m_capacity * 2);
    78137        ASSERT(m_size < m_capacity);
    79 
    80         StructureOrOffset newEntry;
    81         newEntry.structure = structure;
    82 
    83         if (m_size == s_unusedID) {
    84             m_size++;
    85             return allocateID(structure);
    86         }
    87 
    88         StructureID result = m_size;
    89         table()[result] = newEntry;
    90         m_size++;
    91         ASSERT(!isNuked(result));
    92         return result;
     138        RELEASE_ASSERT(m_firstFreeOffset);
    93139    }
    94140
    95     ASSERT(m_firstFreeOffset != s_unusedID);
     141    // entropyBits must not be zero. This ensures that if a corrupted
     142    // structureID is encountered (with incorrect entropyBits), the decoded
     143    // structure pointer for that ID will be always be a bad pointer with
     144    // high bits set.
     145    constexpr uint32_t entropyBitsMask = (1 << s_numberOfEntropyBits) - 1;
     146    uint32_t entropyBits = m_weakRandom.getUint32() & entropyBitsMask;
     147    if (UNLIKELY(!entropyBits)) {
     148        constexpr uint32_t numberOfValuesToPickFrom = entropyBitsMask;
     149        entropyBits = (m_weakRandom.getUint32() % numberOfValuesToPickFrom) + 1;
     150    }
    96151
    97     StructureID result = m_firstFreeOffset;
     152    uint32_t structureIndex = m_firstFreeOffset;
    98153    m_firstFreeOffset = table()[m_firstFreeOffset].offset;
    99     table()[result].structure = structure;
     154    if (!m_firstFreeOffset)
     155        m_lastFreeOffset = 0;
     156
     157    StructureID result = (structureIndex << s_numberOfEntropyBits) | entropyBits;
     158    table()[structureIndex].encodedStructureBits = encode(structure, result);
     159    m_size++;
    100160    ASSERT(!isNuked(result));
    101161    return result;
    102 #else
    103     ASSERT(!isNuked(structure));
    104     return structure;
    105 #endif
    106162}
    107163
    108164void StructureIDTable::deallocateID(Structure* structure, StructureID structureID)
    109165{
    110 #if USE(JSVALUE64)
    111166    ASSERT(structureID != s_unusedID);
    112     RELEASE_ASSERT(table()[structureID].structure == structure);
    113     table()[structureID].offset = m_firstFreeOffset;
    114     m_firstFreeOffset = structureID;
    115 #else
    116     UNUSED_PARAM(structure);
    117     UNUSED_PARAM(structureID);
    118 #endif
     167    uint32_t structureIndex = structureID >> s_numberOfEntropyBits;
     168    ASSERT(structureIndex && structureIndex < s_maximumNumberOfStructures);
     169    RELEASE_ASSERT(table()[structureIndex].encodedStructureBits == encode(structure, structureID));
     170    m_size--;
     171    if (!m_firstFreeOffset) {
     172        table()[structureIndex].offset = 0;
     173        m_firstFreeOffset = structureIndex;
     174        m_lastFreeOffset = structureIndex;
     175        return;
     176    }
     177
     178    bool insertAtHead = m_weakRandom.getUint32() & 1;
     179    if (insertAtHead) {
     180        table()[structureIndex].offset = m_firstFreeOffset;
     181        m_firstFreeOffset = structureIndex;
     182    } else {
     183        table()[structureIndex].offset = 0;
     184        table()[m_lastFreeOffset].offset = structureIndex;
     185        m_lastFreeOffset = structureIndex;
     186    }
    119187}
    120188
     189#endif // USE(JSVALUE64)
     190
    121191} // namespace JSC
  • branches/safari-607-branch/Source/JavaScriptCore/runtime/StructureIDTable.h

    r229309 r246423  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2929#include <wtf/UniqueArray.h>
    3030#include <wtf/Vector.h>
     31#include <wtf/WeakRandom.h>
    3132
    3233namespace JSC {
     
    5657    return id & ~nukedStructureIDBit();
    5758}
    58 #else
     59#else // not USE(JSVALUE64)
    5960typedef Structure* StructureID;
    6061
     
    7879    return bitwise_cast<StructureID>(bitwise_cast<uintptr_t>(id) & ~bitwise_cast<uintptr_t>(nukedStructureIDBit()));
    7980}
    80 #endif
     81#endif // not USE(JSVALUE64)
     82
     83#if USE(JSVALUE64)
     84
     85using EncodedStructureBits = uintptr_t;
    8186
    8287class StructureIDTable {
     
    8792    void** base() { return reinterpret_cast<void**>(&m_table); }
    8893
     94    bool isValid(StructureID);
    8995    Structure* get(StructureID);
    9096    void deallocateID(Structure*, StructureID);
     
    97103private:
    98104    void resize(size_t newCapacity);
     105    void makeFreeListFromRange(uint32_t first, uint32_t last);
    99106
    100107    union StructureOrOffset {
    101108        WTF_MAKE_FAST_ALLOCATED;
    102109    public:
    103         Structure* structure;
     110        EncodedStructureBits encodedStructureBits;
    104111        StructureID offset;
    105112    };
     
    107114    StructureOrOffset* table() const { return m_table.get(); }
    108115   
    109     static const size_t s_initialSize = 256;
     116    static Structure* decode(EncodedStructureBits, StructureID);
     117    static EncodedStructureBits encode(Structure*, StructureID);
     118
     119    static constexpr size_t s_initialSize = 512;
    110120
    111121    Vector<UniqueArray<StructureOrOffset>> m_oldTables;
    112122
    113     uint32_t m_firstFreeOffset;
     123    uint32_t m_firstFreeOffset { 0 };
     124    uint32_t m_lastFreeOffset { 0 };
    114125    UniqueArray<StructureOrOffset> m_table;
    115126
    116     size_t m_size;
     127    size_t m_size { 0 };
    117128    size_t m_capacity;
    118129
    119 #if USE(JSVALUE64)
    120     static const StructureID s_unusedID = unusedPointer;
    121 #endif
     130    WeakRandom m_weakRandom;
     131
     132    static constexpr StructureID s_unusedID = 0;
     133
     134public:
     135    // 1. StructureID is encoded as:
     136    //
     137    //    ----------------------------------------------------------------
     138    //    | 1 Nuke Bit | 24 StructureIDTable index bits | 7 entropy bits |
     139    //    ----------------------------------------------------------------
     140    //
     141    //    The entropy bits are chosen at random and assigned when a StructureID
     142    //    is allocated.
     143    //
     144    // 2. For each StructureID, the StructureIDTable stores encodedStructureBits
     145    //    which are encoded from the structure pointer as such:
     146    //
     147    //    ----------------------------------------------------------------
     148    //    | 7 entropy bits |                   57 structure pointer bits |
     149    //    ----------------------------------------------------------------
     150    //
     151    //    The entropy bits here are the same 7 bits used in the encoding of the
     152    //    StructureID for this structure entry in the StructureIDTable.
     153
     154    static constexpr uint32_t s_numberOfNukeBits = 1;
     155    static constexpr uint32_t s_numberOfEntropyBits = 7;
     156    static constexpr uint32_t s_entropyBitsShiftForStructurePointer = (sizeof(intptr_t) * 8) - s_numberOfEntropyBits;
     157
     158    static constexpr uint32_t s_maximumNumberOfStructures = 1 << (32 - s_numberOfEntropyBits - s_numberOfNukeBits);
    122159};
    123160
     161ALWAYS_INLINE Structure* StructureIDTable::decode(EncodedStructureBits bits, StructureID structureID)
     162{
     163    return bitwise_cast<Structure*>(bits ^ (static_cast<uintptr_t>(structureID) << s_entropyBitsShiftForStructurePointer));
     164}
     165
     166ALWAYS_INLINE EncodedStructureBits StructureIDTable::encode(Structure* structure, StructureID structureID)
     167{
     168    return bitwise_cast<EncodedStructureBits>(structure) ^ (static_cast<EncodedStructureBits>(structureID) << s_entropyBitsShiftForStructurePointer);
     169}
     170
    124171inline Structure* StructureIDTable::get(StructureID structureID)
    125172{
    126 #if USE(JSVALUE64)
    127173    ASSERT_WITH_SECURITY_IMPLICATION(structureID);
    128174    ASSERT_WITH_SECURITY_IMPLICATION(!isNuked(structureID));
    129     ASSERT_WITH_SECURITY_IMPLICATION(structureID < m_capacity);
    130     return table()[structureID].structure;
    131 #else
    132     return structureID;
     175    uint32_t structureIndex = structureID >> s_numberOfEntropyBits;
     176    ASSERT_WITH_SECURITY_IMPLICATION(structureIndex < m_capacity);
     177    return decode(table()[structureIndex].encodedStructureBits, structureID);
     178}
     179
     180inline bool StructureIDTable::isValid(StructureID structureID)
     181{
     182    if (!structureID)
     183        return false;
     184    uint32_t structureIndex = structureID >> s_numberOfEntropyBits;
     185    if (structureIndex >= m_capacity)
     186        return false;
     187#if CPU(ADDRESS64)
     188    Structure* structure = decode(table()[structureIndex].encodedStructureBits, structureID);
     189    if (reinterpret_cast<uintptr_t>(structure) >> s_entropyBitsShiftForStructurePointer)
     190        return false;
    133191#endif
    134 }
     192    return true;
     193}
     194
     195#else // not USE(JSVALUE64)
     196
     197class StructureIDTable {
     198    friend class LLIntOffsetsExtractor;
     199public:
     200    StructureIDTable() = default;
     201
     202    Structure* get(StructureID structureID) { return structureID; }
     203    void deallocateID(Structure*, StructureID) { }
     204    StructureID allocateID(Structure* structure)
     205    {
     206        ASSERT(!isNuked(structure));
     207        return structure;
     208    };
     209
     210    void flushOldTables() { }
     211};
     212
     213#endif // not USE(JSVALUE64)
    135214
    136215} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.