UnlinkedMetadataTableInlines.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 "MetadataTable.h" 29 #include "UnlinkedMetadataTable.h" 30 #include <wtf/FastMalloc.h> 31 32 namespace JSC { 33 34 35 ALWAYS_INLINE UnlinkedMetadataTable::UnlinkedMetadataTable() 36 : m_hasMetadata(false) 37 , m_isFinalized(false) 38 , m_isLinked(false) 39 , m_is32Bit(false) 40 , m_rawBuffer(static_cast<uint8_t*>(MetadataTableMalloc::zeroedMalloc(sizeof(LinkingData) + s_offset32TableSize))) 41 { 42 } 43 44 ALWAYS_INLINE UnlinkedMetadataTable::UnlinkedMetadataTable(bool is32Bit) 45 : m_hasMetadata(false) 46 , m_isFinalized(false) 47 , m_isLinked(false) 48 , m_is32Bit(is32Bit) 49 , m_rawBuffer(static_cast<uint8_t*>(MetadataTableMalloc::zeroedMalloc(sizeof(LinkingData) + (is32Bit ? s_offset16TableSize + s_offset32TableSize : s_offset16TableSize)))) 50 { 51 } 52 53 ALWAYS_INLINE UnlinkedMetadataTable::UnlinkedMetadataTable(EmptyTag) 54 : m_hasMetadata(false) 55 , m_isFinalized(true) 56 , m_isLinked(false) 57 , m_is32Bit(false) 58 , m_rawBuffer(nullptr) 59 { 60 } 61 62 ALWAYS_INLINE UnlinkedMetadataTable::~UnlinkedMetadataTable() 63 { 64 ASSERT(!m_isLinked); 65 if (m_hasMetadata || !m_isFinalized) 66 MetadataTableMalloc::free(m_rawBuffer); 67 } 68 69 ALWAYS_INLINE unsigned UnlinkedMetadataTable::addEntry(OpcodeID opcodeID) 70 { 71 ASSERT(!m_isFinalized && opcodeID < s_offsetTableEntries - 1); 72 m_hasMetadata = true; 73 return preprocessBuffer()[opcodeID]++; 74 } 75 76 ALWAYS_INLINE size_t UnlinkedMetadataTable::sizeInBytes() 77 { 78 if (m_isFinalized && !m_hasMetadata) 79 return 0; 80 81 if (m_is32Bit) 82 return s_offset16TableSize + s_offset32TableSize; 83 return s_offset16TableSize; 84 } 85 86 ALWAYS_INLINE size_t UnlinkedMetadataTable::sizeInBytes(MetadataTable& metadataTable) 87 { 88 ASSERT(m_isFinalized); 89 90 // In this case, we return the size of the table minus the offset table, 91 // which was already accounted for in the UnlinkedCodeBlock. 92 93 // Be careful not to touch m_rawBuffer if this metadataTable is not owning it. 94 // It is possible that, m_rawBuffer is realloced in the other thread while we are accessing here. 95 size_t result = metadataTable.totalSize(); 96 if (metadataTable.buffer() == buffer()) { 97 ASSERT(m_isLinked); 98 if (m_is32Bit) 99 return result - (s_offset16TableSize + s_offset32TableSize); 100 return result - s_offset16TableSize; 101 } 102 return result; 103 } 104 105 ALWAYS_INLINE RefPtr<MetadataTable> UnlinkedMetadataTable::link() 106 { 107 ASSERT(m_isFinalized); 108 109 if (!m_hasMetadata) 110 return nullptr; 111 112 unsigned totalSize = this->totalSize(); 113 unsigned offsetTableSize = this->offsetTableSize(); 114 uint8_t* buffer; 115 if (!m_isLinked) { 116 m_isLinked = true; 117 m_rawBuffer = buffer = reinterpret_cast<uint8_t*>(MetadataTableMalloc::realloc(m_rawBuffer, sizeof(LinkingData) + totalSize)); 118 } else { 119 buffer = reinterpret_cast<uint8_t*>(MetadataTableMalloc::malloc(sizeof(LinkingData) + totalSize)); 120 memcpy(buffer, m_rawBuffer, sizeof(LinkingData) + offsetTableSize); 121 } 122 memset(buffer + sizeof(LinkingData) + offsetTableSize, 0, totalSize - offsetTableSize); 123 return adoptRef(*new (buffer + sizeof(LinkingData)) MetadataTable(*this)); 124 } 125 126 ALWAYS_INLINE void UnlinkedMetadataTable::unlink(MetadataTable& metadataTable) 127 { 128 ASSERT(m_isFinalized); 129 if (!m_hasMetadata) 130 return; 131 132 if (metadataTable.buffer() == buffer()) { 133 ASSERT(m_isLinked); 134 m_isLinked = false; 135 m_rawBuffer = static_cast<uint8_t*>(MetadataTableMalloc::realloc(m_rawBuffer, sizeof(LinkingData) + offsetTableSize())); 136 return; 137 } 138 MetadataTableMalloc::free(&metadataTable.linkingData()); 139 } 140 141 } // namespace JSC