/ runtime / CachedTypes.cpp
CachedTypes.cpp
   1  /*
   2   * Copyright (C) 2019-2020 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  #include "config.h"
  27  #include "CachedTypes.h"
  28  
  29  #include "BuiltinNames.h"
  30  #include "BytecodeCacheError.h"
  31  #include "BytecodeLivenessAnalysis.h"
  32  #include "JSCInlines.h"
  33  #include "JSImmutableButterfly.h"
  34  #include "JSTemplateObjectDescriptor.h"
  35  #include "ScopedArgumentsTable.h"
  36  #include "SourceCodeKey.h"
  37  #include "SourceProvider.h"
  38  #include "UnlinkedEvalCodeBlock.h"
  39  #include "UnlinkedFunctionCodeBlock.h"
  40  #include "UnlinkedMetadataTableInlines.h"
  41  #include "UnlinkedModuleProgramCodeBlock.h"
  42  #include "UnlinkedProgramCodeBlock.h"
  43  #include <wtf/MallocPtr.h>
  44  #include <wtf/Optional.h>
  45  #include <wtf/Packed.h>
  46  #include <wtf/UUID.h>
  47  #include <wtf/text/AtomStringImpl.h>
  48  
  49  namespace JSC {
  50  
  51  namespace Yarr {
  52  enum class Flags : uint8_t;
  53  }
  54  
  55  template <typename T, typename = void>
  56  struct SourceTypeImpl {
  57      using type = T;
  58  };
  59  
  60  template<typename T>
  61  struct SourceTypeImpl<T, std::enable_if_t<!std::is_fundamental<T>::value && !std::is_same<typename T::SourceType_, void>::value>> {
  62      using type = typename T::SourceType_;
  63  
  64  };
  65  
  66  template<typename T>
  67  using SourceType = typename SourceTypeImpl<T>::type;
  68  
  69  static constexpr unsigned jscBytecodeCacheVersion()
  70  {
  71      return StringHasher::computeHash(__TIMESTAMP__);
  72  }
  73  
  74  class Encoder {
  75      WTF_MAKE_NONCOPYABLE(Encoder);
  76      WTF_FORBID_HEAP_ALLOCATION;
  77  
  78  public:
  79      class Allocation {
  80          friend class Encoder;
  81  
  82      public:
  83          uint8_t* buffer() const { return m_buffer; }
  84          ptrdiff_t offset() const { return m_offset; }
  85  
  86      private:
  87          Allocation(uint8_t* buffer, ptrdiff_t offset)
  88              : m_buffer(buffer)
  89              , m_offset(offset)
  90          {
  91          }
  92  
  93          uint8_t* m_buffer;
  94          ptrdiff_t m_offset;
  95      };
  96  
  97      Encoder(VM& vm, FileSystem::PlatformFileHandle fd = FileSystem::invalidPlatformFileHandle)
  98          : m_vm(vm)
  99          , m_fd(fd)
 100          , m_baseOffset(0)
 101          , m_currentPage(nullptr)
 102      {
 103          allocateNewPage();
 104      }
 105  
 106      VM& vm() { return m_vm; }
 107  
 108      Allocation malloc(unsigned size)
 109      {
 110          RELEASE_ASSERT(size);
 111          ptrdiff_t offset;
 112          if (m_currentPage->malloc(size, offset))
 113              return Allocation { m_currentPage->buffer() + offset, m_baseOffset + offset };
 114          allocateNewPage(size);
 115          return malloc(size);
 116      }
 117  
 118      template<typename T, typename... Args>
 119      T* malloc(Args&&... args)
 120      {
 121          return new (malloc(sizeof(T)).buffer()) T(std::forward<Args>(args)...);
 122      }
 123  
 124      ptrdiff_t offsetOf(const void* address)
 125      {
 126          ptrdiff_t offset;
 127          ptrdiff_t baseOffset = 0;
 128          for (const auto& page : m_pages) {
 129              if (page.getOffset(address, offset))
 130                  return baseOffset + offset;
 131              baseOffset += page.size();
 132          }
 133          RELEASE_ASSERT_NOT_REACHED();
 134          return 0;
 135      }
 136  
 137      void cachePtr(const void* ptr, ptrdiff_t offset)
 138      {
 139          m_ptrToOffsetMap.add(ptr, offset);
 140      }
 141  
 142      Optional<ptrdiff_t> cachedOffsetForPtr(const void* ptr)
 143      {
 144          auto it = m_ptrToOffsetMap.find(ptr);
 145          if (it == m_ptrToOffsetMap.end())
 146              return WTF::nullopt;
 147          return { it->value };
 148      }
 149  
 150      void addLeafExecutable(const UnlinkedFunctionExecutable* executable, ptrdiff_t offset)
 151      {
 152          m_leafExecutables.add(executable, offset);
 153      }
 154  
 155      RefPtr<CachedBytecode> release(BytecodeCacheError& error)
 156      {
 157          if (!m_currentPage)
 158              return nullptr;
 159          m_currentPage->alignEnd();
 160  
 161          if (FileSystem::isHandleValid(m_fd)) {
 162              return releaseMapped(error);
 163          }
 164  
 165          size_t size = m_baseOffset + m_currentPage->size();
 166          MallocPtr<uint8_t, VMMalloc> buffer = MallocPtr<uint8_t, VMMalloc>::malloc(size);
 167          unsigned offset = 0;
 168          for (const auto& page : m_pages) {
 169              memcpy(buffer.get() + offset, page.buffer(), page.size());
 170              offset += page.size();
 171          }
 172          RELEASE_ASSERT(offset == size);
 173          return CachedBytecode::create(WTFMove(buffer), size, WTFMove(m_leafExecutables));
 174      }
 175  
 176  private:
 177      RefPtr<CachedBytecode> releaseMapped(BytecodeCacheError& error)
 178      {
 179          size_t size = m_baseOffset + m_currentPage->size();
 180          if (!FileSystem::truncateFile(m_fd, size)) {
 181              error = BytecodeCacheError::StandardError(errno);
 182              return nullptr;
 183          }
 184  
 185          for (const auto& page : m_pages) {
 186              int bytesWritten = FileSystem::writeToFile(m_fd, reinterpret_cast<char*>(page.buffer()), page.size());
 187              if (bytesWritten == -1) {
 188                  error = BytecodeCacheError::StandardError(errno);
 189                  return nullptr;
 190              }
 191  
 192              if (static_cast<size_t>(bytesWritten) != page.size()) {
 193                  error = BytecodeCacheError::WriteError(bytesWritten, page.size());
 194                  return nullptr;
 195              }
 196          }
 197  
 198          bool success;
 199          FileSystem::MappedFileData mappedFileData(m_fd, FileSystem::MappedFileMode::Private, success);
 200          if (!success) {
 201              error = BytecodeCacheError::StandardError(errno);
 202              return nullptr;
 203          }
 204  
 205          return CachedBytecode::create(WTFMove(mappedFileData), WTFMove(m_leafExecutables));
 206      }
 207  
 208      class Page {
 209      public:
 210          Page(size_t size)
 211              : m_buffer(MallocPtr<uint8_t, VMMalloc>::malloc(size))
 212              , m_capacity(size)
 213          {
 214          }
 215  
 216          bool malloc(size_t size, ptrdiff_t& result)
 217          {
 218              size_t alignment = std::min(alignof(std::max_align_t), static_cast<size_t>(WTF::roundUpToPowerOfTwo(size)));
 219              ptrdiff_t offset = roundUpToMultipleOf(alignment, m_offset);
 220              size = roundUpToMultipleOf(alignment, size);
 221              if (static_cast<size_t>(offset + size) > m_capacity)
 222                  return false;
 223  
 224              result = offset;
 225              m_offset = offset + size;
 226              return true;
 227          }
 228  
 229          uint8_t* buffer() const { return m_buffer.get(); }
 230          size_t size() const { return static_cast<size_t>(m_offset); }
 231  
 232          bool getOffset(const void* address, ptrdiff_t& result) const
 233          {
 234              const uint8_t* addr = static_cast<const uint8_t*>(address);
 235              if (addr >= m_buffer.get() && addr < m_buffer.get() + m_offset) {
 236                  result = addr - m_buffer.get();
 237                  return true;
 238              }
 239              return false;
 240          }
 241  
 242          void alignEnd()
 243          {
 244              ptrdiff_t size = roundUpToMultipleOf(alignof(std::max_align_t), m_offset);
 245              if (size == m_offset)
 246                  return;
 247              RELEASE_ASSERT(static_cast<size_t>(size) <= m_capacity);
 248              m_offset = size;
 249          }
 250  
 251      private:
 252          MallocPtr<uint8_t, VMMalloc> m_buffer;
 253          ptrdiff_t m_offset { 0 };
 254          size_t m_capacity;
 255      };
 256  
 257      void allocateNewPage(size_t size = 0)
 258      {
 259          static size_t minPageSize = pageSize();
 260          if (m_currentPage) {
 261              m_currentPage->alignEnd();
 262              m_baseOffset += m_currentPage->size();
 263          }
 264          if (size < minPageSize)
 265              size = minPageSize;
 266          else
 267              size = roundUpToMultipleOf(minPageSize, size);
 268          m_pages.append(Page { size });
 269          m_currentPage = &m_pages.last();
 270      }
 271  
 272      VM& m_vm;
 273      FileSystem::PlatformFileHandle m_fd;
 274      ptrdiff_t m_baseOffset;
 275      Page* m_currentPage;
 276      Vector<Page> m_pages;
 277      HashMap<const void*, ptrdiff_t> m_ptrToOffsetMap;
 278      LeafExecutableMap m_leafExecutables;
 279  };
 280  
 281  Decoder::Decoder(VM& vm, Ref<CachedBytecode> cachedBytecode, RefPtr<SourceProvider> provider)
 282      : m_vm(vm)
 283      , m_cachedBytecode(WTFMove(cachedBytecode))
 284      , m_provider(provider)
 285  {
 286  }
 287  
 288  Decoder::~Decoder()
 289  {
 290      for (auto& finalizer : m_finalizers)
 291          finalizer();
 292  }
 293  
 294  Ref<Decoder> Decoder::create(VM& vm, Ref<CachedBytecode> cachedBytecode, RefPtr<SourceProvider> provider)
 295  {
 296      return adoptRef(*new Decoder(vm, WTFMove(cachedBytecode), WTFMove(provider)));
 297  }
 298  
 299  size_t Decoder::size() const
 300  {
 301      return m_cachedBytecode->size();
 302  }
 303  
 304  ptrdiff_t Decoder::offsetOf(const void* ptr)
 305  {
 306      const uint8_t* addr = static_cast<const uint8_t*>(ptr);
 307      ASSERT(addr >= m_cachedBytecode->data() && addr < m_cachedBytecode->data() + m_cachedBytecode->size());
 308      return addr - m_cachedBytecode->data();
 309  }
 310  
 311  void Decoder::cacheOffset(ptrdiff_t offset, void* ptr)
 312  {
 313      m_offsetToPtrMap.add(offset, ptr);
 314  }
 315  
 316  WTF::Optional<void*> Decoder::cachedPtrForOffset(ptrdiff_t offset)
 317  {
 318      auto it = m_offsetToPtrMap.find(offset);
 319      if (it == m_offsetToPtrMap.end())
 320          return WTF::nullopt;
 321      return { it->value };
 322  }
 323  
 324  const void* Decoder::ptrForOffsetFromBase(ptrdiff_t offset)
 325  {
 326      ASSERT(offset > 0 && static_cast<size_t>(offset) < m_cachedBytecode->size());
 327      return m_cachedBytecode->data() + offset;
 328  }
 329  
 330  CompactTDZEnvironmentMap::Handle Decoder::handleForTDZEnvironment(CompactTDZEnvironment* environment) const
 331  {
 332      auto it = m_environmentToHandleMap.find(environment);
 333      RELEASE_ASSERT(it != m_environmentToHandleMap.end());
 334      return it->value;
 335  }
 336  
 337  void Decoder::setHandleForTDZEnvironment(CompactTDZEnvironment* environment, const CompactTDZEnvironmentMap::Handle& handle)
 338  {
 339      auto addResult = m_environmentToHandleMap.add(environment, handle);
 340      RELEASE_ASSERT(addResult.isNewEntry);
 341  }
 342  
 343  void Decoder::addLeafExecutable(const UnlinkedFunctionExecutable* executable, ptrdiff_t offset)
 344  {
 345      m_cachedBytecode->leafExecutables().add(executable, offset);
 346  }
 347  
 348  template<typename Functor>
 349  void Decoder::addFinalizer(const Functor& fn)
 350  {
 351      m_finalizers.append(fn);
 352  }
 353  
 354  RefPtr<SourceProvider> Decoder::provider() const
 355  {
 356      return m_provider;
 357  }
 358  
 359  template<typename T>
 360  static std::enable_if_t<std::is_same<T, SourceType<T>>::value> encode(Encoder&, T& dst, const SourceType<T>& src)
 361  {
 362      dst = src;
 363  }
 364  
 365  template<typename T>
 366  static std::enable_if_t<!std::is_same<T, SourceType<T>>::value> encode(Encoder& encoder, T& dst, const SourceType<T>& src)
 367  {
 368      dst.encode(encoder, src);
 369  }
 370  
 371  template<typename T, typename... Args>
 372  static std::enable_if_t<std::is_same<T, SourceType<T>>::value> decode(Decoder&, const T& src, SourceType<T>& dst, Args...)
 373  {
 374      dst = src;
 375  }
 376  
 377  template<typename T, typename... Args>
 378  static std::enable_if_t<!std::is_same<T, SourceType<T>>::value> decode(Decoder& decoder, const T& src, SourceType<T>& dst, Args... args)
 379  {
 380      src.decode(decoder, dst, args...);
 381  }
 382  
 383  template<typename T>
 384  static std::enable_if_t<std::is_same<T, SourceType<T>>::value, T> decode(Decoder&, T src)
 385  {
 386      return src;
 387  }
 388  
 389  template<typename T>
 390  static std::enable_if_t<!std::is_same<T, SourceType<T>>::value, SourceType<T>>&& decode(Decoder& decoder, const T& src)
 391  {
 392      return src.decode(decoder);
 393  }
 394  
 395  template<typename Source>
 396  class CachedObject {
 397      WTF_MAKE_NONCOPYABLE(CachedObject<Source>);
 398  
 399  public:
 400      using SourceType_ = Source;
 401  
 402      CachedObject() = default;
 403  
 404      inline void* operator new(size_t, void* where) { return where; }
 405      void* operator new[](size_t, void* where) { return where; }
 406  
 407      // Copied from WTF_FORBID_HEAP_ALLOCATION, since we only want to allow placement new
 408      void* operator new(size_t) = delete;
 409      void operator delete(void*) = delete;
 410      void* operator new[](size_t size) = delete;
 411      void operator delete[](void*) = delete;
 412      void* operator new(size_t, NotNullTag, void* location) = delete;
 413  };
 414  
 415  template<typename Source>
 416  class VariableLengthObject : public CachedObject<Source>, VariableLengthObjectBase {
 417      template<typename, typename>
 418      friend class CachedPtr;
 419      friend struct CachedPtrOffsets;
 420  
 421  public:
 422      VariableLengthObject()
 423          : VariableLengthObjectBase(s_invalidOffset)
 424      {
 425      }
 426  
 427      bool isEmpty() const
 428      {
 429          return m_offset == s_invalidOffset;
 430      }
 431  
 432  protected:
 433      const uint8_t* buffer() const
 434      {
 435          ASSERT(!isEmpty());
 436          return bitwise_cast<const uint8_t*>(this) + m_offset;
 437      }
 438  
 439      template<typename T>
 440      const T* buffer() const
 441      {
 442          ASSERT(!(bitwise_cast<uintptr_t>(buffer()) % alignof(T)));
 443          return bitwise_cast<const T*>(buffer());
 444      }
 445  
 446      uint8_t* allocate(Encoder& encoder, size_t size)
 447      {
 448          ptrdiff_t offsetOffset = encoder.offsetOf(&m_offset);
 449          auto result = encoder.malloc(size);
 450          m_offset = result.offset() - offsetOffset;
 451          return result.buffer();
 452      }
 453  
 454      template<typename T>
 455  #if CPU(ARM64) && CPU(ADDRESS32)
 456      // FIXME: Remove this once it's no longer needed and LLVM doesn't miscompile us:
 457      // <rdar://problem/49792205>
 458      __attribute__((optnone))
 459  #endif
 460      T* allocate(Encoder& encoder, unsigned size = 1)
 461      {
 462          uint8_t* result = allocate(encoder, sizeof(T) * size);
 463          ASSERT(!(bitwise_cast<uintptr_t>(result) % alignof(T)));
 464          return new (result) T[size];
 465      }
 466  
 467  private:
 468      constexpr static ptrdiff_t s_invalidOffset = std::numeric_limits<ptrdiff_t>::max();
 469  };
 470  
 471  template<typename T, typename Source = SourceType<T>>
 472  class CachedPtr : public VariableLengthObject<Source*> {
 473      template<typename, typename, typename>
 474      friend class CachedRefPtr;
 475  
 476      friend struct CachedPtrOffsets;
 477  
 478  public:
 479      void encode(Encoder& encoder, const Source* src)
 480      {
 481          if (!src)
 482              return;
 483  
 484          if (Optional<ptrdiff_t> offset = encoder.cachedOffsetForPtr(src)) {
 485              this->m_offset = *offset - encoder.offsetOf(&this->m_offset);
 486              return;
 487          }
 488  
 489          T* cachedObject = this->template allocate<T>(encoder);
 490          cachedObject->encode(encoder, *src);
 491          encoder.cachePtr(src, encoder.offsetOf(cachedObject));
 492      }
 493  
 494      template<typename... Args>
 495      Source* decode(Decoder& decoder, bool& isNewAllocation, Args&&... args) const
 496      {
 497          if (this->isEmpty()) {
 498              isNewAllocation = false;
 499              return nullptr;
 500          }
 501  
 502          ptrdiff_t bufferOffset = decoder.offsetOf(this->buffer());
 503          if (Optional<void*> ptr = decoder.cachedPtrForOffset(bufferOffset)) {
 504              isNewAllocation = false;
 505              return static_cast<Source*>(*ptr);
 506          }
 507  
 508          isNewAllocation = true;
 509          Source* ptr = get()->decode(decoder, std::forward<Args>(args)...);
 510          decoder.cacheOffset(bufferOffset, ptr);
 511          return ptr;
 512      }
 513  
 514      template<typename... Args>
 515      Source* decode(Decoder& decoder, Args&&... args) const
 516      {
 517          bool unusedIsNewAllocation;
 518          return decode(decoder, unusedIsNewAllocation, std::forward<Args>(args)...);
 519      }
 520  
 521      const T* operator->() const { return get(); }
 522  
 523  private:
 524      const T* get() const
 525      {
 526          RELEASE_ASSERT(!this->isEmpty());
 527          return this->template buffer<T>();
 528      }
 529  };
 530  
 531  ptrdiff_t CachedPtrOffsets::offsetOffset()
 532  {
 533      return OBJECT_OFFSETOF(CachedPtr<void>, m_offset);
 534  }
 535  
 536  template<typename T, typename Source = SourceType<T>, typename PtrTraits = RawPtrTraits<Source>>
 537  class CachedRefPtr : public CachedObject<RefPtr<Source, PtrTraits>> {
 538  public:
 539      void encode(Encoder& encoder, const Source* src)
 540      {
 541          m_ptr.encode(encoder, src);
 542      }
 543  
 544      void encode(Encoder& encoder, const RefPtr<Source, PtrTraits> src)
 545      {
 546          encode(encoder, src.get());
 547      }
 548  
 549      RefPtr<Source, PtrTraits> decode(Decoder& decoder) const
 550      {
 551          bool isNewAllocation;
 552          Source* decodedPtr = m_ptr.decode(decoder, isNewAllocation);
 553          if (!decodedPtr)
 554              return nullptr;
 555          if (isNewAllocation) {
 556              decoder.addFinalizer([=] {
 557                  WTF::DefaultRefDerefTraits<Source>::derefIfNotNull(decodedPtr);
 558              });
 559          }
 560          auto result = adoptRef<Source, PtrTraits>(decodedPtr);
 561          result->ref();
 562          return result;
 563      }
 564  
 565      void decode(Decoder& decoder, RefPtr<Source, PtrTraits>& src) const
 566      {
 567          src = decode(decoder);
 568      }
 569  
 570  private:
 571      CachedPtr<T, Source> m_ptr;
 572  };
 573  
 574  template<typename T, typename Source = SourceType<T>>
 575  class CachedWriteBarrier : public CachedObject<WriteBarrier<Source>> {
 576      friend struct CachedWriteBarrierOffsets;
 577  
 578  public:
 579      bool isEmpty() const { return m_ptr.isEmpty(); }
 580  
 581      void encode(Encoder& encoder, const WriteBarrier<Source> src)
 582      {
 583          m_ptr.encode(encoder, src.get());
 584      }
 585  
 586      void decode(Decoder& decoder, WriteBarrier<Source>& src, const JSCell* owner) const
 587      {
 588          Source* decodedPtr = m_ptr.decode(decoder);
 589          if (decodedPtr)
 590              src.set(decoder.vm(), owner, decodedPtr);
 591      }
 592  
 593  private:
 594      CachedPtr<T, Source> m_ptr;
 595  };
 596  
 597  ptrdiff_t CachedWriteBarrierOffsets::ptrOffset()
 598  {
 599      return OBJECT_OFFSETOF(CachedWriteBarrier<void>, m_ptr);
 600  }
 601  
 602  template<typename T, size_t InlineCapacity = 0, typename OverflowHandler = CrashOnOverflow, typename Malloc = WTF::VectorMalloc>
 603  class CachedVector : public VariableLengthObject<Vector<SourceType<T>, InlineCapacity, OverflowHandler, 16, Malloc>> {
 604  public:
 605      void encode(Encoder& encoder, const Vector<SourceType<T>, InlineCapacity, OverflowHandler, 16, Malloc>& vector)
 606      {
 607          m_size = vector.size();
 608          if (!m_size)
 609              return;
 610          T* buffer = this->template allocate<T>(encoder, m_size);
 611          for (unsigned i = 0; i < m_size; ++i)
 612              ::JSC::encode(encoder, buffer[i], vector[i]);
 613      }
 614  
 615      void encode(Encoder& encoder, const RefCountedArray<SourceType<T>>& vector)
 616      {
 617          m_size = vector.size();
 618          if (!m_size)
 619              return;
 620          T* buffer = this->template allocate<T>(encoder, m_size);
 621          for (unsigned i = 0; i < m_size; ++i)
 622              ::JSC::encode(encoder, buffer[i], vector[i]);
 623      }
 624  
 625      template<typename... Args>
 626      void decode(Decoder& decoder, Vector<SourceType<T>, InlineCapacity, OverflowHandler, 16, Malloc>& vector, Args... args) const
 627      {
 628          if (!m_size)
 629              return;
 630          vector.resizeToFit(m_size);
 631          const T* buffer = this->template buffer<T>();
 632          for (unsigned i = 0; i < m_size; ++i)
 633              ::JSC::decode(decoder, buffer[i], vector[i], args...);
 634      }
 635  
 636      template<typename... Args>
 637      void decode(Decoder& decoder, RefCountedArray<SourceType<T>>& vector, Args... args) const
 638      {
 639          if (!m_size)
 640              return;
 641          vector = RefCountedArray<SourceType<T>>(m_size);
 642          const T* buffer = this->template buffer<T>();
 643          for (unsigned i = 0; i < m_size; ++i)
 644              ::JSC::decode(decoder, buffer[i], vector[i], args...);
 645      }
 646  
 647  
 648  private:
 649      unsigned m_size;
 650  };
 651  
 652  template<typename First, typename Second>
 653  class CachedPair : public CachedObject<std::pair<SourceType<First>, SourceType<Second>>> {
 654  public:
 655      void encode(Encoder& encoder, const std::pair<SourceType<First>, SourceType<Second>>& pair)
 656      {
 657          ::JSC::encode(encoder, m_first, pair.first);
 658          ::JSC::encode(encoder, m_second, pair.second);
 659      }
 660  
 661      void decode(Decoder& decoder, std::pair<SourceType<First>, SourceType<Second>>& pair) const
 662      {
 663          ::JSC::decode(decoder, m_first, pair.first);
 664          ::JSC::decode(decoder, m_second, pair.second);
 665      }
 666  
 667  private:
 668      First m_first;
 669      Second m_second;
 670  };
 671  
 672  template<typename Key, typename Value, typename HashArg = DefaultHash<SourceType<Key>>, typename KeyTraitsArg = HashTraits<SourceType<Key>>, typename MappedTraitsArg = HashTraits<SourceType<Value>>>
 673  class CachedHashMap : public VariableLengthObject<HashMap<SourceType<Key>, SourceType<Value>, HashArg, KeyTraitsArg, MappedTraitsArg>> {
 674      template<typename K, typename V>
 675      using Map = HashMap<K, V, HashArg, KeyTraitsArg, MappedTraitsArg>;
 676  
 677  public:
 678      void encode(Encoder& encoder, const Map<SourceType<Key>, SourceType<Value>>& map)
 679      {
 680          SourceType<decltype(m_entries)> entriesVector(map.size());
 681          unsigned i = 0;
 682          for (const auto& it : map)
 683              entriesVector[i++] = { it.key, it.value };
 684          m_entries.encode(encoder, entriesVector);
 685      }
 686  
 687      void decode(Decoder& decoder, Map<SourceType<Key>, SourceType<Value>>& map) const
 688      {
 689          SourceType<decltype(m_entries)> decodedEntries;
 690          m_entries.decode(decoder, decodedEntries);
 691          for (const auto& pair : decodedEntries)
 692              map.set(pair.first, pair.second);
 693      }
 694  
 695  private:
 696      CachedVector<CachedPair<Key, Value>> m_entries;
 697  };
 698  
 699  template<typename T>
 700  class CachedUniquedStringImplBase : public VariableLengthObject<T> {
 701  public:
 702      void encode(Encoder& encoder, const StringImpl& string)
 703      {
 704          m_isAtomic = string.isAtom();
 705          m_isSymbol = string.isSymbol();
 706          m_isRegistered = false;
 707          m_isWellKnownSymbol = false;
 708          m_isPrivate = false;
 709          RefPtr<StringImpl> impl = const_cast<StringImpl*>(&string);
 710  
 711          if (m_isSymbol) {
 712              SymbolImpl* symbol = static_cast<SymbolImpl*>(impl.get());
 713              m_isRegistered = symbol->isRegistered();
 714              m_isPrivate = symbol->isPrivate();
 715              if (!symbol->isNullSymbol()) {
 716                  // We have special handling for well-known symbols.
 717                  if (!m_isPrivate) {
 718                      m_isWellKnownSymbol = true;
 719                      impl = symbol->substring(strlen("Symbol."));
 720                  }
 721              }
 722          }
 723  
 724          m_is8Bit = impl->is8Bit();
 725          m_length = impl->length();
 726  
 727          if (!m_length)
 728              return;
 729  
 730          unsigned size = m_length;
 731          const void* payload;
 732          if (m_is8Bit)
 733              payload = impl->characters8();
 734          else {
 735              payload = impl->characters16();
 736              size *= 2;
 737          }
 738  
 739          uint8_t* buffer = this->allocate(encoder, size);
 740          memcpy(buffer, payload, size);
 741      }
 742  
 743      UniquedStringImpl* decode(Decoder& decoder) const
 744      {
 745          auto create = [&](const auto* buffer) -> UniquedStringImpl* {
 746              if (!m_isSymbol)
 747                  return AtomStringImpl::add(buffer, m_length).leakRef();
 748  
 749              SymbolImpl* symbol;
 750              VM& vm = decoder.vm();
 751              if (m_isRegistered) {
 752                  String str(buffer, m_length);
 753                  if (m_isPrivate)
 754                      symbol = static_cast<SymbolImpl*>(&vm.privateSymbolRegistry().symbolForKey(str).leakRef());
 755                  else
 756                      symbol = static_cast<SymbolImpl*>(&vm.symbolRegistry().symbolForKey(str).leakRef());
 757              } else if (m_isWellKnownSymbol)
 758                  symbol = vm.propertyNames->builtinNames().lookUpWellKnownSymbol(buffer, m_length);
 759              else
 760                  symbol = vm.propertyNames->builtinNames().lookUpPrivateName(buffer, m_length);
 761              RELEASE_ASSERT(symbol);
 762              String str = symbol;
 763              StringImpl* impl = str.releaseImpl().get();
 764              ASSERT(impl->isSymbol());
 765              if (m_isWellKnownSymbol)
 766                  ASSERT(!static_cast<SymbolImpl*>(impl)->isPrivate());
 767              else
 768                  ASSERT(static_cast<SymbolImpl*>(impl)->isPrivate());
 769              return static_cast<UniquedStringImpl*>(impl);
 770          };
 771  
 772          if (!m_length) {
 773              if (m_isSymbol)
 774                  return &SymbolImpl::createNullSymbol().leakRef();
 775              return AtomStringImpl::add("").leakRef();
 776          }
 777  
 778          if (m_is8Bit)
 779              return create(this->template buffer<LChar>());
 780          return create(this->template buffer<UChar>());
 781      }
 782  
 783  private:
 784      bool m_is8Bit : 1;
 785      bool m_isSymbol : 1;
 786      bool m_isWellKnownSymbol : 1;
 787      bool m_isAtomic : 1;
 788      bool m_isRegistered : 1;
 789      bool m_isPrivate : 1;
 790      unsigned m_length;
 791  };
 792  
 793  class CachedUniquedStringImpl : public CachedUniquedStringImplBase<UniquedStringImpl> { };
 794  class CachedStringImpl : public CachedUniquedStringImplBase<StringImpl> { };
 795  
 796  class CachedString : public VariableLengthObject<String> {
 797  public:
 798      void encode(Encoder& encoder, const String& string)
 799      {
 800          m_impl.encode(encoder, static_cast<UniquedStringImpl*>(string.impl()));
 801      }
 802  
 803      String decode(Decoder& decoder) const
 804      {
 805          return String(static_cast<RefPtr<StringImpl>>(m_impl.decode(decoder)));
 806      }
 807  
 808      void decode(Decoder& decoder, String& dst) const
 809      {
 810          dst = decode(decoder);
 811      }
 812  
 813  private:
 814      CachedRefPtr<CachedUniquedStringImpl> m_impl;
 815  };
 816  
 817  class CachedIdentifier : public VariableLengthObject<Identifier> {
 818  public:
 819      void encode(Encoder& encoder, const Identifier& identifier)
 820      {
 821          m_string.encode(encoder, identifier.string());
 822      }
 823  
 824      Identifier decode(Decoder& decoder) const
 825      {
 826          String str = m_string.decode(decoder);
 827          if (str.isNull())
 828              return Identifier();
 829  
 830          return Identifier::fromUid(decoder.vm(), (UniquedStringImpl*)str.impl());
 831      }
 832  
 833      void decode(Decoder& decoder, Identifier& ident) const
 834      {
 835          ident = decode(decoder);
 836      }
 837  
 838  private:
 839      CachedString m_string;
 840  };
 841  
 842  template<typename T>
 843  class CachedOptional : public VariableLengthObject<Optional<SourceType<T>>> {
 844  public:
 845      void encode(Encoder& encoder, const Optional<SourceType<T>>& source)
 846      {
 847          if (!source)
 848              return;
 849  
 850          this->template allocate<T>(encoder)->encode(encoder, *source);
 851      }
 852  
 853      Optional<SourceType<T>> decode(Decoder& decoder) const
 854      {
 855          if (this->isEmpty())
 856              return WTF::nullopt;
 857  
 858          return { this->template buffer<T>()->decode(decoder) };
 859      }
 860  
 861      void decode(Decoder& decoder, Optional<SourceType<T>>& dst) const
 862      {
 863          dst = decode(decoder);
 864      }
 865  
 866      void encode(Encoder& encoder, const std::unique_ptr<SourceType<T>>& source)
 867      {
 868          if (!source)
 869              encode(encoder, WTF::nullopt);
 870          else
 871              encode(encoder, { *source });
 872      }
 873  
 874      SourceType<T>* decodeAsPtr(Decoder& decoder) const
 875      {
 876          RELEASE_ASSERT(!this->isEmpty());
 877          return this->template buffer<T>()->decode(decoder);
 878      }
 879  };
 880  
 881  class CachedSimpleJumpTable : public CachedObject<UnlinkedSimpleJumpTable> {
 882  public:
 883      void encode(Encoder& encoder, const UnlinkedSimpleJumpTable& jumpTable)
 884      {
 885          m_min = jumpTable.min;
 886          m_branchOffsets.encode(encoder, jumpTable.branchOffsets);
 887      }
 888  
 889      void decode(Decoder& decoder, UnlinkedSimpleJumpTable& jumpTable) const
 890      {
 891          jumpTable.min = m_min;
 892          m_branchOffsets.decode(decoder, jumpTable.branchOffsets);
 893      }
 894  
 895  private:
 896      int32_t m_min;
 897      CachedVector<int32_t> m_branchOffsets;
 898  };
 899  
 900  class CachedStringJumpTable : public CachedObject<UnlinkedStringJumpTable> {
 901  public:
 902      void encode(Encoder& encoder, const UnlinkedStringJumpTable& jumpTable)
 903      {
 904          m_offsetTable.encode(encoder, jumpTable.offsetTable);
 905      }
 906  
 907      void decode(Decoder& decoder, UnlinkedStringJumpTable& jumpTable) const
 908      {
 909          m_offsetTable.decode(decoder, jumpTable.offsetTable);
 910      }
 911  
 912  private:
 913      CachedHashMap<CachedRefPtr<CachedStringImpl>, UnlinkedStringJumpTable:: OffsetLocation> m_offsetTable;
 914  };
 915  
 916  class CachedBitVector : public VariableLengthObject<BitVector> {
 917  public:
 918      void encode(Encoder& encoder, const BitVector& bitVector)
 919      {
 920          m_numBits = bitVector.size();
 921          if (!m_numBits)
 922              return;
 923          size_t sizeInBytes = BitVector::byteCount(m_numBits);
 924          uint8_t* buffer = this->allocate(encoder, sizeInBytes);
 925          memcpy(buffer, bitVector.bits(), sizeInBytes);
 926      }
 927  
 928      void decode(Decoder&, BitVector& bitVector) const
 929      {
 930          if (!m_numBits)
 931              return;
 932          bitVector.ensureSize(m_numBits);
 933          size_t sizeInBytes = BitVector::byteCount(m_numBits);
 934          memcpy(bitVector.bits(), this->buffer(), sizeInBytes);
 935      }
 936  
 937  private:
 938      size_t m_numBits;
 939  };
 940  
 941  template<typename T, typename HashArg = DefaultHash<T>>
 942  class CachedHashSet : public CachedObject<HashSet<SourceType<T>, HashArg>> {
 943  public:
 944      void encode(Encoder& encoder, const HashSet<SourceType<T>, HashArg>& set)
 945      {
 946          SourceType<decltype(m_entries)> entriesVector(set.size());
 947          unsigned i = 0;
 948          for (const auto& item : set)
 949              entriesVector[i++] = item;
 950          m_entries.encode(encoder, entriesVector);
 951      }
 952  
 953      void decode(Decoder& decoder, HashSet<SourceType<T>, HashArg>& set) const
 954      {
 955          SourceType<decltype(m_entries)> entriesVector;
 956          m_entries.decode(decoder, entriesVector);
 957          for (const auto& item : entriesVector)
 958              set.add(item);
 959      }
 960  
 961  private:
 962      CachedVector<T> m_entries;
 963  };
 964  
 965  class CachedConstantIdentifierSetEntry : public VariableLengthObject<ConstantIdentifierSetEntry> {
 966  public:
 967      void encode(Encoder& encoder, const ConstantIdentifierSetEntry& entry)
 968      {
 969          m_constant = entry.second;
 970          m_set.encode(encoder, entry.first);
 971      }
 972  
 973      void decode(Decoder& decoder, ConstantIdentifierSetEntry& entry) const
 974      {
 975          entry.second = m_constant;
 976          m_set.decode(decoder, entry.first);
 977      }
 978  
 979  private:
 980      unsigned m_constant;
 981      CachedHashSet<CachedRefPtr<CachedUniquedStringImpl>, IdentifierRepHash> m_set;
 982  };
 983  
 984  class CachedCodeBlockRareData : public CachedObject<UnlinkedCodeBlock::RareData> {
 985  public:
 986      void encode(Encoder& encoder, const UnlinkedCodeBlock::RareData& rareData)
 987      {
 988          m_exceptionHandlers.encode(encoder, rareData.m_exceptionHandlers);
 989          m_switchJumpTables.encode(encoder, rareData.m_switchJumpTables);
 990          m_stringSwitchJumpTables.encode(encoder, rareData.m_stringSwitchJumpTables);
 991          m_expressionInfoFatPositions.encode(encoder, rareData.m_expressionInfoFatPositions);
 992          m_typeProfilerInfoMap.encode(encoder, rareData.m_typeProfilerInfoMap);
 993          m_opProfileControlFlowBytecodeOffsets.encode(encoder, rareData.m_opProfileControlFlowBytecodeOffsets);
 994          m_bitVectors.encode(encoder, rareData.m_bitVectors);
 995          m_constantIdentifierSets.encode(encoder, rareData.m_constantIdentifierSets);
 996          m_needsClassFieldInitializer = rareData.m_needsClassFieldInitializer;
 997      }
 998  
 999      UnlinkedCodeBlock::RareData* decode(Decoder& decoder) const
1000      {
1001          UnlinkedCodeBlock::RareData* rareData = new UnlinkedCodeBlock::RareData { };
1002          m_exceptionHandlers.decode(decoder, rareData->m_exceptionHandlers);
1003          m_switchJumpTables.decode(decoder, rareData->m_switchJumpTables);
1004          m_stringSwitchJumpTables.decode(decoder, rareData->m_stringSwitchJumpTables);
1005          m_expressionInfoFatPositions.decode(decoder, rareData->m_expressionInfoFatPositions);
1006          m_typeProfilerInfoMap.decode(decoder, rareData->m_typeProfilerInfoMap);
1007          m_opProfileControlFlowBytecodeOffsets.decode(decoder, rareData->m_opProfileControlFlowBytecodeOffsets);
1008          m_bitVectors.decode(decoder, rareData->m_bitVectors);
1009          m_constantIdentifierSets.decode(decoder, rareData->m_constantIdentifierSets);
1010          rareData->m_needsClassFieldInitializer = m_needsClassFieldInitializer;
1011          return rareData;
1012      }
1013  
1014  private:
1015      CachedVector<UnlinkedHandlerInfo> m_exceptionHandlers;
1016      CachedVector<CachedSimpleJumpTable> m_switchJumpTables;
1017      CachedVector<CachedStringJumpTable> m_stringSwitchJumpTables;
1018      CachedVector<ExpressionRangeInfo::FatPosition> m_expressionInfoFatPositions;
1019      CachedHashMap<unsigned, UnlinkedCodeBlock::RareData::TypeProfilerExpressionRange> m_typeProfilerInfoMap;
1020      CachedVector<InstructionStream::Offset> m_opProfileControlFlowBytecodeOffsets;
1021      CachedVector<CachedBitVector> m_bitVectors;
1022      CachedVector<CachedConstantIdentifierSetEntry> m_constantIdentifierSets;
1023      unsigned m_needsClassFieldInitializer : 1;
1024  };
1025  
1026  class CachedVariableEnvironmentRareData : public CachedObject<VariableEnvironment::RareData> {
1027  public:
1028      void encode(Encoder& encoder, const VariableEnvironment::RareData& rareData)
1029      {
1030          m_privateNames.encode(encoder, rareData.m_privateNames);
1031      }
1032  
1033      void decode(Decoder& decoder, VariableEnvironment::RareData& rareData) const
1034      {
1035          m_privateNames.decode(decoder, rareData.m_privateNames);
1036      }
1037  
1038  private:
1039      CachedHashMap<CachedRefPtr<CachedUniquedStringImpl, UniquedStringImpl, WTF::PackedPtrTraits<UniquedStringImpl>>, PrivateNameEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>, PrivateNameEntryHashTraits> m_privateNames;
1040  };
1041  
1042  class CachedVariableEnvironment : public CachedObject<VariableEnvironment> {
1043  public:
1044      void encode(Encoder& encoder, const VariableEnvironment& env)
1045      {
1046          m_isEverythingCaptured = env.m_isEverythingCaptured;
1047          m_map.encode(encoder, env.m_map);
1048          m_rareData.encode(encoder, env.m_rareData.get());
1049      }
1050  
1051      void decode(Decoder& decoder, VariableEnvironment& env) const
1052      {
1053          env.m_isEverythingCaptured = m_isEverythingCaptured;
1054          m_map.decode(decoder, env.m_map);
1055          if (!m_rareData.isEmpty()) {
1056              env.m_rareData = WTF::makeUnique<VariableEnvironment::RareData>();
1057              m_rareData->decode(decoder, *env.m_rareData);
1058          }
1059      }
1060  
1061  private:
1062      bool m_isEverythingCaptured;
1063      CachedHashMap<CachedRefPtr<CachedUniquedStringImpl, UniquedStringImpl, WTF::PackedPtrTraits<UniquedStringImpl>>, VariableEnvironmentEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>, VariableEnvironmentEntryHashTraits> m_map;
1064      CachedPtr<CachedVariableEnvironmentRareData> m_rareData;
1065  };
1066  
1067  class CachedCompactTDZEnvironment : public CachedObject<CompactTDZEnvironment> {
1068  public:
1069      void encode(Encoder& encoder, const CompactTDZEnvironment& env)
1070      {
1071          if (WTF::holds_alternative<CompactTDZEnvironment::Compact>(env.m_variables))
1072              m_variables.encode(encoder, WTF::get<CompactTDZEnvironment::Compact>(env.m_variables));
1073          else {
1074              CompactTDZEnvironment::Compact compact;
1075              for (auto& key : WTF::get<CompactTDZEnvironment::Inflated>(env.m_variables))
1076                  compact.append(key);
1077              m_variables.encode(encoder, compact);
1078          }
1079          m_hash = env.m_hash;
1080      }
1081  
1082      void decode(Decoder& decoder, CompactTDZEnvironment& env) const
1083      {
1084          {
1085              CompactTDZEnvironment::Compact compact;
1086              m_variables.decode(decoder, compact);
1087              CompactTDZEnvironment::sortCompact(compact);
1088              env.m_variables = CompactTDZEnvironment::Variables(WTFMove(compact));
1089          }
1090          env.m_hash = m_hash;
1091      }
1092  
1093      CompactTDZEnvironment* decode(Decoder& decoder) const
1094      {
1095          CompactTDZEnvironment* env = new CompactTDZEnvironment;
1096          decode(decoder, *env);
1097          return env;
1098      }
1099  
1100  private:
1101      CachedVector<CachedRefPtr<CachedUniquedStringImpl, UniquedStringImpl, WTF::PackedPtrTraits<UniquedStringImpl>>> m_variables;
1102      unsigned m_hash;
1103  };
1104  
1105  class CachedCompactTDZEnvironmentMapHandle : public CachedObject<CompactTDZEnvironmentMap::Handle> {
1106  public:
1107      void encode(Encoder& encoder, const CompactTDZEnvironmentMap::Handle& handle)
1108      {
1109          m_environment.encode(encoder, handle.m_environment);
1110      }
1111  
1112      CompactTDZEnvironmentMap::Handle decode(Decoder& decoder) const
1113      {
1114          bool isNewAllocation;
1115          CompactTDZEnvironment* environment = m_environment.decode(decoder, isNewAllocation);
1116          if (!environment) {
1117              ASSERT(!isNewAllocation);
1118              return CompactTDZEnvironmentMap::Handle();
1119          }
1120  
1121          if (!isNewAllocation)
1122              return decoder.handleForTDZEnvironment(environment);
1123          bool isNewEntry;
1124          CompactTDZEnvironmentMap::Handle handle = decoder.vm().m_compactVariableMap->get(environment, isNewEntry);
1125          if (!isNewEntry) {
1126              decoder.addFinalizer([=] {
1127                  delete environment;
1128              });
1129          }
1130          decoder.setHandleForTDZEnvironment(environment, handle);
1131          return handle;
1132      }
1133  
1134      void decode(Decoder& decoder, CompactTDZEnvironmentMap::Handle& handle) const
1135      {
1136          handle = decode(decoder);
1137      }
1138  
1139  private:
1140      CachedPtr<CachedCompactTDZEnvironment> m_environment;
1141  };
1142  
1143  template<typename T, typename Source = SourceType<T>>
1144  class CachedArray : public VariableLengthObject<Source*> {
1145  public:
1146      void encode(Encoder& encoder, const Source* array, unsigned size)
1147      {
1148          if (!size)
1149              return;
1150          T* dst = this->template allocate<T>(encoder, size);
1151          for (unsigned i = 0; i < size; ++i)
1152              ::JSC::encode(encoder, dst[i], array[i]);
1153      }
1154  
1155      template<typename... Args>
1156      void decode(Decoder& decoder, Source* array, unsigned size, Args... args) const
1157      {
1158          if (!size)
1159              return;
1160          const T* buffer = this->template buffer<T>();
1161          for (unsigned i = 0; i < size; ++i)
1162              ::JSC::decode(decoder, buffer[i], array[i], args...);
1163      }
1164  };
1165  
1166  class CachedScopedArgumentsTable : public CachedObject<ScopedArgumentsTable> {
1167  public:
1168      void encode(Encoder& encoder, const ScopedArgumentsTable& scopedArgumentsTable)
1169      {
1170          m_length = scopedArgumentsTable.m_length;
1171          m_arguments.encode(encoder, scopedArgumentsTable.m_arguments.get(m_length), m_length);
1172      }
1173  
1174      ScopedArgumentsTable* decode(Decoder& decoder) const
1175      {
1176          ScopedArgumentsTable* scopedArgumentsTable = ScopedArgumentsTable::tryCreate(decoder.vm(), m_length);
1177          RELEASE_ASSERT(scopedArgumentsTable); // We crash here. This is unlikely to continue execution if we hit this condition when decoding UnlinkedCodeBlock.
1178          m_arguments.decode(decoder, scopedArgumentsTable->m_arguments.get(m_length), m_length);
1179          return scopedArgumentsTable;
1180      }
1181  
1182  private:
1183      uint32_t m_length;
1184      CachedArray<ScopeOffset> m_arguments;
1185  };
1186  
1187  class CachedSymbolTableEntry : public CachedObject<SymbolTableEntry> {
1188  public:
1189      void encode(Encoder&, const SymbolTableEntry& symbolTableEntry)
1190      {
1191          m_bits = symbolTableEntry.m_bits | SymbolTableEntry::SlimFlag;
1192      }
1193  
1194      void decode(Decoder&, SymbolTableEntry& symbolTableEntry) const
1195      {
1196          symbolTableEntry.m_bits = m_bits;
1197      }
1198  
1199  private:
1200      intptr_t m_bits;
1201  };
1202  
1203  class CachedSymbolTableRareData : public CachedObject<SymbolTable::SymbolTableRareData> {
1204  public:
1205      void encode(Encoder& encoder, const SymbolTable::SymbolTableRareData& rareData)
1206      {
1207          m_privateNames.encode(encoder, rareData.m_privateNames);
1208      }
1209  
1210      void decode(Decoder& decoder, SymbolTable::SymbolTableRareData& rareData) const
1211      {
1212          m_privateNames.decode(decoder, rareData.m_privateNames);
1213      }
1214  
1215  private:
1216      CachedHashSet<CachedRefPtr<CachedUniquedStringImpl>, IdentifierRepHash> m_privateNames;
1217  };
1218  
1219  class CachedSymbolTable : public CachedObject<SymbolTable> {
1220  public:
1221      void encode(Encoder& encoder, const SymbolTable& symbolTable)
1222      {
1223          m_map.encode(encoder, symbolTable.m_map);
1224          m_maxScopeOffset = symbolTable.m_maxScopeOffset;
1225          m_usesNonStrictEval = symbolTable.m_usesNonStrictEval;
1226          m_nestedLexicalScope = symbolTable.m_nestedLexicalScope;
1227          m_scopeType = symbolTable.m_scopeType;
1228          m_arguments.encode(encoder, symbolTable.m_arguments.get());
1229          m_rareData.encode(encoder, symbolTable.m_rareData.get());
1230      }
1231  
1232      SymbolTable* decode(Decoder& decoder) const
1233      {
1234          SymbolTable* symbolTable = SymbolTable::create(decoder.vm());
1235          m_map.decode(decoder, symbolTable->m_map);
1236          symbolTable->m_maxScopeOffset = m_maxScopeOffset;
1237          symbolTable->m_usesNonStrictEval = m_usesNonStrictEval;
1238          symbolTable->m_nestedLexicalScope = m_nestedLexicalScope;
1239          symbolTable->m_scopeType = m_scopeType;
1240          ScopedArgumentsTable* scopedArgumentsTable = m_arguments.decode(decoder);
1241          if (scopedArgumentsTable)
1242              symbolTable->m_arguments.set(decoder.vm(), symbolTable, scopedArgumentsTable);
1243          if (!m_rareData.isEmpty()) {
1244              symbolTable->m_rareData = WTF::makeUnique<SymbolTable::SymbolTableRareData>();
1245              m_rareData->decode(decoder, *symbolTable->m_rareData);
1246          }
1247  
1248          return symbolTable;
1249      }
1250  
1251  private:
1252      CachedHashMap<CachedRefPtr<CachedUniquedStringImpl>, CachedSymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>, SymbolTableIndexHashTraits> m_map;
1253      ScopeOffset m_maxScopeOffset;
1254      unsigned m_usesNonStrictEval : 1;
1255      unsigned m_nestedLexicalScope : 1;
1256      unsigned m_scopeType : 3;
1257      CachedPtr<CachedScopedArgumentsTable> m_arguments;
1258      CachedPtr<CachedSymbolTableRareData> m_rareData;
1259  };
1260  
1261  class CachedJSValue;
1262  class CachedImmutableButterfly : public CachedObject<JSImmutableButterfly> {
1263  public:
1264      CachedImmutableButterfly()
1265          : m_cachedDoubles()
1266      {
1267      }
1268  
1269      void encode(Encoder& encoder, JSImmutableButterfly& immutableButterfly)
1270      {
1271          m_length = immutableButterfly.length();
1272          m_indexingType = immutableButterfly.indexingTypeAndMisc();
1273          if (hasDouble(m_indexingType))
1274              m_cachedDoubles.encode(encoder, immutableButterfly.toButterfly()->contiguousDouble().data(), m_length);
1275          else
1276              m_cachedValues.encode(encoder, immutableButterfly.toButterfly()->contiguous().data(), m_length);
1277      }
1278  
1279      JSImmutableButterfly* decode(Decoder& decoder) const
1280      {
1281          JSImmutableButterfly* immutableButterfly = JSImmutableButterfly::create(decoder.vm(), m_indexingType, m_length);
1282          if (hasDouble(m_indexingType))
1283              m_cachedDoubles.decode(decoder, immutableButterfly->toButterfly()->contiguousDouble().data(), m_length, immutableButterfly);
1284          else
1285              m_cachedValues.decode(decoder, immutableButterfly->toButterfly()->contiguous().data(), m_length, immutableButterfly);
1286          return immutableButterfly;
1287      }
1288  
1289  private:
1290      IndexingType m_indexingType;
1291      unsigned m_length;
1292      union {
1293          CachedArray<double> m_cachedDoubles;
1294          CachedArray<CachedJSValue, WriteBarrier<Unknown>> m_cachedValues;
1295      };
1296  };
1297  
1298  class CachedRegExp : public CachedObject<RegExp> {
1299  public:
1300      void encode(Encoder& encoder, const RegExp& regExp)
1301      {
1302          m_patternString.encode(encoder, regExp.m_patternString);
1303          m_flags = regExp.m_flags;
1304      }
1305  
1306      RegExp* decode(Decoder& decoder) const
1307      {
1308          String pattern { m_patternString.decode(decoder) };
1309          return RegExp::create(decoder.vm(), pattern, m_flags);
1310      }
1311  
1312  private:
1313      CachedString m_patternString;
1314      OptionSet<Yarr::Flags> m_flags;
1315  };
1316  
1317  class CachedTemplateObjectDescriptor : public CachedObject<TemplateObjectDescriptor> {
1318  public:
1319      void encode(Encoder& encoder, const JSTemplateObjectDescriptor& descriptor)
1320      {
1321          m_rawStrings.encode(encoder, descriptor.descriptor().rawStrings());
1322          m_cookedStrings.encode(encoder, descriptor.descriptor().cookedStrings());
1323          m_endOffset = descriptor.endOffset();
1324      }
1325  
1326      JSTemplateObjectDescriptor* decode(Decoder& decoder) const
1327      {
1328          TemplateObjectDescriptor::StringVector decodedRawStrings;
1329          TemplateObjectDescriptor::OptionalStringVector decodedCookedStrings;
1330          m_rawStrings.decode(decoder, decodedRawStrings);
1331          m_cookedStrings.decode(decoder, decodedCookedStrings);
1332          return JSTemplateObjectDescriptor::create(decoder.vm(), TemplateObjectDescriptor::create(WTFMove(decodedRawStrings), WTFMove(decodedCookedStrings)), m_endOffset);
1333      }
1334  
1335  private:
1336      CachedVector<CachedString, 4> m_rawStrings;
1337      CachedVector<CachedOptional<CachedString>, 4> m_cookedStrings;
1338      int m_endOffset;
1339  };
1340  
1341  class CachedBigInt : public VariableLengthObject<JSBigInt> {
1342  public:
1343      void encode(Encoder& encoder, JSBigInt& bigInt)
1344      {
1345          m_length = bigInt.length();
1346          m_sign = bigInt.sign();
1347  
1348          if (!m_length)
1349              return;
1350  
1351          unsigned size = sizeof(JSBigInt::Digit) * m_length;
1352          uint8_t* buffer = this->allocate(encoder, size);
1353          memcpy(buffer, bigInt.dataStorage(), size);
1354      }
1355  
1356      JSBigInt* decode(Decoder& decoder) const
1357      {
1358          JSBigInt* bigInt = JSBigInt::tryCreateWithLength(decoder.vm(), m_length);
1359          RELEASE_ASSERT(bigInt);
1360          bigInt->setSign(m_sign);
1361          if (m_length)
1362              memcpy(bigInt->dataStorage(), this->buffer(), sizeof(JSBigInt::Digit) * m_length);
1363          return bigInt;
1364      }
1365  
1366  private:
1367      unsigned m_length;
1368      bool m_sign;
1369  };
1370  
1371  class CachedJSValue : public VariableLengthObject<WriteBarrier<Unknown>> {
1372  public:
1373      void encode(Encoder& encoder, const WriteBarrier<Unknown> value)
1374      {
1375          JSValue v = value.get();
1376  
1377          if (!v.isCell() || v.isEmpty()) {
1378              m_type = EncodedType::JSValue;
1379              *this->allocate<EncodedJSValue>(encoder) = JSValue::encode(v);
1380              return;
1381          }
1382  
1383          JSCell* cell = v.asCell();
1384          VM& vm = encoder.vm();
1385  
1386          if (auto* symbolTable = jsDynamicCast<SymbolTable*>(vm, cell)) {
1387              m_type = EncodedType::SymbolTable;
1388              this->allocate<CachedSymbolTable>(encoder)->encode(encoder, *symbolTable);
1389              return;
1390          }
1391  
1392          if (auto* string = jsDynamicCast<JSString*>(vm, cell)) {
1393              m_type = EncodedType::String;
1394              StringImpl* impl = string->tryGetValue().impl();
1395              this->allocate<CachedUniquedStringImpl>(encoder)->encode(encoder, *impl);
1396              return;
1397          }
1398  
1399          if (auto* immutableButterfly = jsDynamicCast<JSImmutableButterfly*>(vm, cell)) {
1400              m_type = EncodedType::ImmutableButterfly;
1401              this->allocate<CachedImmutableButterfly>(encoder)->encode(encoder, *immutableButterfly);
1402              return;
1403          }
1404  
1405          if (auto* regexp = jsDynamicCast<RegExp*>(vm, cell)) {
1406              m_type = EncodedType::RegExp;
1407              this->allocate<CachedRegExp>(encoder)->encode(encoder, *regexp);
1408              return;
1409          }
1410  
1411          if (auto* templateObjectDescriptor = jsDynamicCast<JSTemplateObjectDescriptor*>(vm, cell)) {
1412              m_type = EncodedType::TemplateObjectDescriptor;
1413              this->allocate<CachedTemplateObjectDescriptor>(encoder)->encode(encoder, *templateObjectDescriptor);
1414              return;
1415          }
1416  
1417          if (auto* bigInt = jsDynamicCast<JSBigInt*>(vm, cell)) {
1418              m_type = EncodedType::BigInt;
1419              this->allocate<CachedBigInt>(encoder)->encode(encoder, *bigInt);
1420              return;
1421          }
1422  
1423          RELEASE_ASSERT_NOT_REACHED();
1424      }
1425  
1426      void decode(Decoder& decoder, WriteBarrier<Unknown>& value, const JSCell* owner) const
1427      {
1428          JSValue v;
1429          switch (m_type) {
1430          case EncodedType::JSValue:
1431              v = JSValue::decode(*this->buffer<EncodedJSValue>());
1432              break;
1433          case EncodedType::SymbolTable:
1434              v = this->buffer<CachedSymbolTable>()->decode(decoder);
1435              break;
1436          case EncodedType::String: {
1437              StringImpl* impl = this->buffer<CachedUniquedStringImpl>()->decode(decoder);
1438              v = jsString(decoder.vm(), adoptRef(*impl));
1439              break;
1440          }
1441          case EncodedType::ImmutableButterfly:
1442              v = this->buffer<CachedImmutableButterfly>()->decode(decoder);
1443              break;
1444          case EncodedType::RegExp:
1445              v = this->buffer<CachedRegExp>()->decode(decoder);
1446              break;
1447          case EncodedType::TemplateObjectDescriptor:
1448              v = this->buffer<CachedTemplateObjectDescriptor>()->decode(decoder);
1449              break;
1450          case EncodedType::BigInt:
1451              v = this->buffer<CachedBigInt>()->decode(decoder);
1452              break;
1453          default:
1454              RELEASE_ASSERT_NOT_REACHED();
1455          }
1456          value.set(decoder.vm(), owner, v);
1457      }
1458  
1459  private:
1460      enum class EncodedType : uint8_t {
1461          JSValue,
1462          SymbolTable,
1463          String,
1464          ImmutableButterfly,
1465          RegExp,
1466          TemplateObjectDescriptor,
1467          BigInt,
1468      };
1469  
1470      EncodedType m_type;
1471  };
1472  
1473  class CachedInstructionStream : public CachedObject<InstructionStream> {
1474  public:
1475      void encode(Encoder& encoder, const InstructionStream& stream)
1476      {
1477          m_instructions.encode(encoder, stream.m_instructions);
1478      }
1479  
1480      InstructionStream* decode(Decoder& decoder) const
1481      {
1482          Vector<uint8_t, 0, UnsafeVectorOverflow, 16, InstructionStreamMalloc> instructionsVector;
1483          m_instructions.decode(decoder, instructionsVector);
1484          return new InstructionStream(WTFMove(instructionsVector));
1485      }
1486  
1487  private:
1488      CachedVector<uint8_t, 0, UnsafeVectorOverflow, InstructionStreamMalloc> m_instructions;
1489  };
1490  
1491  class CachedMetadataTable : public CachedObject<UnlinkedMetadataTable> {
1492  public:
1493      void encode(Encoder&, const UnlinkedMetadataTable& metadataTable)
1494      {
1495          ASSERT(metadataTable.m_isFinalized);
1496          m_hasMetadata = metadataTable.m_hasMetadata;
1497          if (!m_hasMetadata)
1498              return;
1499          m_is32Bit = metadataTable.m_is32Bit;
1500          if (m_is32Bit) {
1501              for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
1502                  m_metadata[i] = metadataTable.offsetTable32()[i];
1503          } else {
1504              for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
1505                  m_metadata[i] = metadataTable.offsetTable16()[i];
1506          }
1507      }
1508  
1509      Ref<UnlinkedMetadataTable> decode(Decoder&) const
1510      {
1511          if (!m_hasMetadata)
1512              return UnlinkedMetadataTable::empty();
1513  
1514          Ref<UnlinkedMetadataTable> metadataTable = UnlinkedMetadataTable::create(m_is32Bit);
1515          metadataTable->m_isFinalized = true;
1516          metadataTable->m_isLinked = false;
1517          metadataTable->m_hasMetadata = m_hasMetadata;
1518          if (m_is32Bit) {
1519              for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
1520                  metadataTable->offsetTable32()[i] = m_metadata[i];
1521          } else {
1522              for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
1523                  metadataTable->offsetTable16()[i] = m_metadata[i];
1524          }
1525          return metadataTable;
1526      }
1527  
1528  private:
1529      bool m_hasMetadata;
1530      bool m_is32Bit;
1531      std::array<unsigned, UnlinkedMetadataTable::s_offsetTableEntries> m_metadata;
1532  };
1533  
1534  class CachedSourceOrigin : public CachedObject<SourceOrigin> {
1535  public:
1536      void encode(Encoder& encoder, const SourceOrigin& sourceOrigin)
1537      {
1538          m_string.encode(encoder, sourceOrigin.url().string());
1539      }
1540  
1541      SourceOrigin decode(Decoder& decoder) const
1542      {
1543          return SourceOrigin { URL({ }, m_string.decode(decoder)) };
1544      }
1545  
1546  private:
1547      CachedString m_string;
1548  };
1549  
1550  class CachedTextPosition : public CachedObject<TextPosition> {
1551  public:
1552      void encode(Encoder&, TextPosition textPosition)
1553      {
1554          m_line = textPosition.m_line.zeroBasedInt();
1555          m_column = textPosition.m_column.zeroBasedInt();
1556      }
1557  
1558      TextPosition decode(Decoder&) const
1559      {
1560          return TextPosition { OrdinalNumber::fromZeroBasedInt(m_line), OrdinalNumber::fromZeroBasedInt(m_column) };
1561      }
1562  
1563  private:
1564      int m_line;
1565      int m_column;
1566  };
1567  
1568  template <typename Source, typename CachedType>
1569  class CachedSourceProviderShape : public CachedObject<Source> {
1570  public:
1571      void encode(Encoder& encoder, const SourceProvider& sourceProvider)
1572      {
1573          m_sourceOrigin.encode(encoder, sourceProvider.sourceOrigin());
1574          m_sourceURL.encode(encoder, sourceProvider.sourceURL());
1575          m_sourceURLDirective.encode(encoder, sourceProvider.sourceURLDirective());
1576          m_sourceMappingURLDirective.encode(encoder, sourceProvider.sourceMappingURLDirective());
1577          m_startPosition.encode(encoder, sourceProvider.startPosition());
1578      }
1579  
1580      void decode(Decoder& decoder, SourceProvider& sourceProvider) const
1581      {
1582          sourceProvider.setSourceURLDirective(m_sourceURLDirective.decode(decoder));
1583          sourceProvider.setSourceMappingURLDirective(m_sourceMappingURLDirective.decode(decoder));
1584      }
1585  
1586  protected:
1587      CachedSourceOrigin m_sourceOrigin;
1588      CachedString m_sourceURL;
1589      CachedString m_sourceURLDirective;
1590      CachedString m_sourceMappingURLDirective;
1591      CachedTextPosition m_startPosition;
1592  };
1593  
1594  class CachedStringSourceProvider : public CachedSourceProviderShape<StringSourceProvider, CachedStringSourceProvider> {
1595      using Base = CachedSourceProviderShape<StringSourceProvider, CachedStringSourceProvider>;
1596  
1597  public:
1598      void encode(Encoder& encoder, const StringSourceProvider& sourceProvider)
1599      {
1600          Base::encode(encoder, sourceProvider);
1601          m_source.encode(encoder, sourceProvider.source().toString());
1602      }
1603  
1604      StringSourceProvider* decode(Decoder& decoder, SourceProviderSourceType sourceType) const
1605      {
1606          String decodedSource = m_source.decode(decoder);
1607          SourceOrigin decodedSourceOrigin = m_sourceOrigin.decode(decoder);
1608          String decodedSourceURL = m_sourceURL.decode(decoder);
1609          TextPosition decodedStartPosition = m_startPosition.decode(decoder);
1610  
1611          Ref<StringSourceProvider> sourceProvider = StringSourceProvider::create(decodedSource, decodedSourceOrigin, decodedSourceURL, decodedStartPosition, sourceType);
1612          Base::decode(decoder, sourceProvider.get());
1613          return &sourceProvider.leakRef();
1614      }
1615  
1616  private:
1617      CachedString m_source;
1618  };
1619  
1620  #if ENABLE(WEBASSEMBLY)
1621  class CachedWebAssemblySourceProvider : public CachedSourceProviderShape<WebAssemblySourceProvider, CachedWebAssemblySourceProvider> {
1622      using Base = CachedSourceProviderShape<WebAssemblySourceProvider, CachedWebAssemblySourceProvider>;
1623  
1624  public:
1625      void encode(Encoder& encoder, const WebAssemblySourceProvider& sourceProvider)
1626      {
1627          Base::encode(encoder, sourceProvider);
1628          m_data.encode(encoder, sourceProvider.data());
1629      }
1630  
1631      WebAssemblySourceProvider* decode(Decoder& decoder) const
1632      {
1633          Vector<uint8_t> decodedData;
1634          SourceOrigin decodedSourceOrigin = m_sourceOrigin.decode(decoder);
1635          String decodedSourceURL = m_sourceURL.decode(decoder);
1636  
1637          m_data.decode(decoder, decodedData);
1638  
1639          Ref<WebAssemblySourceProvider> sourceProvider = WebAssemblySourceProvider::create(WTFMove(decodedData), decodedSourceOrigin, decodedSourceURL);
1640          Base::decode(decoder, sourceProvider.get());
1641  
1642          return &sourceProvider.leakRef();
1643      }
1644  
1645  private:
1646      CachedVector<uint8_t> m_data;
1647  };
1648  #endif
1649  
1650  class CachedSourceProvider : public VariableLengthObject<SourceProvider> {
1651  public:
1652      void encode(Encoder& encoder, const SourceProvider& sourceProvider)
1653      {
1654          m_sourceType = sourceProvider.sourceType();
1655          switch (m_sourceType) {
1656          case SourceProviderSourceType::Program:
1657          case SourceProviderSourceType::Module:
1658              this->allocate<CachedStringSourceProvider>(encoder)->encode(encoder, reinterpret_cast<const StringSourceProvider&>(sourceProvider));
1659              break;
1660  #if ENABLE(WEBASSEMBLY)
1661          case SourceProviderSourceType::WebAssembly:
1662              this->allocate<CachedWebAssemblySourceProvider>(encoder)->encode(encoder, reinterpret_cast<const WebAssemblySourceProvider&>(sourceProvider));
1663              break;
1664  #endif
1665          default:
1666              RELEASE_ASSERT_NOT_REACHED();
1667          }
1668      }
1669  
1670      SourceProvider* decode(Decoder& decoder) const
1671      {
1672          switch (m_sourceType) {
1673          case SourceProviderSourceType::Program:
1674          case SourceProviderSourceType::Module:
1675              return this->buffer<CachedStringSourceProvider>()->decode(decoder, m_sourceType);
1676  #if ENABLE(WEBASSEMBLY)
1677          case SourceProviderSourceType::WebAssembly:
1678              return this->buffer<CachedWebAssemblySourceProvider>()->decode(decoder);
1679  #endif
1680          default:
1681              RELEASE_ASSERT_NOT_REACHED();
1682          }
1683      }
1684  
1685  private:
1686      SourceProviderSourceType m_sourceType;
1687  };
1688  
1689  template<typename Source>
1690  class CachedUnlinkedSourceCodeShape : public CachedObject<Source> {
1691  public:
1692      void encode(Encoder& encoder, const UnlinkedSourceCode& sourceCode)
1693      {
1694          m_provider.encode(encoder, sourceCode.m_provider);
1695          m_startOffset = sourceCode.startOffset();
1696          m_endOffset = sourceCode.endOffset();
1697      }
1698  
1699      void decode(Decoder& decoder, UnlinkedSourceCode& sourceCode) const
1700      {
1701          sourceCode.m_provider = m_provider.decode(decoder);
1702          sourceCode.m_startOffset = m_startOffset;
1703          sourceCode.m_endOffset = m_endOffset;
1704      }
1705  
1706  private:
1707      CachedRefPtr<CachedSourceProvider> m_provider;
1708      int m_startOffset;
1709      int m_endOffset;
1710  };
1711  
1712  
1713  class CachedUnlinkedSourceCode : public CachedUnlinkedSourceCodeShape<UnlinkedSourceCode> { };
1714  
1715  class CachedSourceCode : public CachedUnlinkedSourceCodeShape<SourceCode> {
1716      using Base = CachedUnlinkedSourceCodeShape<SourceCode>;
1717  
1718  public:
1719      void encode(Encoder& encoder, const SourceCode& sourceCode)
1720      {
1721          Base::encode(encoder, sourceCode);
1722          m_firstLine = sourceCode.firstLine().zeroBasedInt();
1723          m_startColumn = sourceCode.startColumn().zeroBasedInt();
1724      }
1725  
1726      void decode(Decoder& decoder, SourceCode& sourceCode) const
1727      {
1728          Base::decode(decoder, sourceCode);
1729          sourceCode.m_firstLine = OrdinalNumber::fromZeroBasedInt(m_firstLine);
1730          sourceCode.m_startColumn = OrdinalNumber::fromZeroBasedInt(m_startColumn);
1731      }
1732  
1733  private:
1734      int m_firstLine;
1735      int m_startColumn;
1736  };
1737  
1738  class CachedSourceCodeWithoutProvider : public CachedObject<SourceCode> {
1739  public:
1740      void encode(Encoder&, const SourceCode& sourceCode)
1741      {
1742          m_hasProvider = !!sourceCode.provider();
1743          m_startOffset = sourceCode.startOffset();
1744          m_endOffset = sourceCode.endOffset();
1745          m_firstLine = sourceCode.firstLine().zeroBasedInt();
1746          m_startColumn = sourceCode.startColumn().zeroBasedInt();
1747      }
1748  
1749      void decode(Decoder& decoder, SourceCode& sourceCode) const
1750      {
1751          if (m_hasProvider)
1752              sourceCode.m_provider = decoder.provider();
1753          sourceCode.m_startOffset = m_startOffset;
1754          sourceCode.m_endOffset = m_endOffset;
1755          sourceCode.m_firstLine = OrdinalNumber::fromZeroBasedInt(m_firstLine);
1756          sourceCode.m_startColumn = OrdinalNumber::fromZeroBasedInt(m_startColumn);
1757      }
1758  
1759  private:
1760      bool m_hasProvider;
1761      int m_startOffset;
1762      int m_endOffset;
1763      int m_firstLine;
1764      int m_startColumn;
1765  };
1766  
1767  class CachedTDZEnvironmentLink : public CachedObject<TDZEnvironmentLink> {
1768  public:
1769      void encode(Encoder& encoder, const TDZEnvironmentLink& environment)
1770      {
1771          m_handle.encode(encoder, environment.m_handle);
1772          m_parent.encode(encoder, environment.m_parent);
1773      }
1774  
1775      TDZEnvironmentLink* decode(Decoder& decoder) const
1776      {
1777          CompactTDZEnvironmentMap::Handle handle = m_handle.decode(decoder);
1778          RefPtr<TDZEnvironmentLink> parent = m_parent.decode(decoder);
1779          return new TDZEnvironmentLink(WTFMove(handle), WTFMove(parent));
1780      }
1781  
1782  private:
1783      CachedCompactTDZEnvironmentMapHandle m_handle;
1784      CachedRefPtr<CachedTDZEnvironmentLink> m_parent;
1785  };
1786  
1787  class CachedFunctionExecutableRareData : public CachedObject<UnlinkedFunctionExecutable::RareData> {
1788  public:
1789      void encode(Encoder& encoder, const UnlinkedFunctionExecutable::RareData& rareData)
1790      {
1791          m_classSource.encode(encoder, rareData.m_classSource);
1792          m_parentScopeTDZVariables.encode(encoder, rareData.m_parentScopeTDZVariables);
1793      }
1794  
1795      UnlinkedFunctionExecutable::RareData* decode(Decoder& decoder) const
1796      {
1797          UnlinkedFunctionExecutable::RareData* rareData = new UnlinkedFunctionExecutable::RareData { };
1798          m_classSource.decode(decoder, rareData->m_classSource);
1799          m_parentScopeTDZVariables.decode(decoder, rareData->m_parentScopeTDZVariables);
1800          return rareData;
1801      }
1802  
1803  private:
1804      CachedSourceCodeWithoutProvider m_classSource;
1805      CachedRefPtr<CachedTDZEnvironmentLink> m_parentScopeTDZVariables;
1806  };
1807  
1808  class CachedFunctionExecutable : public CachedObject<UnlinkedFunctionExecutable> {
1809      friend struct CachedFunctionExecutableOffsets;
1810  
1811  public:
1812      void encode(Encoder&, const UnlinkedFunctionExecutable&);
1813      UnlinkedFunctionExecutable* decode(Decoder&) const;
1814  
1815      unsigned firstLineOffset() const { return m_firstLineOffset; }
1816      unsigned lineCount() const { return m_lineCount; }
1817      unsigned unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; }
1818      unsigned unlinkedBodyStartColumn() const { return m_unlinkedBodyStartColumn; }
1819      unsigned unlinkedBodyEndColumn() const { return m_unlinkedBodyEndColumn; }
1820      unsigned startOffset() const { return m_startOffset; }
1821      unsigned sourceLength() const { return m_sourceLength; }
1822      unsigned parametersStartOffset() const { return m_parametersStartOffset; }
1823      unsigned typeProfilingStartOffset() const { return m_typeProfilingStartOffset; }
1824      unsigned typeProfilingEndOffset() const { return m_typeProfilingEndOffset; }
1825      unsigned parameterCount() const { return m_parameterCount; }
1826  
1827      CodeFeatures features() const { return m_mutableMetadata.m_features; }
1828      SourceParseMode sourceParseMode() const { return m_sourceParseMode; }
1829  
1830      unsigned isInStrictContext() const { return m_isInStrictContext; }
1831      unsigned hasCapturedVariables() const { return m_mutableMetadata.m_hasCapturedVariables; }
1832      unsigned isBuiltinFunction() const { return m_isBuiltinFunction; }
1833      unsigned isBuiltinDefaultClassConstructor() const { return m_isBuiltinDefaultClassConstructor; }
1834      unsigned constructAbility() const { return m_constructAbility; }
1835      unsigned constructorKind() const { return m_constructorKind; }
1836      unsigned functionMode() const { return m_functionMode; }
1837      unsigned scriptMode() const { return m_scriptMode; }
1838      unsigned superBinding() const { return m_superBinding; }
1839      unsigned derivedContextType() const { return m_derivedContextType; }
1840      unsigned needsClassFieldInitializer() const { return m_needsClassFieldInitializer; }
1841  
1842      Identifier name(Decoder& decoder) const { return m_name.decode(decoder); }
1843      Identifier ecmaName(Decoder& decoder) const { return m_ecmaName.decode(decoder); }
1844  
1845      UnlinkedFunctionExecutable::RareData* rareData(Decoder& decoder) const { return m_rareData.decode(decoder); }
1846  
1847      const CachedWriteBarrier<CachedFunctionCodeBlock, UnlinkedFunctionCodeBlock>& unlinkedCodeBlockForCall() const { return m_unlinkedCodeBlockForCall; }
1848      const CachedWriteBarrier<CachedFunctionCodeBlock, UnlinkedFunctionCodeBlock>& unlinkedCodeBlockForConstruct() const { return m_unlinkedCodeBlockForConstruct; }
1849  
1850  private:
1851      CachedFunctionExecutableMetadata m_mutableMetadata;
1852  
1853      unsigned m_firstLineOffset : 31;
1854      unsigned m_isInStrictContext : 1;
1855      unsigned m_lineCount : 31;
1856      unsigned m_isBuiltinFunction : 1;
1857      unsigned m_unlinkedFunctionNameStart : 31;
1858      unsigned m_isBuiltinDefaultClassConstructor : 1;
1859      unsigned m_unlinkedBodyStartColumn : 31;
1860      unsigned m_constructAbility: 1;
1861      unsigned m_unlinkedBodyEndColumn : 31;
1862      unsigned m_startOffset : 31;
1863      unsigned m_scriptMode: 1; // JSParserScriptMode
1864      unsigned m_sourceLength : 31;
1865      unsigned m_superBinding : 1;
1866      unsigned m_parametersStartOffset : 31;
1867      unsigned m_typeProfilingStartOffset;
1868      unsigned m_typeProfilingEndOffset;
1869      unsigned m_parameterCount;
1870      SourceParseMode m_sourceParseMode;
1871      unsigned m_constructorKind : 2;
1872      unsigned m_functionMode : 2; // FunctionMode
1873      unsigned m_derivedContextType: 2;
1874      unsigned m_needsClassFieldInitializer : 1;
1875  
1876      CachedPtr<CachedFunctionExecutableRareData> m_rareData;
1877  
1878      CachedIdentifier m_name;
1879      CachedIdentifier m_ecmaName;
1880  
1881      CachedWriteBarrier<CachedFunctionCodeBlock, UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForCall;
1882      CachedWriteBarrier<CachedFunctionCodeBlock, UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForConstruct;
1883  };
1884  
1885  ptrdiff_t CachedFunctionExecutableOffsets::codeBlockForCallOffset()
1886  {
1887      return OBJECT_OFFSETOF(CachedFunctionExecutable, m_unlinkedCodeBlockForCall);
1888  }
1889  
1890  ptrdiff_t CachedFunctionExecutableOffsets::codeBlockForConstructOffset()
1891  {
1892      return OBJECT_OFFSETOF(CachedFunctionExecutable, m_unlinkedCodeBlockForConstruct);
1893  }
1894  
1895  ptrdiff_t CachedFunctionExecutableOffsets::metadataOffset()
1896  {
1897      return OBJECT_OFFSETOF(CachedFunctionExecutable, m_mutableMetadata);
1898  }
1899  
1900  template<typename CodeBlockType>
1901  class CachedCodeBlock : public CachedObject<CodeBlockType> {
1902  public:
1903      void encode(Encoder&, const UnlinkedCodeBlock&);
1904      void decode(Decoder&, UnlinkedCodeBlock&) const;
1905  
1906      InstructionStream* instructions(Decoder& decoder) const { return m_instructions.decode(decoder); }
1907  
1908      VirtualRegister thisRegister() const { return m_thisRegister; }
1909      VirtualRegister scopeRegister() const { return m_scopeRegister; }
1910  
1911      RefPtr<StringImpl> sourceURLDirective(Decoder& decoder) const { return m_sourceURLDirective.decode(decoder); }
1912      RefPtr<StringImpl> sourceMappingURLDirective(Decoder& decoder) const { return m_sourceMappingURLDirective.decode(decoder); }
1913  
1914      Ref<UnlinkedMetadataTable> metadata(Decoder& decoder) const { return m_metadata.decode(decoder); }
1915  
1916      unsigned usesEval() const { return m_usesEval; }
1917      unsigned isConstructor() const { return m_isConstructor; }
1918      unsigned hasCapturedVariables() const { return m_hasCapturedVariables; }
1919      unsigned isBuiltinFunction() const { return m_isBuiltinFunction; }
1920      unsigned superBinding() const { return m_superBinding; }
1921      unsigned scriptMode() const { return m_scriptMode; }
1922      unsigned isArrowFunctionContext() const { return m_isArrowFunctionContext; }
1923      unsigned isClassContext() const { return m_isClassContext; }
1924      unsigned constructorKind() const { return m_constructorKind; }
1925      unsigned derivedContextType() const { return m_derivedContextType; }
1926      unsigned needsClassFieldInitializer() const { return m_needsClassFieldInitializer; }
1927      unsigned evalContextType() const { return m_evalContextType; }
1928      unsigned hasTailCalls() const { return m_hasTailCalls; }
1929      unsigned hasCheckpoints() const { return m_hasCheckpoints; }
1930      unsigned lineCount() const { return m_lineCount; }
1931      unsigned endColumn() const { return m_endColumn; }
1932  
1933      int numVars() const { return m_numVars; }
1934      int numCalleeLocals() const { return m_numCalleeLocals; }
1935      int numParameters() const { return m_numParameters; }
1936  
1937      CodeFeatures features() const { return m_features; }
1938      SourceParseMode parseMode() const { return m_parseMode; }
1939      OptionSet<CodeGenerationMode> codeGenerationMode() const { return m_codeGenerationMode; }
1940      unsigned codeType() const { return m_codeType; }
1941  
1942      UnlinkedCodeBlock::RareData* rareData(Decoder& decoder) const { return m_rareData.decode(decoder); }
1943  
1944  private:
1945      VirtualRegister m_thisRegister;
1946      VirtualRegister m_scopeRegister;
1947  
1948      unsigned m_usesEval : 1;
1949      unsigned m_isConstructor : 1;
1950      unsigned m_hasCapturedVariables : 1;
1951      unsigned m_isBuiltinFunction : 1;
1952      unsigned m_superBinding : 1;
1953      unsigned m_scriptMode: 1;
1954      unsigned m_isArrowFunctionContext : 1;
1955      unsigned m_isClassContext : 1;
1956      unsigned m_constructorKind : 2;
1957      unsigned m_derivedContextType : 2;
1958      unsigned m_needsClassFieldInitializer : 1;
1959      unsigned m_evalContextType : 2;
1960      unsigned m_hasTailCalls : 1;
1961      unsigned m_codeType : 2;
1962      unsigned m_hasCheckpoints : 1;
1963  
1964      CodeFeatures m_features;
1965      SourceParseMode m_parseMode;
1966      OptionSet<CodeGenerationMode> m_codeGenerationMode;
1967  
1968      unsigned m_lineCount;
1969      unsigned m_endColumn;
1970  
1971      int m_numVars;
1972      int m_numCalleeLocals;
1973      int m_numParameters;
1974  
1975      CachedMetadataTable m_metadata;
1976  
1977      CachedPtr<CachedCodeBlockRareData> m_rareData;
1978  
1979      CachedRefPtr<CachedStringImpl> m_sourceURLDirective;
1980      CachedRefPtr<CachedStringImpl> m_sourceMappingURLDirective;
1981  
1982      CachedPtr<CachedInstructionStream> m_instructions;
1983      CachedVector<InstructionStream::Offset> m_jumpTargets;
1984      CachedVector<CachedJSValue> m_constantRegisters;
1985      CachedVector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation;
1986      CachedVector<ExpressionRangeInfo> m_expressionInfo;
1987      CachedHashMap<InstructionStream::Offset, int> m_outOfLineJumpTargets;
1988  
1989      CachedVector<CachedIdentifier> m_identifiers;
1990      CachedVector<CachedWriteBarrier<CachedFunctionExecutable>> m_functionDecls;
1991      CachedVector<CachedWriteBarrier<CachedFunctionExecutable>> m_functionExprs;
1992  };
1993  
1994  class CachedProgramCodeBlock : public CachedCodeBlock<UnlinkedProgramCodeBlock> {
1995      using Base = CachedCodeBlock<UnlinkedProgramCodeBlock>;
1996  
1997  public:
1998      void encode(Encoder& encoder, const UnlinkedProgramCodeBlock& codeBlock)
1999      {
2000          Base::encode(encoder, codeBlock);
2001          m_varDeclarations.encode(encoder, codeBlock.m_varDeclarations);
2002          m_lexicalDeclarations.encode(encoder, codeBlock.m_lexicalDeclarations);
2003      }
2004  
2005      UnlinkedProgramCodeBlock* decode(Decoder& decoder) const
2006      {
2007          UnlinkedProgramCodeBlock* codeBlock = new (NotNull, allocateCell<UnlinkedProgramCodeBlock>(decoder.vm().heap)) UnlinkedProgramCodeBlock(decoder, *this);
2008          codeBlock->finishCreation(decoder.vm());
2009          Base::decode(decoder, *codeBlock);
2010          m_varDeclarations.decode(decoder, codeBlock->m_varDeclarations);
2011          m_lexicalDeclarations.decode(decoder, codeBlock->m_lexicalDeclarations);
2012          return codeBlock;
2013      }
2014  
2015  private:
2016      CachedVariableEnvironment m_varDeclarations;
2017      CachedVariableEnvironment m_lexicalDeclarations;
2018  };
2019  
2020  class CachedModuleCodeBlock : public CachedCodeBlock<UnlinkedModuleProgramCodeBlock> {
2021      using Base = CachedCodeBlock<UnlinkedModuleProgramCodeBlock>;
2022  
2023  public:
2024      void encode(Encoder& encoder, const UnlinkedModuleProgramCodeBlock& codeBlock)
2025      {
2026          Base::encode(encoder, codeBlock);
2027          m_moduleEnvironmentSymbolTableConstantRegisterOffset = codeBlock.m_moduleEnvironmentSymbolTableConstantRegisterOffset;
2028      }
2029  
2030      UnlinkedModuleProgramCodeBlock* decode(Decoder& decoder) const
2031      {
2032          UnlinkedModuleProgramCodeBlock* codeBlock = new (NotNull, allocateCell<UnlinkedModuleProgramCodeBlock>(decoder.vm().heap)) UnlinkedModuleProgramCodeBlock(decoder, *this);
2033          codeBlock->finishCreation(decoder.vm());
2034          Base::decode(decoder, *codeBlock);
2035          codeBlock->m_moduleEnvironmentSymbolTableConstantRegisterOffset = m_moduleEnvironmentSymbolTableConstantRegisterOffset;
2036          return codeBlock;
2037      }
2038  
2039  private:
2040      int m_moduleEnvironmentSymbolTableConstantRegisterOffset;
2041  };
2042  
2043  class CachedEvalCodeBlock : public CachedCodeBlock<UnlinkedEvalCodeBlock> {
2044      using Base = CachedCodeBlock<UnlinkedEvalCodeBlock>;
2045  
2046  public:
2047      void encode(Encoder& encoder, const UnlinkedEvalCodeBlock& codeBlock)
2048      {
2049          Base::encode(encoder, codeBlock);
2050          m_variables.encode(encoder, codeBlock.m_variables);
2051          m_functionHoistingCandidates.encode(encoder, codeBlock.m_functionHoistingCandidates);
2052      }
2053  
2054      UnlinkedEvalCodeBlock* decode(Decoder& decoder) const
2055      {
2056          UnlinkedEvalCodeBlock* codeBlock = new (NotNull, allocateCell<UnlinkedEvalCodeBlock>(decoder.vm().heap)) UnlinkedEvalCodeBlock(decoder, *this);
2057          codeBlock->finishCreation(decoder.vm());
2058          Base::decode(decoder, *codeBlock);
2059          m_variables.decode(decoder, codeBlock->m_variables);
2060          m_functionHoistingCandidates.decode(decoder, codeBlock->m_functionHoistingCandidates);
2061          return codeBlock;
2062      }
2063  
2064  private:
2065      CachedVector<CachedIdentifier, 0, UnsafeVectorOverflow> m_variables;
2066      CachedVector<CachedIdentifier, 0, UnsafeVectorOverflow> m_functionHoistingCandidates;
2067  };
2068  
2069  class CachedFunctionCodeBlock : public CachedCodeBlock<UnlinkedFunctionCodeBlock> {
2070      using Base = CachedCodeBlock<UnlinkedFunctionCodeBlock>;
2071  
2072  public:
2073      void encode(Encoder& encoder, const UnlinkedFunctionCodeBlock& codeBlock)
2074      {
2075          Base::encode(encoder, codeBlock);
2076      }
2077  
2078      UnlinkedFunctionCodeBlock* decode(Decoder& decoder) const
2079      {
2080          UnlinkedFunctionCodeBlock* codeBlock = new (NotNull, allocateCell<UnlinkedFunctionCodeBlock>(decoder.vm().heap)) UnlinkedFunctionCodeBlock(decoder, *this);
2081          codeBlock->finishCreation(decoder.vm());
2082          Base::decode(decoder, *codeBlock);
2083          return codeBlock;
2084      }
2085  };
2086  
2087  ALWAYS_INLINE UnlinkedFunctionCodeBlock::UnlinkedFunctionCodeBlock(Decoder& decoder, const CachedFunctionCodeBlock& cachedCodeBlock)
2088      : Base(decoder, decoder.vm().unlinkedFunctionCodeBlockStructure.get(), cachedCodeBlock)
2089  {
2090  }
2091  
2092  template<typename T>
2093  struct CachedCodeBlockTypeImpl;
2094  
2095  enum CachedCodeBlockTag {
2096      CachedProgramCodeBlockTag,
2097      CachedModuleCodeBlockTag,
2098      CachedEvalCodeBlockTag,
2099  };
2100  
2101  static CachedCodeBlockTag tagFromSourceCodeType(SourceCodeType type)
2102  {
2103      switch (type) {
2104      case SourceCodeType::ProgramType:
2105          return CachedProgramCodeBlockTag;
2106      case SourceCodeType::EvalType:
2107          return CachedEvalCodeBlockTag;
2108      case SourceCodeType::ModuleType:
2109          return CachedModuleCodeBlockTag;
2110      case SourceCodeType::FunctionType:
2111          break;
2112      }
2113      ASSERT_NOT_REACHED();
2114      return static_cast<CachedCodeBlockTag>(-1);
2115  }
2116  
2117  template<>
2118  struct CachedCodeBlockTypeImpl<UnlinkedProgramCodeBlock> {
2119      using type = CachedProgramCodeBlock;
2120      static constexpr CachedCodeBlockTag tag = CachedProgramCodeBlockTag;
2121  };
2122  
2123  template<>
2124  struct CachedCodeBlockTypeImpl<UnlinkedModuleProgramCodeBlock> {
2125      using type = CachedModuleCodeBlock;
2126      static constexpr CachedCodeBlockTag tag = CachedModuleCodeBlockTag;
2127  };
2128  
2129  template<>
2130  struct CachedCodeBlockTypeImpl<UnlinkedEvalCodeBlock> {
2131      using type = CachedEvalCodeBlock;
2132      static constexpr CachedCodeBlockTag tag = CachedEvalCodeBlockTag;
2133  };
2134  
2135  template<typename T>
2136  using CachedCodeBlockType = typename CachedCodeBlockTypeImpl<T>::type;
2137  
2138  template<typename CodeBlockType>
2139  ALWAYS_INLINE UnlinkedCodeBlock::UnlinkedCodeBlock(Decoder& decoder, Structure* structure, const CachedCodeBlock<CodeBlockType>& cachedCodeBlock)
2140      : Base(decoder.vm(), structure)
2141      , m_thisRegister(cachedCodeBlock.thisRegister())
2142      , m_scopeRegister(cachedCodeBlock.scopeRegister())
2143  
2144      , m_usesEval(cachedCodeBlock.usesEval())
2145      , m_isConstructor(cachedCodeBlock.isConstructor())
2146      , m_hasCapturedVariables(cachedCodeBlock.hasCapturedVariables())
2147      , m_isBuiltinFunction(cachedCodeBlock.isBuiltinFunction())
2148      , m_superBinding(cachedCodeBlock.superBinding())
2149      , m_scriptMode(cachedCodeBlock.scriptMode())
2150      , m_isArrowFunctionContext(cachedCodeBlock.isArrowFunctionContext())
2151      , m_isClassContext(cachedCodeBlock.isClassContext())
2152      , m_hasTailCalls(cachedCodeBlock.hasTailCalls())
2153      , m_constructorKind(cachedCodeBlock.constructorKind())
2154      , m_derivedContextType(cachedCodeBlock.derivedContextType())
2155      , m_evalContextType(cachedCodeBlock.evalContextType())
2156      , m_codeType(cachedCodeBlock.codeType())
2157  
2158      , m_didOptimize(static_cast<unsigned>(TriState::Indeterminate))
2159      , m_age(0)
2160      , m_hasCheckpoints(cachedCodeBlock.hasCheckpoints())
2161  
2162      , m_features(cachedCodeBlock.features())
2163      , m_parseMode(cachedCodeBlock.parseMode())
2164      , m_codeGenerationMode(cachedCodeBlock.codeGenerationMode())
2165  
2166      , m_lineCount(cachedCodeBlock.lineCount())
2167      , m_endColumn(cachedCodeBlock.endColumn())
2168      , m_numVars(cachedCodeBlock.numVars())
2169      , m_numCalleeLocals(cachedCodeBlock.numCalleeLocals())
2170      , m_numParameters(cachedCodeBlock.numParameters())
2171  
2172      , m_sourceURLDirective(cachedCodeBlock.sourceURLDirective(decoder))
2173      , m_sourceMappingURLDirective(cachedCodeBlock.sourceMappingURLDirective(decoder))
2174  
2175      , m_metadata(cachedCodeBlock.metadata(decoder))
2176      , m_instructions(cachedCodeBlock.instructions(decoder))
2177  
2178      , m_rareData(cachedCodeBlock.rareData(decoder))
2179  {
2180  }
2181  
2182  template<typename CodeBlockType>
2183  ALWAYS_INLINE void CachedCodeBlock<CodeBlockType>::decode(Decoder& decoder, UnlinkedCodeBlock& codeBlock) const
2184  {
2185      m_constantRegisters.decode(decoder, codeBlock.m_constantRegisters, &codeBlock);
2186      m_constantsSourceCodeRepresentation.decode(decoder, codeBlock.m_constantsSourceCodeRepresentation);
2187      m_expressionInfo.decode(decoder, codeBlock.m_expressionInfo);
2188      m_outOfLineJumpTargets.decode(decoder, codeBlock.m_outOfLineJumpTargets);
2189      m_jumpTargets.decode(decoder, codeBlock.m_jumpTargets);
2190      m_identifiers.decode(decoder, codeBlock.m_identifiers);
2191      m_functionDecls.decode(decoder, codeBlock.m_functionDecls, &codeBlock);
2192      m_functionExprs.decode(decoder, codeBlock.m_functionExprs, &codeBlock);
2193  }
2194  
2195  ALWAYS_INLINE UnlinkedProgramCodeBlock::UnlinkedProgramCodeBlock(Decoder& decoder, const CachedProgramCodeBlock& cachedCodeBlock)
2196      : Base(decoder, decoder.vm().unlinkedProgramCodeBlockStructure.get(), cachedCodeBlock)
2197  {
2198  }
2199  
2200  ALWAYS_INLINE UnlinkedModuleProgramCodeBlock::UnlinkedModuleProgramCodeBlock(Decoder& decoder, const CachedModuleCodeBlock& cachedCodeBlock)
2201      : Base(decoder, decoder.vm().unlinkedModuleProgramCodeBlockStructure.get(), cachedCodeBlock)
2202  {
2203  }
2204  
2205  ALWAYS_INLINE UnlinkedEvalCodeBlock::UnlinkedEvalCodeBlock(Decoder& decoder, const CachedEvalCodeBlock& cachedCodeBlock)
2206      : Base(decoder, decoder.vm().unlinkedEvalCodeBlockStructure.get(), cachedCodeBlock)
2207  {
2208  }
2209  
2210  ALWAYS_INLINE void CachedFunctionExecutable::encode(Encoder& encoder, const UnlinkedFunctionExecutable& executable)
2211  {
2212      m_mutableMetadata.m_features = executable.m_features;
2213      m_mutableMetadata.m_hasCapturedVariables = executable.m_hasCapturedVariables;
2214  
2215      m_firstLineOffset = executable.m_firstLineOffset;
2216      m_lineCount = executable.m_lineCount;
2217      m_unlinkedFunctionNameStart = executable.m_unlinkedFunctionNameStart;
2218      m_unlinkedBodyStartColumn = executable.m_unlinkedBodyStartColumn;
2219      m_unlinkedBodyEndColumn = executable.m_unlinkedBodyEndColumn;
2220      m_startOffset = executable.m_startOffset;
2221      m_sourceLength = executable.m_sourceLength;
2222      m_parametersStartOffset = executable.m_parametersStartOffset;
2223      m_typeProfilingStartOffset = executable.m_typeProfilingStartOffset;
2224      m_typeProfilingEndOffset = executable.m_typeProfilingEndOffset;
2225      m_parameterCount = executable.m_parameterCount;
2226  
2227      m_sourceParseMode = executable.m_sourceParseMode;
2228  
2229      m_isInStrictContext = executable.m_isInStrictContext;
2230      m_isBuiltinFunction = executable.m_isBuiltinFunction;
2231      m_isBuiltinDefaultClassConstructor = executable.m_isBuiltinDefaultClassConstructor;
2232      m_constructAbility = executable.m_constructAbility;
2233      m_constructorKind = executable.m_constructorKind;
2234      m_functionMode = executable.m_functionMode;
2235      m_scriptMode = executable.m_scriptMode;
2236      m_superBinding = executable.m_superBinding;
2237      m_derivedContextType = executable.m_derivedContextType;
2238      m_needsClassFieldInitializer = executable.m_needsClassFieldInitializer;
2239  
2240      m_rareData.encode(encoder, executable.m_rareData.get());
2241  
2242      m_name.encode(encoder, executable.name());
2243      m_ecmaName.encode(encoder, executable.ecmaName());
2244  
2245      m_unlinkedCodeBlockForCall.encode(encoder, executable.m_unlinkedCodeBlockForCall);
2246      m_unlinkedCodeBlockForConstruct.encode(encoder, executable.m_unlinkedCodeBlockForConstruct);
2247  
2248      if (!executable.m_unlinkedCodeBlockForCall || !executable.m_unlinkedCodeBlockForConstruct)
2249          encoder.addLeafExecutable(&executable, encoder.offsetOf(this));
2250  }
2251  
2252  ALWAYS_INLINE UnlinkedFunctionExecutable* CachedFunctionExecutable::decode(Decoder& decoder) const
2253  {
2254      UnlinkedFunctionExecutable* executable = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(decoder.vm().heap)) UnlinkedFunctionExecutable(decoder, *this);
2255      executable->finishCreation(decoder.vm());
2256      return executable;
2257  }
2258  
2259  ALWAYS_INLINE UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(Decoder& decoder, const CachedFunctionExecutable& cachedExecutable)
2260      : Base(decoder.vm(), decoder.vm().unlinkedFunctionExecutableStructure.get())
2261      , m_firstLineOffset(cachedExecutable.firstLineOffset())
2262      , m_isInStrictContext(cachedExecutable.isInStrictContext())
2263      , m_lineCount(cachedExecutable.lineCount())
2264      , m_hasCapturedVariables(cachedExecutable.hasCapturedVariables())
2265      , m_unlinkedFunctionNameStart(cachedExecutable.unlinkedFunctionNameStart())
2266      , m_isBuiltinFunction(cachedExecutable.isBuiltinFunction())
2267      , m_unlinkedBodyStartColumn(cachedExecutable.unlinkedBodyStartColumn())
2268      , m_isBuiltinDefaultClassConstructor(cachedExecutable.isBuiltinDefaultClassConstructor())
2269      , m_unlinkedBodyEndColumn(cachedExecutable.unlinkedBodyEndColumn())
2270      , m_constructAbility(cachedExecutable.constructAbility())
2271      , m_startOffset(cachedExecutable.startOffset())
2272      , m_scriptMode(cachedExecutable.scriptMode())
2273      , m_sourceLength(cachedExecutable.sourceLength())
2274      , m_superBinding(cachedExecutable.superBinding())
2275      , m_parametersStartOffset(cachedExecutable.parametersStartOffset())
2276      , m_isCached(false)
2277      , m_typeProfilingStartOffset(cachedExecutable.typeProfilingStartOffset())
2278      , m_typeProfilingEndOffset(cachedExecutable.typeProfilingEndOffset())
2279      , m_parameterCount(cachedExecutable.parameterCount())
2280      , m_features(cachedExecutable.features())
2281      , m_sourceParseMode(cachedExecutable.sourceParseMode())
2282      , m_constructorKind(cachedExecutable.constructorKind())
2283      , m_functionMode(cachedExecutable.functionMode())
2284      , m_derivedContextType(cachedExecutable.derivedContextType())
2285      , m_isGeneratedFromCache(true)
2286      , m_needsClassFieldInitializer(cachedExecutable.needsClassFieldInitializer())
2287      , m_unlinkedCodeBlockForCall()
2288      , m_unlinkedCodeBlockForConstruct()
2289  
2290      , m_name(cachedExecutable.name(decoder))
2291      , m_ecmaName(cachedExecutable.ecmaName(decoder))
2292  
2293      , m_rareData(cachedExecutable.rareData(decoder))
2294  {
2295  
2296      uint32_t leafExecutables = 2;
2297      auto checkBounds = [&](int32_t& codeBlockOffset, auto& cachedPtr) {
2298          if (!cachedPtr.isEmpty()) {
2299              ptrdiff_t offset = decoder.offsetOf(&cachedPtr);
2300              if (static_cast<size_t>(offset) < decoder.size()) {
2301                  codeBlockOffset = offset;
2302                  m_isCached = true;
2303                  leafExecutables--;
2304                  return;
2305              }
2306          }
2307  
2308          codeBlockOffset = 0;
2309      };
2310  
2311      if (!cachedExecutable.unlinkedCodeBlockForCall().isEmpty() || !cachedExecutable.unlinkedCodeBlockForConstruct().isEmpty()) {
2312          checkBounds(m_cachedCodeBlockForCallOffset, cachedExecutable.unlinkedCodeBlockForCall());
2313          checkBounds(m_cachedCodeBlockForConstructOffset, cachedExecutable.unlinkedCodeBlockForConstruct());
2314          if (m_isCached)
2315              m_decoder = &decoder;
2316          else
2317              m_decoder = nullptr;
2318      }
2319  
2320      if (leafExecutables)
2321          decoder.addLeafExecutable(this, decoder.offsetOf(&cachedExecutable));
2322  }
2323  
2324  template<typename CodeBlockType>
2325  ALWAYS_INLINE void CachedCodeBlock<CodeBlockType>::encode(Encoder& encoder, const UnlinkedCodeBlock& codeBlock)
2326  {
2327      m_thisRegister = codeBlock.m_thisRegister;
2328      m_scopeRegister = codeBlock.m_scopeRegister;
2329      m_usesEval = codeBlock.m_usesEval;
2330      m_isConstructor = codeBlock.m_isConstructor;
2331      m_hasCapturedVariables = codeBlock.m_hasCapturedVariables;
2332      m_isBuiltinFunction = codeBlock.m_isBuiltinFunction;
2333      m_superBinding = codeBlock.m_superBinding;
2334      m_scriptMode = codeBlock.m_scriptMode;
2335      m_isArrowFunctionContext = codeBlock.m_isArrowFunctionContext;
2336      m_isClassContext = codeBlock.m_isClassContext;
2337      m_hasTailCalls = codeBlock.m_hasTailCalls;
2338      m_constructorKind = codeBlock.m_constructorKind;
2339      m_derivedContextType = codeBlock.m_derivedContextType;
2340      m_evalContextType = codeBlock.m_evalContextType;
2341      m_lineCount = codeBlock.m_lineCount;
2342      m_endColumn = codeBlock.m_endColumn;
2343      m_numVars = codeBlock.m_numVars;
2344      m_numCalleeLocals = codeBlock.m_numCalleeLocals;
2345      m_numParameters = codeBlock.m_numParameters;
2346      m_features = codeBlock.m_features;
2347      m_parseMode = codeBlock.m_parseMode;
2348      m_codeGenerationMode = codeBlock.m_codeGenerationMode;
2349      m_codeType = codeBlock.m_codeType;
2350      m_hasCheckpoints = codeBlock.m_hasCheckpoints;
2351  
2352      m_metadata.encode(encoder, codeBlock.m_metadata.get());
2353      m_rareData.encode(encoder, codeBlock.m_rareData.get());
2354  
2355      m_sourceURLDirective.encode(encoder, codeBlock.m_sourceURLDirective.get());
2356      m_sourceMappingURLDirective.encode(encoder, codeBlock.m_sourceURLDirective.get());
2357  
2358      m_instructions.encode(encoder, codeBlock.m_instructions.get());
2359      m_constantRegisters.encode(encoder, codeBlock.m_constantRegisters);
2360      m_constantsSourceCodeRepresentation.encode(encoder, codeBlock.m_constantsSourceCodeRepresentation);
2361      m_expressionInfo.encode(encoder, codeBlock.m_expressionInfo);
2362      m_jumpTargets.encode(encoder, codeBlock.m_jumpTargets);
2363      m_outOfLineJumpTargets.encode(encoder, codeBlock.m_outOfLineJumpTargets);
2364  
2365      m_identifiers.encode(encoder, codeBlock.m_identifiers);
2366      m_functionDecls.encode(encoder, codeBlock.m_functionDecls);
2367      m_functionExprs.encode(encoder, codeBlock.m_functionExprs);
2368  }
2369  
2370  class CachedSourceCodeKey : public CachedObject<SourceCodeKey> {
2371  public:
2372      void encode(Encoder& encoder, const SourceCodeKey& key)
2373      {
2374          m_sourceCode.encode(encoder, key.m_sourceCode);
2375          m_name.encode(encoder, key.m_name);
2376          m_flags = key.m_flags.m_flags;
2377          m_hash = key.hash();
2378          m_functionConstructorParametersEndPosition = key.m_functionConstructorParametersEndPosition;
2379      }
2380  
2381      void decode(Decoder& decoder, SourceCodeKey& key) const
2382      {
2383          m_sourceCode.decode(decoder, key.m_sourceCode);
2384          m_name.decode(decoder, key.m_name);
2385          key.m_flags.m_flags = m_flags;
2386          key.m_hash = m_hash;
2387          key.m_functionConstructorParametersEndPosition = m_functionConstructorParametersEndPosition;
2388      }
2389  
2390  private:
2391      CachedUnlinkedSourceCode m_sourceCode;
2392      CachedString m_name;
2393      unsigned m_flags;
2394      unsigned m_hash;
2395      int m_functionConstructorParametersEndPosition;
2396  };
2397  
2398  class GenericCacheEntry {
2399  public:
2400      bool decode(Decoder&, std::pair<SourceCodeKey, UnlinkedCodeBlock*>&) const;
2401      bool isStillValid(Decoder&, const SourceCodeKey&, CachedCodeBlockTag) const;
2402  
2403  protected:
2404      GenericCacheEntry(Encoder& encoder, CachedCodeBlockTag tag)
2405          : m_tag(tag)
2406      {
2407          m_bootSessionUUID.encode(encoder, bootSessionUUIDString());
2408      }
2409  
2410      CachedCodeBlockTag tag() const { return m_tag; }
2411  
2412      bool isUpToDate(Decoder& decoder) const
2413      {
2414          if (m_cacheVersion != jscBytecodeCacheVersion())
2415              return false;
2416          if (m_bootSessionUUID.decode(decoder) != bootSessionUUIDString())
2417              return false;
2418          return true;
2419      }
2420  
2421  private:
2422      uint32_t m_cacheVersion { jscBytecodeCacheVersion() };
2423      CachedString m_bootSessionUUID;
2424      CachedCodeBlockTag m_tag;
2425  };
2426  
2427  static_assert(alignof(GenericCacheEntry) <= alignof(std::max_align_t));
2428  
2429  template<typename UnlinkedCodeBlockType>
2430  class CacheEntry : public GenericCacheEntry {
2431  public:
2432      CacheEntry(Encoder& encoder)
2433          : GenericCacheEntry(encoder, CachedCodeBlockTypeImpl<UnlinkedCodeBlockType>::tag)
2434      {
2435      }
2436  
2437      void encode(Encoder& encoder, std::pair<SourceCodeKey, const UnlinkedCodeBlockType*> pair)
2438      {
2439          m_key.encode(encoder, pair.first);
2440          m_codeBlock.encode(encoder, pair.second);
2441      }
2442  
2443  private:
2444      friend GenericCacheEntry;
2445  
2446      bool isStillValid(Decoder& decoder, const SourceCodeKey& key) const
2447      {
2448          SourceCodeKey decodedKey;
2449          m_key.decode(decoder, decodedKey);
2450          return decodedKey == key;
2451      }
2452  
2453      bool decode(Decoder& decoder, std::pair<SourceCodeKey, UnlinkedCodeBlockType*>& result) const
2454      {
2455          ASSERT(tag() == CachedCodeBlockTypeImpl<UnlinkedCodeBlockType>::tag);
2456          SourceCodeKey decodedKey;
2457          m_key.decode(decoder, decodedKey);
2458          result = { WTFMove(decodedKey), m_codeBlock.decode(decoder) };
2459          return true;
2460      }
2461  
2462      CachedSourceCodeKey m_key;
2463      CachedPtr<CachedCodeBlockType<UnlinkedCodeBlockType>> m_codeBlock;
2464  };
2465  
2466  static_assert(alignof(CacheEntry<UnlinkedProgramCodeBlock>) <= alignof(std::max_align_t));
2467  static_assert(alignof(CacheEntry<UnlinkedModuleProgramCodeBlock>) <= alignof(std::max_align_t));
2468  
2469  bool GenericCacheEntry::decode(Decoder& decoder, std::pair<SourceCodeKey, UnlinkedCodeBlock*>& result) const
2470  {
2471      if (!isUpToDate(decoder))
2472          return false;
2473  
2474      switch (m_tag) {
2475      case CachedProgramCodeBlockTag:
2476          return bitwise_cast<const CacheEntry<UnlinkedProgramCodeBlock>*>(this)->decode(decoder, reinterpret_cast<std::pair<SourceCodeKey, UnlinkedProgramCodeBlock*>&>(result));
2477      case CachedModuleCodeBlockTag:
2478          return bitwise_cast<const CacheEntry<UnlinkedModuleProgramCodeBlock>*>(this)->decode(decoder, reinterpret_cast<std::pair<SourceCodeKey, UnlinkedModuleProgramCodeBlock*>&>(result));
2479      case CachedEvalCodeBlockTag:
2480          // We do not cache eval code blocks
2481          RELEASE_ASSERT_NOT_REACHED();
2482      }
2483      RELEASE_ASSERT_NOT_REACHED();
2484  #if COMPILER(MSVC)
2485      // Without this, MSVC will complain that this path does not return a value.
2486      return false;
2487  #endif
2488  }
2489  
2490  bool GenericCacheEntry::isStillValid(Decoder& decoder, const SourceCodeKey& key, CachedCodeBlockTag tag) const
2491  {
2492      if (!isUpToDate(decoder))
2493          return false;
2494  
2495      switch (tag) {
2496      case CachedProgramCodeBlockTag:
2497          return bitwise_cast<const CacheEntry<UnlinkedProgramCodeBlock>*>(this)->isStillValid(decoder, key);
2498      case CachedModuleCodeBlockTag:
2499          return bitwise_cast<const CacheEntry<UnlinkedModuleProgramCodeBlock>*>(this)->isStillValid(decoder, key);
2500      case CachedEvalCodeBlockTag:
2501          // We do not cache eval code blocks
2502          RELEASE_ASSERT_NOT_REACHED();
2503      }
2504      RELEASE_ASSERT_NOT_REACHED();
2505      return false;
2506  }
2507  
2508  template<typename UnlinkedCodeBlockType>
2509  void encodeCodeBlock(Encoder& encoder, const SourceCodeKey& key, const UnlinkedCodeBlock* codeBlock)
2510  {
2511      auto* entry = encoder.template malloc<CacheEntry<UnlinkedCodeBlockType>>(encoder);
2512      entry->encode(encoder, { key, jsCast<const UnlinkedCodeBlockType*>(codeBlock) });
2513  }
2514  
2515  RefPtr<CachedBytecode> encodeCodeBlock(VM& vm, const SourceCodeKey& key, const UnlinkedCodeBlock* codeBlock, FileSystem::PlatformFileHandle fd, BytecodeCacheError& error)
2516  {
2517      const ClassInfo* classInfo = codeBlock->classInfo(vm);
2518  
2519      Encoder encoder(vm, fd);
2520      if (classInfo == UnlinkedProgramCodeBlock::info())
2521          encodeCodeBlock<UnlinkedProgramCodeBlock>(encoder, key, codeBlock);
2522      else if (classInfo == UnlinkedModuleProgramCodeBlock::info())
2523          encodeCodeBlock<UnlinkedModuleProgramCodeBlock>(encoder, key, codeBlock);
2524      else
2525          ASSERT(classInfo == UnlinkedEvalCodeBlock::info());
2526  
2527      return encoder.release(error);
2528  }
2529  
2530  RefPtr<CachedBytecode> encodeCodeBlock(VM& vm, const SourceCodeKey& key, const UnlinkedCodeBlock* codeBlock)
2531  {
2532      BytecodeCacheError error;
2533      return encodeCodeBlock(vm, key, codeBlock, FileSystem::invalidPlatformFileHandle, error);
2534  }
2535  
2536  RefPtr<CachedBytecode> encodeFunctionCodeBlock(VM& vm, const UnlinkedFunctionCodeBlock* codeBlock, BytecodeCacheError& error)
2537  {
2538      Encoder encoder(vm);
2539      encoder.malloc<CachedFunctionCodeBlock>()->encode(encoder, *codeBlock);
2540      return encoder.release(error);
2541  }
2542  
2543  UnlinkedCodeBlock* decodeCodeBlockImpl(VM& vm, const SourceCodeKey& key, Ref<CachedBytecode> cachedBytecode)
2544  {
2545      const auto* cachedEntry = bitwise_cast<const GenericCacheEntry*>(cachedBytecode->data());
2546      Ref<Decoder> decoder = Decoder::create(vm, WTFMove(cachedBytecode), &key.source().provider());
2547      std::pair<SourceCodeKey, UnlinkedCodeBlock*> entry;
2548      {
2549          DeferGC deferGC(vm.heap);
2550          if (!cachedEntry->decode(decoder.get(), entry))
2551              return nullptr;
2552      }
2553  
2554      if (entry.first != key)
2555          return nullptr;
2556      return entry.second;
2557  }
2558  
2559  bool isCachedBytecodeStillValid(VM& vm, Ref<CachedBytecode> cachedBytecode, const SourceCodeKey& key, SourceCodeType type)
2560  {
2561      const void* buffer = cachedBytecode->data();
2562      size_t size = cachedBytecode->size();
2563      if (!size)
2564          return false;
2565      const auto* cachedEntry = bitwise_cast<const GenericCacheEntry*>(buffer);
2566      Ref<Decoder> decoder = Decoder::create(vm, WTFMove(cachedBytecode));
2567      return cachedEntry->isStillValid(decoder.get(), key, tagFromSourceCodeType(type));
2568  }
2569  
2570  void decodeFunctionCodeBlock(Decoder& decoder, int32_t cachedFunctionCodeBlockOffset, WriteBarrier<UnlinkedFunctionCodeBlock>& codeBlock, const JSCell* owner)
2571  {
2572      ASSERT(decoder.vm().heap.isDeferred());
2573      auto* cachedCodeBlock = static_cast<const CachedWriteBarrier<CachedFunctionCodeBlock, UnlinkedFunctionCodeBlock>*>(decoder.ptrForOffsetFromBase(cachedFunctionCodeBlockOffset));
2574      cachedCodeBlock->decode(decoder, codeBlock, owner);
2575  }
2576  
2577  } // namespace JSC