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