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