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