UnlinkedMetadataTable.h
1 /* 2 * Copyright (C) 2018 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #pragma once 27 28 #include "Opcode.h" 29 #include <wtf/Ref.h> 30 #include <wtf/RefCounted.h> 31 32 namespace JSC { 33 34 class VM; 35 36 DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(MetadataTable); 37 38 class MetadataTable; 39 40 class UnlinkedMetadataTable : public RefCounted<UnlinkedMetadataTable> { 41 friend class LLIntOffsetsExtractor; 42 friend class MetadataTable; 43 friend class CachedMetadataTable; 44 public: 45 static constexpr unsigned s_maxMetadataAlignment = 8; 46 47 struct LinkingData { 48 Ref<UnlinkedMetadataTable> unlinkedMetadata; 49 unsigned refCount; 50 }; 51 52 ~UnlinkedMetadataTable(); 53 54 unsigned addEntry(OpcodeID); 55 56 size_t sizeInBytes(); 57 58 void finalize(); 59 60 RefPtr<MetadataTable> link(); 61 62 static Ref<UnlinkedMetadataTable> create() 63 { 64 return adoptRef(*new UnlinkedMetadataTable); 65 } 66 67 private: 68 enum EmptyTag { Empty }; 69 70 UnlinkedMetadataTable(); 71 UnlinkedMetadataTable(bool is32Bit); 72 UnlinkedMetadataTable(EmptyTag); 73 74 static Ref<UnlinkedMetadataTable> create(bool is32Bit) 75 { 76 return adoptRef(*new UnlinkedMetadataTable(is32Bit)); 77 } 78 79 static Ref<UnlinkedMetadataTable> empty() 80 { 81 return adoptRef(*new UnlinkedMetadataTable(Empty)); 82 } 83 84 void unlink(MetadataTable&); 85 86 size_t sizeInBytes(MetadataTable&); 87 88 unsigned totalSize() const 89 { 90 ASSERT(m_isFinalized); 91 if (m_is32Bit) 92 return offsetTable32()[s_offsetTableEntries - 1]; 93 return offsetTable16()[s_offsetTableEntries - 1]; 94 } 95 96 unsigned offsetTableSize() const 97 { 98 ASSERT(m_isFinalized); 99 if (m_is32Bit) 100 return s_offset16TableSize + s_offset32TableSize; 101 return s_offset16TableSize; 102 } 103 104 using Offset32 = uint32_t; 105 using Offset16 = uint16_t; 106 107 static constexpr unsigned s_offsetTableEntries = NUMBER_OF_BYTECODE_WITH_METADATA + 1; // one extra entry for the "end" offset; 108 109 // Not to break alignment of 32bit offset table, we round up size with sizeof(Offset32). 110 static constexpr unsigned s_offset16TableSize = roundUpToMultipleOf<sizeof(Offset32)>(s_offsetTableEntries * sizeof(Offset16)); 111 // Not to break alignment of the metadata calculated based on the alignment of s_offset16TableSize, s_offset32TableSize must be rounded by 8. 112 // Then, s_offset16TableSize and s_offset16TableSize + s_offset32TableSize offer the same alignment characteristics for subsequent Metadata. 113 static constexpr unsigned s_offset32TableSize = roundUpToMultipleOf<s_maxMetadataAlignment>(s_offsetTableEntries * sizeof(Offset32)); 114 115 Offset32* preprocessBuffer() const { return bitwise_cast<Offset32*>(m_rawBuffer + sizeof(LinkingData)); } 116 void* buffer() const { return m_rawBuffer + sizeof(LinkingData); } 117 118 Offset16* offsetTable16() const 119 { 120 ASSERT(!m_is32Bit); 121 return bitwise_cast<Offset16*>(m_rawBuffer + sizeof(LinkingData)); 122 } 123 Offset32* offsetTable32() const 124 { 125 ASSERT(m_is32Bit); 126 return bitwise_cast<Offset32*>(m_rawBuffer + sizeof(LinkingData) + s_offset16TableSize); 127 } 128 129 bool m_hasMetadata : 1; 130 bool m_isFinalized : 1; 131 bool m_isLinked : 1; 132 bool m_is32Bit : 1; 133 uint8_t* m_rawBuffer; 134 }; 135 136 } // namespace JSC