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