Changeset 246423 in webkit
- Timestamp:
- Jun 13, 2019, 7:59:16 PM (7 years ago)
- Location:
- branches/safari-607-branch/Source/JavaScriptCore
- Files:
-
- 10 edited
-
ChangeLog (modified) (1 diff)
-
ftl/FTLLowerDFGToB3.cpp (modified) (1 diff)
-
heap/SlotVisitor.cpp (modified) (2 diffs)
-
jit/AssemblyHelpers.cpp (modified) (2 diffs)
-
jit/AssemblyHelpers.h (modified) (3 diffs)
-
jit/SpecializedThunkJIT.h (modified) (2 diffs)
-
llint/LowLevelInterpreter.asm (modified) (1 diff)
-
llint/LowLevelInterpreter64.asm (modified) (2 diffs)
-
runtime/StructureIDTable.cpp (modified) (4 diffs)
-
runtime/StructureIDTable.h (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/safari-607-branch/Source/JavaScriptCore/ChangeLog
r246420 r246423 1 2019-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 23 2019-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 100 2019-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 125 2019-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 1 139 2019-06-13 Kocsen Chung <kocsen_chung@apple.com> 2 140 -
branches/safari-607-branch/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r246379 r246423 16929 16929 LValue loadStructure(LValue value) 16930 16930 { 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); 16937 16938 } 16938 16939 -
branches/safari-607-branch/Source/JavaScriptCore/heap/SlotVisitor.cpp
r240564 r246423 1 1 /* 2 * Copyright (C) 2012-201 8Apple Inc. All rights reserved.2 * Copyright (C) 2012-2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 199 199 #if USE(JSVALUE64) 200 200 // 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"); 203 203 #endif 204 204 }; -
branches/safari-607-branch/Source/JavaScriptCore/jit/AssemblyHelpers.cpp
r240375 r246423 1 1 /* 2 * Copyright (C) 2011-201 8Apple Inc. All rights reserved.2 * Copyright (C) 2011-2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 370 370 { 371 371 #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 372 380 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); 374 385 loadPtr(vm.heap.structureIDTable().base(), scratch); 386 rshift32(scratch2, TrustedImm32(StructureIDTable::s_numberOfEntropyBits), dest); 375 387 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) 377 391 UNUSED_PARAM(scratch); 392 UNUSED_PARAM(scratch2); 378 393 UNUSED_PARAM(vm); 379 394 loadPtr(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest); 380 #endif 395 #endif // not USE(JSVALUE64) 381 396 } 382 397 -
branches/safari-607-branch/Source/JavaScriptCore/jit/AssemblyHelpers.h
r240375 r246423 1 1 /* 2 * Copyright (C) 2011-201 8Apple Inc. All rights reserved.2 * Copyright (C) 2011-2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 1782 1782 } 1783 1783 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); 1785 1785 JumpList branchIfTruthy(VM& vm, JSValueRegs value, GPRReg scratch, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg scratchFPR0, FPRReg scratchFPR1, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject* globalObject) 1786 1786 { … … 1791 1791 return branchIfValue(vm, value, scratch, scratchIfShouldCheckMasqueradesAsUndefined, scratchFPR0, scratchFPR1, shouldCheckMasqueradesAsUndefined, globalObject, true); 1792 1792 } 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); 1794 1794 1795 1795 template<typename ClassType> -
branches/safari-607-branch/Source/JavaScriptCore/jit/SpecializedThunkJIT.h
r232105 r246423 1 1 /* 2 * Copyright (C) 2010-201 8Apple Inc. All rights reserved.2 * Copyright (C) 2010-2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 72 72 } 73 73 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 83 74 void loadInt32Argument(int argument, RegisterID dst, Jump& failTarget) 84 75 { -
branches/safari-607-branch/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
r240399 r246423 203 203 const DeletedValueTag = constexpr JSValue::DeletedValueTag 204 204 const LowestTag = constexpr JSValue::LowestTag 205 end 206 207 if JSVALUE64 208 const NumberOfStructureIDEntropyBits = constexpr StructureIDTable::s_numberOfEntropyBits 209 const StructureEntropyBitsShift = constexpr StructureIDTable::s_entropyBitsShiftForStructurePointer 205 210 end 206 211 -
branches/safari-607-branch/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r240501 r246423 536 536 loadp CodeBlock::m_poisonedVM[scratch], scratch 537 537 unpoison(_g_CodeBlockPoison, scratch, scratch2) 538 move structureIDThenStructure, scratch2 539 rshifti NumberOfStructureIDEntropyBits, scratch2 538 540 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 540 544 end 541 545 … … 1176 1180 return(t1) 1177 1181 .masqueradesAsUndefined: 1178 loadStructureWithScratch(t0, t3, t1, t 5)1182 loadStructureWithScratch(t0, t3, t1, t2) 1179 1183 loadp CodeBlock[cfr], t1 1180 1184 loadp CodeBlock::m_globalObject[t1], t1 -
branches/safari-607-branch/Source/JavaScriptCore/runtime/StructureIDTable.cpp
r229309 r246423 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013-2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 32 32 namespace JSC { 33 33 34 #if USE(JSVALUE64) 35 34 36 StructureIDTable::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) 38 39 , m_capacity(s_initialSize) 39 40 { 40 41 // We pre-allocate the first offset so that the null Structure 41 42 // 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 48 void 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; 43 98 } 44 99 45 100 void StructureIDTable::resize(size_t newCapacity) 46 101 { 102 if (newCapacity > s_maximumNumberOfStructures) 103 newCapacity = s_maximumNumberOfStructures; 104 47 105 // Create the new table. 48 106 auto newTable = makeUniqueArray<StructureOrOffset>(newCapacity); … … 62 120 // Update the capacity. 63 121 m_capacity = newCapacity; 122 123 makeFreeListFromRange(m_size, m_capacity - 1); 64 124 } 65 125 … … 71 131 StructureID StructureIDTable::allocateID(Structure* structure) 72 132 { 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); 78 137 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); 93 139 } 94 140 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 } 96 151 97 StructureID result= m_firstFreeOffset;152 uint32_t structureIndex = m_firstFreeOffset; 98 153 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++; 100 160 ASSERT(!isNuked(result)); 101 161 return result; 102 #else103 ASSERT(!isNuked(structure));104 return structure;105 #endif106 162 } 107 163 108 164 void StructureIDTable::deallocateID(Structure* structure, StructureID structureID) 109 165 { 110 #if USE(JSVALUE64)111 166 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 } 119 187 } 120 188 189 #endif // USE(JSVALUE64) 190 121 191 } // namespace JSC -
branches/safari-607-branch/Source/JavaScriptCore/runtime/StructureIDTable.h
r229309 r246423 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013-2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 29 29 #include <wtf/UniqueArray.h> 30 30 #include <wtf/Vector.h> 31 #include <wtf/WeakRandom.h> 31 32 32 33 namespace JSC { … … 56 57 return id & ~nukedStructureIDBit(); 57 58 } 58 #else 59 #else // not USE(JSVALUE64) 59 60 typedef Structure* StructureID; 60 61 … … 78 79 return bitwise_cast<StructureID>(bitwise_cast<uintptr_t>(id) & ~bitwise_cast<uintptr_t>(nukedStructureIDBit())); 79 80 } 80 #endif 81 #endif // not USE(JSVALUE64) 82 83 #if USE(JSVALUE64) 84 85 using EncodedStructureBits = uintptr_t; 81 86 82 87 class StructureIDTable { … … 87 92 void** base() { return reinterpret_cast<void**>(&m_table); } 88 93 94 bool isValid(StructureID); 89 95 Structure* get(StructureID); 90 96 void deallocateID(Structure*, StructureID); … … 97 103 private: 98 104 void resize(size_t newCapacity); 105 void makeFreeListFromRange(uint32_t first, uint32_t last); 99 106 100 107 union StructureOrOffset { 101 108 WTF_MAKE_FAST_ALLOCATED; 102 109 public: 103 Structure* structure;110 EncodedStructureBits encodedStructureBits; 104 111 StructureID offset; 105 112 }; … … 107 114 StructureOrOffset* table() const { return m_table.get(); } 108 115 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; 110 120 111 121 Vector<UniqueArray<StructureOrOffset>> m_oldTables; 112 122 113 uint32_t m_firstFreeOffset; 123 uint32_t m_firstFreeOffset { 0 }; 124 uint32_t m_lastFreeOffset { 0 }; 114 125 UniqueArray<StructureOrOffset> m_table; 115 126 116 size_t m_size ;127 size_t m_size { 0 }; 117 128 size_t m_capacity; 118 129 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 134 public: 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); 122 159 }; 123 160 161 ALWAYS_INLINE Structure* StructureIDTable::decode(EncodedStructureBits bits, StructureID structureID) 162 { 163 return bitwise_cast<Structure*>(bits ^ (static_cast<uintptr_t>(structureID) << s_entropyBitsShiftForStructurePointer)); 164 } 165 166 ALWAYS_INLINE EncodedStructureBits StructureIDTable::encode(Structure* structure, StructureID structureID) 167 { 168 return bitwise_cast<EncodedStructureBits>(structure) ^ (static_cast<EncodedStructureBits>(structureID) << s_entropyBitsShiftForStructurePointer); 169 } 170 124 171 inline Structure* StructureIDTable::get(StructureID structureID) 125 172 { 126 #if USE(JSVALUE64)127 173 ASSERT_WITH_SECURITY_IMPLICATION(structureID); 128 174 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 180 inline 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; 133 191 #endif 134 } 192 return true; 193 } 194 195 #else // not USE(JSVALUE64) 196 197 class StructureIDTable { 198 friend class LLIntOffsetsExtractor; 199 public: 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) 135 214 136 215 } // namespace JSC
Note:
See TracChangeset
for help on using the changeset viewer.