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