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

Changeset 245669 in webkit


Ignore:
Timestamp:
May 22, 2019, 6:47:29 PM (7 years ago)
Author:
ysuzuki@apple.com
Message:

[JSC] UnlinkedMetadataTable's offset table should be small
https://bugs.webkit.org/show_bug.cgi?id=197910

Reviewed by Saam Barati.

In Gmail, we found that massive # of UnlinkedMetadataTable (21979 - 24727) exists. Each UnlinkedMetadataTable takes at least 204 bytes
because of large (unsinged) offset table. This patch reduces the size of offset table by introducing 16bit version offset table.
Previously our code for looking up Metadata is like this.

offset = offsetTable32[opcode]
metadata = (SomeOp::Metadata*)table[offset] + id

Instead, we introduce uint16_t offset table. The lookup code becomes like this.

offset = offsetTable16[opcode]
if (!offset)

offset = offsetTable32[opcode]

metadata = (SomeOp::Metadata*)table[offset] + id

We use 0 offset as a marker to indicate that we have 32bit offset table. This is OK since 0 offset does not appear since all the offsets
included in this table is larger than s_offset16TableSize.

32bit offset table is allocated only when the offset exceeds 16bit range. It means that this will be used only when Metadata table is larger
than almost 64KB. Even in Gmail, such MetadataTable is rare, and additional 32bit offset table size does not matter much in this case since
MetadataTable is already so large.

Based on the # of UnlinkedMetadataTables, this optimization should improve Gmail steady state memory by 2MB.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • bytecode/MetadataTable.cpp:

(JSC::MetadataTable::~MetadataTable):
(JSC::MetadataTable::destroy):

  • bytecode/MetadataTable.h:

(JSC::MetadataTable::ref):
(JSC::MetadataTable::deref):
(JSC::MetadataTable::buffer):
(JSC::MetadataTable::is32Bit const):
(JSC::MetadataTable::offsetTable16 const):
(JSC::MetadataTable::offsetTable32 const):
(JSC::MetadataTable::totalSize const):
(JSC::MetadataTable::getOffset const):
(JSC::MetadataTable::getImpl):
(JSC::MetadataTable::ref const): Deleted.
(JSC::MetadataTable::deref const): Deleted.

  • bytecode/Opcode.cpp:
  • bytecode/UnlinkedMetadataTable.cpp: Added.

(JSC::UnlinkedMetadataTable::finalize):

  • bytecode/UnlinkedMetadataTable.h:

(JSC::UnlinkedMetadataTable::create):
(JSC::UnlinkedMetadataTable::totalSize const):
(JSC::UnlinkedMetadataTable::offsetTableSize const):
(JSC::UnlinkedMetadataTable::preprocessBuffer const):
(JSC::UnlinkedMetadataTable::buffer const):
(JSC::UnlinkedMetadataTable::offsetTable16 const):
(JSC::UnlinkedMetadataTable::offsetTable32 const):

  • bytecode/UnlinkedMetadataTableInlines.h:

(JSC::UnlinkedMetadataTable::UnlinkedMetadataTable):
(JSC::UnlinkedMetadataTable::addEntry):
(JSC::UnlinkedMetadataTable::sizeInBytes):
(JSC::UnlinkedMetadataTable::link):
(JSC::UnlinkedMetadataTable::unlink):
(JSC::UnlinkedMetadataTable::finalize): Deleted.

  • llint/LowLevelInterpreter.asm:
  • runtime/CachedTypes.cpp:

(JSC::CachedMetadataTable::encode):
(JSC::CachedMetadataTable::decode const):

Location:
trunk/Source/JavaScriptCore
Files:
1 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r245667 r245669  
     12019-05-22  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] UnlinkedMetadataTable's offset table should be small
     4        https://bugs.webkit.org/show_bug.cgi?id=197910
     5
     6        Reviewed by Saam Barati.
     7
     8        In Gmail, we found that massive # of UnlinkedMetadataTable (21979 - 24727) exists. Each UnlinkedMetadataTable takes at least 204 bytes
     9        because of large (unsinged) offset table. This patch reduces the size of offset table by introducing 16bit version offset table.
     10        Previously our code for looking up Metadata is like this.
     11
     12            offset = offsetTable32[opcode]
     13            metadata = (SomeOp::Metadata*)table[offset] + id
     14
     15        Instead, we introduce uint16_t offset table. The lookup code becomes like this.
     16
     17            offset = offsetTable16[opcode]
     18            if (!offset)
     19                offset = offsetTable32[opcode]
     20            metadata = (SomeOp::Metadata*)table[offset] + id
     21
     22        We use 0 offset as a marker to indicate that we have 32bit offset table. This is OK since 0 offset does not appear since all the offsets
     23        included in this table is larger than s_offset16TableSize.
     24
     25        32bit offset table is allocated only when the offset exceeds 16bit range. It means that this will be used only when Metadata table is larger
     26        than almost 64KB. Even in Gmail, such MetadataTable is rare, and additional 32bit offset table size does not matter much in this case since
     27        MetadataTable is already so large.
     28
     29        Based on the # of UnlinkedMetadataTables, this optimization should improve Gmail steady state memory by 2MB.
     30
     31        * JavaScriptCore.xcodeproj/project.pbxproj:
     32        * Sources.txt:
     33        * bytecode/MetadataTable.cpp:
     34        (JSC::MetadataTable::~MetadataTable):
     35        (JSC::MetadataTable::destroy):
     36        * bytecode/MetadataTable.h:
     37        (JSC::MetadataTable::ref):
     38        (JSC::MetadataTable::deref):
     39        (JSC::MetadataTable::buffer):
     40        (JSC::MetadataTable::is32Bit const):
     41        (JSC::MetadataTable::offsetTable16 const):
     42        (JSC::MetadataTable::offsetTable32 const):
     43        (JSC::MetadataTable::totalSize const):
     44        (JSC::MetadataTable::getOffset const):
     45        (JSC::MetadataTable::getImpl):
     46        (JSC::MetadataTable::ref const): Deleted.
     47        (JSC::MetadataTable::deref const): Deleted.
     48        * bytecode/Opcode.cpp:
     49        * bytecode/UnlinkedMetadataTable.cpp: Added.
     50        (JSC::UnlinkedMetadataTable::finalize):
     51        * bytecode/UnlinkedMetadataTable.h:
     52        (JSC::UnlinkedMetadataTable::create):
     53        (JSC::UnlinkedMetadataTable::totalSize const):
     54        (JSC::UnlinkedMetadataTable::offsetTableSize const):
     55        (JSC::UnlinkedMetadataTable::preprocessBuffer const):
     56        (JSC::UnlinkedMetadataTable::buffer const):
     57        (JSC::UnlinkedMetadataTable::offsetTable16 const):
     58        (JSC::UnlinkedMetadataTable::offsetTable32 const):
     59        * bytecode/UnlinkedMetadataTableInlines.h:
     60        (JSC::UnlinkedMetadataTable::UnlinkedMetadataTable):
     61        (JSC::UnlinkedMetadataTable::addEntry):
     62        (JSC::UnlinkedMetadataTable::sizeInBytes):
     63        (JSC::UnlinkedMetadataTable::link):
     64        (JSC::UnlinkedMetadataTable::unlink):
     65        (JSC::UnlinkedMetadataTable::finalize): Deleted.
     66        * llint/LowLevelInterpreter.asm:
     67        * runtime/CachedTypes.cpp:
     68        (JSC::CachedMetadataTable::encode):
     69        (JSC::CachedMetadataTable::decode const):
     70
    1712019-05-22  Yusuke Suzuki  <ysuzuki@apple.com>
    272
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r245564 r245669  
    47254725                E18E3A560DF9278C00D90B34 /* VM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = VM.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
    47264726                E18E3A570DF9278C00D90B34 /* VM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = VM.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
     4727                E3060128228F978100FAABDF /* UnlinkedMetadataTable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UnlinkedMetadataTable.cpp; sourceTree = "<group>"; };
    47274728                E30677971B8BC6F5003F87F0 /* ModuleLoader.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = ModuleLoader.js; sourceTree = "<group>"; };
    47284729                E31179A92288385D00514B2C /* SymbolTableOrScopeDepth.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SymbolTableOrScopeDepth.h; sourceTree = "<group>"; };
     
    80688069                                14142E501B796ECE00F4BF4B /* UnlinkedFunctionExecutable.h */,
    80698070                                14AD911C1DCA9FA40014F9FE /* UnlinkedGlobalCodeBlock.h */,
     8071                                E3060128228F978100FAABDF /* UnlinkedMetadataTable.cpp */,
    80708072                                142D52BE21762958002DB086 /* UnlinkedMetadataTable.h */,
    80718073                                142D52BD21762957002DB086 /* UnlinkedMetadataTableInlines.h */,
  • trunk/Source/JavaScriptCore/Sources.txt

    r245214 r245669  
    274274bytecode/UnlinkedFunctionCodeBlock.cpp
    275275bytecode/UnlinkedFunctionExecutable.cpp
     276bytecode/UnlinkedMetadataTable.cpp
    276277bytecode/UnlinkedModuleProgramCodeBlock.cpp
    277278bytecode/UnlinkedProgramCodeBlock.cpp
  • trunk/Source/JavaScriptCore/bytecode/MetadataTable.cpp

    r244088 r245669  
    5757    for (unsigned i = 0; i < NUMBER_OF_BYTECODE_WITH_METADATA; i++)
    5858        getOpcodeType<DeallocTable>(static_cast<OpcodeID>(i), this);
    59     Ref<UnlinkedMetadataTable> unlinkedMetadata = WTFMove(linkingData().unlinkedMetadata);
    6059    linkingData().~LinkingData();
     60}
     61
     62void MetadataTable::destroy(MetadataTable* table)
     63{
     64    Ref<UnlinkedMetadataTable> unlinkedMetadata = WTFMove(table->linkingData().unlinkedMetadata);
     65    table->~MetadataTable();
    6166    // Since UnlinkedMetadata::unlink frees the underlying memory of MetadataTable.
    6267    // We need to destroy LinkingData before calling it.
    63     unlinkedMetadata->unlink(*this);
     68    unlinkedMetadata->unlink(*table);
    6469}
    6570
  • trunk/Source/JavaScriptCore/bytecode/MetadataTable.h

    r245658 r245669  
    6464    size_t sizeInBytes();
    6565
    66     void ref() const
     66    void ref()
    6767    {
    6868        ++linkingData().refCount;
    6969    }
    7070
    71     void deref() const
     71    void deref()
    7272    {
    7373        unsigned tempRefCount = linkingData().refCount - 1;
    7474        if (!tempRefCount) {
    75             this->~MetadataTable();
     75            MetadataTable::destroy(this);
    7676            return;
    7777        }
     
    9292    MetadataTable(UnlinkedMetadataTable&);
    9393
     94    UnlinkedMetadataTable::Offset16* offsetTable16() const { return bitwise_cast<UnlinkedMetadataTable::Offset16*>(this); }
     95    UnlinkedMetadataTable::Offset32* offsetTable32() const { return bitwise_cast<UnlinkedMetadataTable::Offset32*>(bitwise_cast<uint8_t*>(this) + UnlinkedMetadataTable::s_offset16TableSize); }
     96
     97    size_t totalSize() const
     98    {
     99        return getOffset(UnlinkedMetadataTable::s_offsetTableEntries - 1);
     100    }
     101
    94102    UnlinkedMetadataTable::LinkingData& linkingData() const
    95103    {
     
    97105    }
    98106
    99     UnlinkedMetadataTable::Offset* buffer()
     107    void* buffer() { return this; }
     108
     109    bool is32Bit() const { return !offsetTable16()[0]; }
     110
     111    ALWAYS_INLINE unsigned getOffset(unsigned i) const
    100112    {
    101         return bitwise_cast<UnlinkedMetadataTable::Offset*>(this);
     113        unsigned offset = offsetTable16()[i];
     114        if (offset)
     115            return offset;
     116        return offsetTable32()[i];
    102117    }
    103118
    104119    ALWAYS_INLINE uint8_t* getImpl(unsigned i)
    105120    {
    106         return bitwise_cast<uint8_t*>(this) + buffer()[i];
     121        return bitwise_cast<uint8_t*>(this) + getOffset(i);
    107122    }
     123
     124    static void destroy(MetadataTable*);
    108125};
    109126
  • trunk/Source/JavaScriptCore/bytecode/Opcode.cpp

    r243633 r245669  
    204204#endif
    205205
    206 static unsigned metadataSizes[] = {
     206static const unsigned metadataSizes[] = {
    207207
    208208#define METADATA_SIZE(size) size,
     
    212212};
    213213
    214 static unsigned metadataAlignments[] = {
     214static const unsigned metadataAlignments[] = {
    215215
    216216#define METADATA_ALIGNMENT(size) size,
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedMetadataTable.h

    r244019 r245669  
    3838    friend class MetadataTable;
    3939    friend class CachedMetadataTable;
     40public:
     41    static constexpr unsigned s_maxMetadataAlignment = 8;
    4042
    41 public:
    4243    struct LinkingData {
    4344        Ref<UnlinkedMetadataTable> unlinkedMetadata;
     
    6263private:
    6364    UnlinkedMetadataTable();
     65    UnlinkedMetadataTable(bool is32Bit);
     66
     67    static Ref<UnlinkedMetadataTable> create(bool is32Bit)
     68    {
     69        return adoptRef(*new UnlinkedMetadataTable(is32Bit));
     70    }
    6471
    6572    void unlink(MetadataTable&);
     
    6774    size_t sizeInBytes(MetadataTable&);
    6875
    69     using Offset = unsigned;
     76    unsigned totalSize() const
     77    {
     78        ASSERT(m_isFinalized);
     79        if (m_is32Bit)
     80            return offsetTable32()[s_offsetTableEntries - 1];
     81        return offsetTable16()[s_offsetTableEntries - 1];
     82    }
     83
     84    unsigned offsetTableSize() const
     85    {
     86        ASSERT(m_isFinalized);
     87        if (m_is32Bit)
     88            return s_offset16TableSize + s_offset32TableSize;
     89        return s_offset16TableSize;
     90    }
     91
     92    using Offset32 = uint32_t;
     93    using Offset16 = uint16_t;
    7094
    7195    static constexpr unsigned s_offsetTableEntries = NUMBER_OF_BYTECODE_WITH_METADATA + 1; // one extra entry for the "end" offset;
    72     static constexpr unsigned s_offsetTableSize = s_offsetTableEntries * sizeof(UnlinkedMetadataTable::Offset);
    7396
    74     Offset* buffer() const { return bitwise_cast<Offset*>(bitwise_cast<uint8_t*>(m_rawBuffer) + sizeof(LinkingData)); }
     97    // Not to break alignment of 32bit offset table, we round up size with sizeof(Offset32).
     98    static constexpr unsigned s_offset16TableSize = roundUpToMultipleOf<sizeof(Offset32)>(s_offsetTableEntries * sizeof(Offset16));
     99    // Not to break alignment of the metadata calculated based on the alignment of s_offset16TableSize, s_offset32TableSize must be rounded by 8.
     100    // Then, s_offset16TableSize and s_offset16TableSize + s_offset32TableSize offer the same alignment characteristics for subsequent Metadata.
     101    static constexpr unsigned s_offset32TableSize = roundUpToMultipleOf<s_maxMetadataAlignment>(s_offsetTableEntries * sizeof(Offset32));
     102
     103    Offset32* preprocessBuffer() const { return bitwise_cast<Offset32*>(m_rawBuffer + sizeof(LinkingData)); }
     104    void* buffer() const { return m_rawBuffer + sizeof(LinkingData); }
     105
     106    Offset16* offsetTable16() const
     107    {
     108        ASSERT(!m_is32Bit);
     109        return bitwise_cast<Offset16*>(m_rawBuffer + sizeof(LinkingData));
     110    }
     111    Offset32* offsetTable32() const
     112    {
     113        ASSERT(m_is32Bit);
     114        return bitwise_cast<Offset32*>(m_rawBuffer + sizeof(LinkingData) + s_offset16TableSize);
     115    }
    75116
    76117    bool m_hasMetadata : 1;
    77118    bool m_isFinalized : 1;
    78119    bool m_isLinked : 1;
    79     void* m_rawBuffer;
     120    bool m_is32Bit : 1;
     121    uint8_t* m_rawBuffer;
    80122};
    81123
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedMetadataTableInlines.h

    r240915 r245669  
    3636    , m_isFinalized(false)
    3737    , m_isLinked(false)
    38     , m_rawBuffer(fastZeroedMalloc(sizeof(LinkingData) + s_offsetTableSize))
     38    , m_is32Bit(false)
     39    , m_rawBuffer(static_cast<uint8_t*>(fastZeroedMalloc(sizeof(LinkingData) + s_offset32TableSize)))
     40{
     41}
     42
     43ALWAYS_INLINE UnlinkedMetadataTable::UnlinkedMetadataTable(bool is32Bit)
     44    : m_hasMetadata(false)
     45    , m_isFinalized(false)
     46    , m_isLinked(false)
     47    , m_is32Bit(is32Bit)
     48    , m_rawBuffer(static_cast<uint8_t*>(fastZeroedMalloc(sizeof(LinkingData) + (is32Bit ? s_offset16TableSize + s_offset32TableSize : s_offset16TableSize))))
    3949{
    4050}
     
    5161    ASSERT(!m_isFinalized && opcodeID < s_offsetTableEntries - 1);
    5262    m_hasMetadata = true;
    53     return buffer()[opcodeID]++;
     63    return preprocessBuffer()[opcodeID]++;
    5464}
    5565
     
    5969        return 0;
    6070
    61     return s_offsetTableSize;
     71    if (m_is32Bit)
     72        return s_offset16TableSize + s_offset32TableSize;
     73    return s_offset16TableSize;
    6274}
    6375
     
    6880    // In this case, we return the size of the table minus the offset table,
    6981    // which was already accounted for in the UnlinkedCodeBlock.
     82    size_t result = totalSize();
    7083    if (metadataTable.buffer() == buffer()) {
    7184        ASSERT(m_isLinked);
    72         return buffer()[s_offsetTableEntries - 1] - s_offsetTableSize;
     85        if (m_is32Bit)
     86            return result - (s_offset16TableSize + s_offset32TableSize);
     87        return result - s_offset16TableSize;
    7388    }
    74 
    75     return metadataTable.buffer()[s_offsetTableEntries - 1];
    76 }
    77 
    78 ALWAYS_INLINE void UnlinkedMetadataTable::finalize()
    79 {
    80     ASSERT(!m_isFinalized);
    81     m_isFinalized = true;
    82     if (!m_hasMetadata) {
    83         fastFree(m_rawBuffer);
    84         m_rawBuffer = nullptr;
    85         return;
    86     }
    87 
    88     unsigned offset = s_offsetTableSize;
    89     for (unsigned i = 0; i < s_offsetTableEntries - 1; i++) {
    90         unsigned numberOfEntries = buffer()[i];
    91 
    92         if (numberOfEntries > 0) {
    93             offset = roundUpToMultipleOf(metadataAlignment(static_cast<OpcodeID>(i)), offset);
    94             buffer()[i] = offset;
    95             offset += numberOfEntries * metadataSize(static_cast<OpcodeID>(i));
    96         } else
    97             buffer()[i] = offset;
    98     }
    99     buffer()[s_offsetTableEntries - 1] = offset;
     89    return result;
    10090}
    10191
     
    10797        return nullptr;
    10898
    109     unsigned totalSize = buffer()[s_offsetTableEntries - 1];
     99    unsigned totalSize = this->totalSize();
     100    unsigned offsetTableSize = this->offsetTableSize();
    110101    uint8_t* buffer;
    111102    if (!m_isLinked) {
     
    114105    } else {
    115106        buffer = reinterpret_cast<uint8_t*>(fastMalloc(sizeof(LinkingData) + totalSize));
    116         memcpy(buffer, m_rawBuffer, sizeof(LinkingData) + s_offsetTableSize);
     107        memcpy(buffer, m_rawBuffer, sizeof(LinkingData) + offsetTableSize);
    117108    }
    118     memset(buffer + sizeof(LinkingData) + s_offsetTableSize, 0, totalSize - s_offsetTableSize);
     109    memset(buffer + sizeof(LinkingData) + offsetTableSize, 0, totalSize - offsetTableSize);
    119110    return adoptRef(*new (buffer + sizeof(LinkingData)) MetadataTable(*this));
    120111}
     
    129120        ASSERT(m_isLinked);
    130121        m_isLinked = false;
    131         m_rawBuffer = fastRealloc(m_rawBuffer, sizeof(LinkingData) + s_offsetTableSize);
     122        m_rawBuffer = static_cast<uint8_t*>(fastRealloc(m_rawBuffer, sizeof(LinkingData) + offsetTableSize()));
    132123        return;
    133124    }
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r243254 r245669  
    181181const FirstArgumentOffset = ThisArgumentOffset + SlotSize
    182182const CallFrameHeaderSize = ThisArgumentOffset
     183
     184const MetadataOffsetTable16Offset = 0
     185const MetadataOffsetTable32Offset = constexpr UnlinkedMetadataTable::s_offset16TableSize
    183186
    184187# Some value representation constants.
     
    337340
    338341macro metadata(size, opcode, dst, scratch)
    339     loadi constexpr %opcode%::opcodeID * 4[metadataTable], dst # offset = metadataTable<unsigned*>[opcodeID]
     342    loadh (constexpr %opcode%::opcodeID * 2 + MetadataOffsetTable16Offset)[metadataTable], dst # offset = metadataTable<uint16_t*>[opcodeID]
     343    btinz dst, .setUpOffset
     344    loadi (constexpr %opcode%::opcodeID * 4 + MetadataOffsetTable32Offset)[metadataTable], dst # offset = metadataTable<uint32_t*>[opcodeID]
     345.setUpOffset:
    340346    getu(size, opcode, m_metadataID, scratch) # scratch = bytecode.m_metadataID
    341347    muli sizeof %opcode%::Metadata, scratch # scratch *= sizeof(Op::Metadata)
  • trunk/Source/JavaScriptCore/runtime/CachedTypes.cpp

    r245563 r245669  
    13491349        if (!m_hasMetadata)
    13501350            return;
    1351         for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
    1352             m_metadata[i] = metadataTable.buffer()[i];
     1351        m_is32Bit = metadataTable.m_is32Bit;
     1352        if (m_is32Bit) {
     1353            for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
     1354                m_metadata[i] = metadataTable.offsetTable32()[i];
     1355        } else {
     1356            for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
     1357                m_metadata[i] = metadataTable.offsetTable16()[i];
     1358        }
    13531359    }
    13541360
    13551361    Ref<UnlinkedMetadataTable> decode(Decoder&) const
    13561362    {
    1357         Ref<UnlinkedMetadataTable> metadataTable = UnlinkedMetadataTable::create();
     1363        Ref<UnlinkedMetadataTable> metadataTable = UnlinkedMetadataTable::create(m_is32Bit);
    13581364        metadataTable->m_isFinalized = true;
    13591365        metadataTable->m_isLinked = false;
    13601366        metadataTable->m_hasMetadata = m_hasMetadata;
    1361         for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
    1362             metadataTable->buffer()[i] = m_metadata[i];
     1367        if (m_is32Bit) {
     1368            for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
     1369                metadataTable->offsetTable32()[i] = m_metadata[i];
     1370        } else {
     1371            for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
     1372                metadataTable->offsetTable16()[i] = m_metadata[i];
     1373        }
    13631374        return metadataTable;
    13641375    }
     
    13661377private:
    13671378    bool m_hasMetadata;
     1379    bool m_is32Bit;
    13681380    std::array<unsigned, UnlinkedMetadataTable::s_offsetTableEntries> m_metadata;
    13691381};
Note: See TracChangeset for help on using the changeset viewer.