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