/ bytecode / MetadataTable.h
MetadataTable.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 "Instruction.h"
 29  #include "Opcode.h"
 30  #include "UnlinkedMetadataTable.h"
 31  #include <wtf/RefCounted.h>
 32  
 33  namespace JSC {
 34  
 35  class CodeBlock;
 36  
 37  // MetadataTable has a bit strange memory layout for LLInt optimization.
 38  // [UnlinkedMetadataTable::LinkingData][MetadataTable]
 39  //                                     ^
 40  //                 The pointer of MetadataTable points at this address.
 41  class MetadataTable {
 42      WTF_MAKE_FAST_ALLOCATED;
 43      WTF_MAKE_NONCOPYABLE(MetadataTable);
 44      friend class LLIntOffsetsExtractor;
 45      friend class UnlinkedMetadataTable;
 46  public:
 47      ~MetadataTable();
 48  
 49      ALWAYS_INLINE Instruction::Metadata* get(OpcodeID opcodeID)
 50      {
 51          ASSERT(opcodeID < NUMBER_OF_BYTECODE_WITH_METADATA);
 52          return reinterpret_cast<Instruction::Metadata*>(getImpl(opcodeID));
 53      }
 54  
 55      template<typename Op, typename Functor>
 56      ALWAYS_INLINE void forEach(const Functor& func)
 57      {
 58          auto* metadata = bitwise_cast<typename Op::Metadata*>(get(Op::opcodeID));
 59          auto* end = bitwise_cast<typename Op::Metadata*>(getImpl(Op::opcodeID + 1));
 60          for (; metadata + 1 <= end; ++metadata)
 61              func(*metadata);
 62      }
 63  
 64      size_t sizeInBytes();
 65  
 66      void ref()
 67      {
 68          ++linkingData().refCount;
 69      }
 70  
 71      void deref()
 72      {
 73          unsigned tempRefCount = linkingData().refCount - 1;
 74          if (!tempRefCount) {
 75              MetadataTable::destroy(this);
 76              return;
 77          }
 78          linkingData().refCount = tempRefCount;
 79      }
 80  
 81      unsigned refCount() const
 82      {
 83          return linkingData().refCount;
 84      }
 85  
 86      unsigned hasOneRef() const
 87      {
 88          return refCount() == 1;
 89      }
 90  
 91  private:
 92      MetadataTable(UnlinkedMetadataTable&);
 93  
 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  
102      UnlinkedMetadataTable::LinkingData& linkingData() const
103      {
104          return *bitwise_cast<UnlinkedMetadataTable::LinkingData*>((bitwise_cast<uint8_t*>(this) - sizeof(UnlinkedMetadataTable::LinkingData)));
105      }
106  
107      void* buffer() { return this; }
108  
109      bool is32Bit() const { return !offsetTable16()[0]; }
110  
111      ALWAYS_INLINE unsigned getOffset(unsigned i) const
112      {
113          unsigned offset = offsetTable16()[i];
114          if (offset)
115              return offset;
116          return offsetTable32()[i];
117      }
118  
119      ALWAYS_INLINE uint8_t* getImpl(unsigned i)
120      {
121          return bitwise_cast<uint8_t*>(this) + getOffset(i);
122      }
123  
124      static void destroy(MetadataTable*);
125  };
126  
127  } // namespace JSC