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