[go: nahoru, domu]

View | Details | Raw Unified | Return to bug 192782 | Differences between
and this patch

Collapse All | Expand All

(-)a/Source/JavaScriptCore/ChangeLog (+176 lines)
Lines 1-3 Link Here
1
2018-12-17  Tadeu Zagallo  <tzagallo@apple.com>
2
3
        Cache bytecode to disk
4
        https://bugs.webkit.org/show_bug.cgi?id=192782
5
        <rdar://problem/46084932>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        * JavaScriptCore.xcodeproj/project.pbxproj:
10
        * builtins/BuiltinNames.cpp:
11
        (JSC::BuiltinNames::BuiltinNames):
12
        * builtins/BuiltinNames.h:
13
        * bytecode/CodeBlock.cpp:
14
        (JSC::CodeBlock::setConstantIdentifierSetRegisters):
15
        * bytecode/CodeBlock.h:
16
        * bytecode/HandlerInfo.h:
17
        (JSC::UnlinkedHandlerInfo::UnlinkedHandlerInfo):
18
        * bytecode/InstructionStream.h:
19
        * bytecode/UnlinkedCodeBlock.h:
20
        (JSC::UnlinkedCodeBlock::addSetConstant):
21
        (JSC::UnlinkedCodeBlock::constantIdentifierSets):
22
        * bytecode/UnlinkedEvalCodeBlock.h:
23
        * bytecode/UnlinkedFunctionCodeBlock.h:
24
        * bytecode/UnlinkedFunctionExecutable.h:
25
        * bytecode/UnlinkedGlobalCodeBlock.h:
26
        (JSC::UnlinkedGlobalCodeBlock::UnlinkedGlobalCodeBlock):
27
        * bytecode/UnlinkedMetadataTable.h:
28
        * bytecode/UnlinkedModuleProgramCodeBlock.h:
29
        * bytecode/UnlinkedProgramCodeBlock.h:
30
        * interpreter/Interpreter.cpp:
31
        (JSC::Interpreter::executeProgram):
32
        * parser/SourceCode.h:
33
        * parser/SourceCodeKey.h:
34
        (JSC::SourceCodeKey::operator!= const):
35
        * parser/UnlinkedSourceCode.h:
36
        * parser/VariableEnvironment.h:
37
        * runtime/CachedTypes.h: Added.
38
        (JSC::Encoder::Encoder):
39
        (JSC::Encoder::~Encoder):
40
        (JSC::Encoder::vm):
41
        (JSC::Encoder::buffer const):
42
        (JSC::Encoder::size const):
43
        (JSC::Encoder::mallocOffset):
44
        (JSC::Encoder::malloc):
45
        (JSC::Encoder::offsetOf):
46
        (JSC::Encoder::cachePtr):
47
        (JSC::Encoder::offsetForPtr):
48
        (JSC::Decoder::Decoder):
49
        (JSC::Decoder::~Decoder):
50
        (JSC::Decoder::vm):
51
        (JSC::Decoder::offsetOf):
52
        (JSC::Decoder::cacheOffset):
53
        (JSC::Decoder::addFinalizer):
54
        (JSC::encode):
55
        (JSC::decode):
56
        (JSC::CachedObject::sizeOf):
57
        (JSC::CachedObject::cast):
58
        (JSC::VariableLengthObject::buffer const):
59
        (JSC::VariableLengthObject::buffer):
60
        (JSC::VariableLengthObject::allocate):
61
        (JSC::CachedPtr::encode):
62
        (JSC::CachedPtr::decode const):
63
        (JSC::CachedPtr::operator->):
64
        (JSC::CachedPtr::operator-> const):
65
        (JSC::CachedRefPtr::encode):
66
        (JSC::CachedRefPtr::decode const):
67
        (JSC::CachedWriteBarrier::encode):
68
        (JSC::CachedWriteBarrier::decode const):
69
        (JSC::CachedVector::encode):
70
        (JSC::CachedVector::decode const):
71
        (JSC::CachedPair::encode):
72
        (JSC::CachedPair::decode const):
73
        (JSC::CachedHashMap::encode):
74
        (JSC::CachedHashMap::decode const):
75
        (JSC::CachedUniquedStringImpl::encode):
76
        (JSC::CachedUniquedStringImpl::decode const):
77
        (JSC::CachedStringImpl::encode):
78
        (JSC::CachedStringImpl::decode const):
79
        (JSC::CachedString::encode):
80
        (JSC::CachedString::decode const):
81
        (JSC::CachedIdentifier::encode):
82
        (JSC::CachedIdentifier::decode const):
83
        (JSC::CachedOptional::encode):
84
        (JSC::CachedOptional::decode const):
85
        (JSC::CachedOptional::decodeAsPtr const):
86
        (JSC::CachedSimpleJumpTable::encode):
87
        (JSC::CachedSimpleJumpTable::decode const):
88
        (JSC::CachedStringJumpTable::encode):
89
        (JSC::CachedStringJumpTable::decode const):
90
        (JSC::CachedRareData::encode):
91
        (JSC::CachedRareData::decode const):
92
        (JSC::CachedBitVector::encode):
93
        (JSC::CachedBitVector::decode const):
94
        (JSC::CachedHashSet::encode):
95
        (JSC::CachedHashSet::decode const):
96
        (JSC::CachedConstantIdentifierSetEntry::encode):
97
        (JSC::CachedConstantIdentifierSetEntry::decode const):
98
        (JSC::CachedVariableEnvironment::encode):
99
        (JSC::CachedVariableEnvironment::decode const):
100
        (JSC::CachedArray::encode):
101
        (JSC::CachedArray::decode const):
102
        (JSC::CachedScopedArgumentsTable::encode):
103
        (JSC::CachedScopedArgumentsTable::decode const):
104
        (JSC::CachedSymbolTableEntry::encode):
105
        (JSC::CachedSymbolTableEntry::decode const):
106
        (JSC::CachedSymbolTable::encode):
107
        (JSC::CachedSymbolTable::decode const):
108
        (JSC::CachedImmutableButterfly::encode):
109
        (JSC::CachedImmutableButterfly::decode const):
110
        (JSC::CachedRegExp::encode):
111
        (JSC::CachedRegExp::decode const):
112
        (JSC::CachedTemplateObjectDescriptor::encode):
113
        (JSC::CachedTemplateObjectDescriptor::decode const):
114
        (JSC::CachedBigInt::encode):
115
        (JSC::CachedBigInt::decode const):
116
        (JSC::CachedJSValue::encode):
117
        (JSC::CachedJSValue::decode const):
118
        (JSC::CachedInstructionStream::encode):
119
        (JSC::CachedInstructionStream::decode const):
120
        (JSC::CachedMetadataTable::encode):
121
        (JSC::CachedMetadataTable::decode const):
122
        (JSC::CachedSourceOrigin::encode):
123
        (JSC::CachedSourceOrigin::decode const):
124
        (JSC::CachedTextPosition::encode):
125
        (JSC::CachedTextPosition::decode const):
126
        (JSC::CachedSourceProviderShape::encode):
127
        (JSC::CachedSourceProviderShape::decode const):
128
        (JSC::CachedStringSourceProvider::encode):
129
        (JSC::CachedStringSourceProvider::decode const):
130
        (JSC::CachedWebAssemblySourceProvider::encode):
131
        (JSC::CachedWebAssemblySourceProvider::decode const):
132
        (JSC::CachedSourceProvider::encode):
133
        (JSC::CachedSourceProvider::decode const):
134
        (JSC::CachedUnlinkedSourceCodeShape::encode):
135
        (JSC::CachedUnlinkedSourceCodeShape::decode const):
136
        (JSC::CachedSourceCode::encode):
137
        (JSC::CachedSourceCode::decode const):
138
        (JSC::CachedProgramCodeBlock::encode):
139
        (JSC::CachedProgramCodeBlock::decode const):
140
        (JSC::CachedModuleCodeBlock::encode):
141
        (JSC::CachedModuleCodeBlock::decode const):
142
        (JSC::CachedEvalCodeBlock::encode):
143
        (JSC::CachedEvalCodeBlock::decode const):
144
        (JSC::CachedFunctionCodeBlock::encode):
145
        (JSC::CachedFunctionCodeBlock::decode const):
146
        (JSC::UnlinkedFunctionCodeBlock::UnlinkedFunctionCodeBlock):
147
        (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
148
        (JSC::CachedCodeBlockType>::decode const):
149
        (JSC::UnlinkedProgramCodeBlock::UnlinkedProgramCodeBlock):
150
        (JSC::UnlinkedModuleProgramCodeBlock::UnlinkedModuleProgramCodeBlock):
151
        (JSC::UnlinkedEvalCodeBlock::UnlinkedEvalCodeBlock):
152
        (JSC::CachedFunctionExecutable::encode):
153
        (JSC::CachedFunctionExecutable::decode const):
154
        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
155
        (JSC::CachedCodeBlockType>::encode):
156
        (JSC::CachedSourceCodeKey::encode):
157
        (JSC::CachedSourceCodeKey::decode const):
158
        (JSC::CacheEntry::encode):
159
        (JSC::CacheEntry:: const):
160
        (JSC::encodeCodeBlock):
161
        * runtime/CodeCache.cpp:
162
        (JSC::CodeCache::getUnlinkedGlobalCodeBlock):
163
        (JSC::CodeCache::getUnlinkedGlobalFunctionExecutable):
164
        (JSC::CodeCache::write):
165
        * runtime/CodeCache.h:
166
        (JSC::CodeCacheMap::begin):
167
        (JSC::CodeCacheMap::end):
168
        (JSC::CodeCacheMap::findCacheAndUpdateAge):
169
        * runtime/JSBigInt.cpp:
170
        (JSC::JSBigInt::offsetOfData): Deleted.
171
        (JSC::JSBigInt::dataStorage): Deleted.
172
        * runtime/JSBigInt.h:
173
        * runtime/RegExp.h:
174
        * runtime/ScopedArgumentsTable.h:
175
        * runtime/SymbolTable.h:
176
1
2018-10-31  Devin Rousso  <drousso@apple.com>
177
2018-10-31  Devin Rousso  <drousso@apple.com>
2
178
3
        Web Inspector: Canvas: create a setting for auto-recording newly created contexts
179
        Web Inspector: Canvas: create a setting for auto-recording newly created contexts
(-)a/Source/WTF/ChangeLog (+10 lines)
Lines 1-3 Link Here
1
2018-12-17  Tadeu Zagallo  <tzagallo@apple.com>
2
3
        Cache bytecode to disk
4
        https://bugs.webkit.org/show_bug.cgi?id=192782
5
        <rdar://problem/46084932>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        * wtf/BitVector.h:
10
1
2018-10-30  Don Olmstead  <don.olmstead@sony.com>
11
2018-10-30  Don Olmstead  <don.olmstead@sony.com>
2
12
3
        [PlayStation] Enable JavaScriptCore
13
        [PlayStation] Enable JavaScriptCore
(-)a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (+2 lines)
Lines 3139-3144 Link Here
3139
		14386A731DD69895008652C4 /* DirectEvalExecutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectEvalExecutable.h; sourceTree = "<group>"; };
3139
		14386A731DD69895008652C4 /* DirectEvalExecutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectEvalExecutable.h; sourceTree = "<group>"; };
3140
		14386A761DD6989C008652C4 /* IndirectEvalExecutable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndirectEvalExecutable.cpp; sourceTree = "<group>"; };
3140
		14386A761DD6989C008652C4 /* IndirectEvalExecutable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndirectEvalExecutable.cpp; sourceTree = "<group>"; };
3141
		14386A771DD6989C008652C4 /* IndirectEvalExecutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndirectEvalExecutable.h; sourceTree = "<group>"; };
3141
		14386A771DD6989C008652C4 /* IndirectEvalExecutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndirectEvalExecutable.h; sourceTree = "<group>"; };
3142
		143BE26521C857770020CD17 /* CachedTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedTypes.h; sourceTree = "<group>"; };
3142
		1440051F0A531D3B0005F061 /* Node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Node.h; path = tests/Node.h; sourceTree = "<group>"; };
3143
		1440051F0A531D3B0005F061 /* Node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Node.h; path = tests/Node.h; sourceTree = "<group>"; };
3143
		144005200A531D3B0005F061 /* Node.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Node.c; path = tests/Node.c; sourceTree = "<group>"; };
3144
		144005200A531D3B0005F061 /* Node.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Node.c; path = tests/Node.c; sourceTree = "<group>"; };
3144
		144007480A536CC20005F061 /* NodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NodeList.h; path = tests/NodeList.h; sourceTree = "<group>"; };
3145
		144007480A536CC20005F061 /* NodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NodeList.h; path = tests/NodeList.h; sourceTree = "<group>"; };
Lines 6568-6573 Link Here
6568
				9E729409190F0306001A91B5 /* BundlePath.mm */,
6569
				9E729409190F0306001A91B5 /* BundlePath.mm */,
6569
				0FB7F38B15ED8E3800F167B2 /* Butterfly.h */,
6570
				0FB7F38B15ED8E3800F167B2 /* Butterfly.h */,
6570
				0FB7F38C15ED8E3800F167B2 /* ButterflyInlines.h */,
6571
				0FB7F38C15ED8E3800F167B2 /* ButterflyInlines.h */,
6572
				143BE26521C857770020CD17 /* CachedTypes.h */,
6571
				0FEC3C5F1F379F5300F59B6C /* CagedBarrierPtr.h */,
6573
				0FEC3C5F1F379F5300F59B6C /* CagedBarrierPtr.h */,
6572
				BCA62DFE0E2826230004F30D /* CallData.cpp */,
6574
				BCA62DFE0E2826230004F30D /* CallData.cpp */,
6573
				145C507F0D9DF63B0088F6B9 /* CallData.h */,
6575
				145C507F0D9DF63B0088F6B9 /* CallData.h */,
(-)a/Source/JavaScriptCore/builtins/BuiltinNames.cpp (+1 lines)
Lines 63-68 BuiltinNames::BuiltinNames(VM* vm, CommonIdentifiers* commonIdentifiers) Link Here
63
    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PRIVATE_TO_PUBLIC_ENTRY)
63
    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PRIVATE_TO_PUBLIC_ENTRY)
64
    JSC_FOREACH_BUILTIN_FUNCTION_NAME(INITIALIZE_PUBLIC_TO_PRIVATE_ENTRY)
64
    JSC_FOREACH_BUILTIN_FUNCTION_NAME(INITIALIZE_PUBLIC_TO_PRIVATE_ENTRY)
65
    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PUBLIC_TO_PRIVATE_ENTRY)
65
    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PUBLIC_TO_PRIVATE_ENTRY)
66
    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(INITIALIZE_SYMBOL_PRIVATE_TO_PUBLIC_ENTRY)
66
    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(INITIALIZE_SYMBOL_PUBLIC_TO_PRIVATE_ENTRY)
67
    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(INITIALIZE_SYMBOL_PUBLIC_TO_PRIVATE_ENTRY)
67
    m_privateToPublicMap.add(m_dollarVMPrivateName.impl(), &m_dollarVMName);
68
    m_privateToPublicMap.add(m_dollarVMPrivateName.impl(), &m_dollarVMName);
68
    m_publicToPrivateMap.add(m_dollarVMName.impl(), &m_dollarVMPrivateName);
69
    m_publicToPrivateMap.add(m_dollarVMName.impl(), &m_dollarVMPrivateName);
(-)a/Source/JavaScriptCore/builtins/BuiltinNames.h (+1 lines)
Lines 213-218 extern SymbolImpl::StaticSymbolImpl polyProtoPrivateName; Link Here
213
// We commandeer the publicToPrivateMap to allow us to convert private symbol names into the appropriate symbol.
213
// We commandeer the publicToPrivateMap to allow us to convert private symbol names into the appropriate symbol.
214
// e.g. @iteratorSymbol points to Symbol.iterator in this map rather than to a an actual private name.
214
// e.g. @iteratorSymbol points to Symbol.iterator in this map rather than to a an actual private name.
215
// FIXME: This is a weird hack and we shouldn't need to do this.
215
// FIXME: This is a weird hack and we shouldn't need to do this.
216
#define INITIALIZE_SYMBOL_PRIVATE_TO_PUBLIC_ENTRY(name) m_privateToPublicMap.add(m_##name##Symbol.impl(), &m_##name##SymbolPrivateIdentifier);
216
#define INITIALIZE_SYMBOL_PUBLIC_TO_PRIVATE_ENTRY(name) m_publicToPrivateMap.add(m_##name##SymbolPrivateIdentifier.impl(), &m_##name##Symbol);
217
#define INITIALIZE_SYMBOL_PUBLIC_TO_PRIVATE_ENTRY(name) m_publicToPrivateMap.add(m_##name##SymbolPrivateIdentifier.impl(), &m_##name##Symbol);
217
218
218
class BuiltinNames {
219
class BuiltinNames {
(-)a/Source/JavaScriptCore/bytecode/CodeBlock.cpp (-1 / +1 lines)
Lines 860-866 CodeBlock::~CodeBlock() Link Here
860
#endif // ENABLE(JIT)
860
#endif // ENABLE(JIT)
861
}
861
}
862
862
863
void CodeBlock::setConstantIdentifierSetRegisters(VM& vm, const Vector<ConstantIndentifierSetEntry>& constants)
863
void CodeBlock::setConstantIdentifierSetRegisters(VM& vm, const Vector<ConstantIdentifierSetEntry>& constants)
864
{
864
{
865
    auto scope = DECLARE_THROW_SCOPE(vm);
865
    auto scope = DECLARE_THROW_SCOPE(vm);
866
    JSGlobalObject* globalObject = m_globalObject.get();
866
    JSGlobalObject* globalObject = m_globalObject.get();
(-)a/Source/JavaScriptCore/bytecode/CodeBlock.h (-1 / +1 lines)
Lines 891-897 private: Link Here
891
891
892
    void updateAllPredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles);
892
    void updateAllPredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles);
893
893
894
    void setConstantIdentifierSetRegisters(VM&, const Vector<ConstantIndentifierSetEntry>& constants);
894
    void setConstantIdentifierSetRegisters(VM&, const Vector<ConstantIdentifierSetEntry>& constants);
895
895
896
    void setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation);
896
    void setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation);
897
897
(-)a/Source/JavaScriptCore/bytecode/HandlerInfo.h (+4 lines)
Lines 89-94 struct HandlerInfoBase { Link Here
89
};
89
};
90
90
91
struct UnlinkedHandlerInfo : public HandlerInfoBase {
91
struct UnlinkedHandlerInfo : public HandlerInfoBase {
92
    UnlinkedHandlerInfo()
93
    {
94
    }
95
92
    UnlinkedHandlerInfo(uint32_t start, uint32_t end, uint32_t target, HandlerType handlerType)
96
    UnlinkedHandlerInfo(uint32_t start, uint32_t end, uint32_t target, HandlerType handlerType)
93
    {
97
    {
94
        this->start = start;
98
        this->start = start;
(-)a/Source/JavaScriptCore/bytecode/InstructionStream.h (+1 lines)
Lines 39-44 class InstructionStream { Link Here
39
    using InstructionBuffer = Vector<uint8_t, 0, UnsafeVectorOverflow>;
39
    using InstructionBuffer = Vector<uint8_t, 0, UnsafeVectorOverflow>;
40
40
41
    friend class InstructionStreamWriter;
41
    friend class InstructionStreamWriter;
42
    friend struct CachedInstructionStream;
42
public:
43
public:
43
    size_t sizeInBytes() const;
44
    size_t sizeInBytes() const;
44
45
(-)a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (-4 / +14 lines)
Lines 65-76 class UnlinkedFunctionCodeBlock; Link Here
65
class UnlinkedFunctionExecutable;
65
class UnlinkedFunctionExecutable;
66
struct ExecutableInfo;
66
struct ExecutableInfo;
67
67
68
template<typename CodeBlockType, typename CachedCodeBlockType>
69
struct CachedCodeBlock;
70
68
typedef unsigned UnlinkedValueProfile;
71
typedef unsigned UnlinkedValueProfile;
69
typedef unsigned UnlinkedArrayProfile;
72
typedef unsigned UnlinkedArrayProfile;
70
typedef unsigned UnlinkedArrayAllocationProfile;
73
typedef unsigned UnlinkedArrayAllocationProfile;
71
typedef unsigned UnlinkedObjectAllocationProfile;
74
typedef unsigned UnlinkedObjectAllocationProfile;
72
typedef unsigned UnlinkedLLIntCallLinkInfo;
75
typedef unsigned UnlinkedLLIntCallLinkInfo;
73
using ConstantIndentifierSetEntry = std::pair<IdentifierSet, unsigned>;
76
using ConstantIdentifierSetEntry = std::pair<IdentifierSet, unsigned>;
74
77
75
struct UnlinkedStringJumpTable {
78
struct UnlinkedStringJumpTable {
76
    struct OffsetLocation {
79
    struct OffsetLocation {
Lines 168-174 public: Link Here
168
        unsigned result = m_constantRegisters.size();
171
        unsigned result = m_constantRegisters.size();
169
        m_constantRegisters.append(WriteBarrier<Unknown>());
172
        m_constantRegisters.append(WriteBarrier<Unknown>());
170
        m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
173
        m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
171
        m_constantIdentifierSets.append(ConstantIndentifierSetEntry(set, result));
174
        m_constantIdentifierSets.append(ConstantIdentifierSetEntry(set, result));
172
    }
175
    }
173
176
174
    unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other)
177
    unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other)
Lines 202-208 public: Link Here
202
        return m_linkTimeConstants[index];
205
        return m_linkTimeConstants[index];
203
    }
206
    }
204
    const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; }
207
    const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; }
205
    const Vector<ConstantIndentifierSetEntry>& constantIdentifierSets() { return m_constantIdentifierSets; }
208
    const Vector<ConstantIdentifierSetEntry>& constantIdentifierSets() { return m_constantIdentifierSets; }
206
    const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
209
    const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
207
    ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
210
    ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
208
    ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
211
    ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
Lines 367-372 public: Link Here
367
370
368
protected:
371
protected:
369
    UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&, DebuggerMode);
372
    UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&, DebuggerMode);
373
374
    template<typename CodeBlockType, typename CachedCodeBlockType>
375
    UnlinkedCodeBlock(Decoder&, Structure*, const CachedCodeBlock<CodeBlockType, CachedCodeBlockType>&);
376
370
    ~UnlinkedCodeBlock();
377
    ~UnlinkedCodeBlock();
371
378
372
    void finishCreation(VM& vm)
379
    void finishCreation(VM& vm)
Lines 378-383 private: Link Here
378
    friend class BytecodeRewriter;
385
    friend class BytecodeRewriter;
379
    friend class BytecodeGenerator;
386
    friend class BytecodeGenerator;
380
387
388
    template<typename CodeBlockType, typename CachedCodeBlockType>
389
    friend struct CachedCodeBlock;
390
381
    void applyModification(BytecodeRewriter&, InstructionStreamWriter&);
391
    void applyModification(BytecodeRewriter&, InstructionStreamWriter&);
382
392
383
    void createRareDataIfNecessary()
393
    void createRareDataIfNecessary()
Lines 444-450 private: Link Here
444
    Vector<Identifier> m_identifiers;
454
    Vector<Identifier> m_identifiers;
445
    Vector<BitVector> m_bitVectors;
455
    Vector<BitVector> m_bitVectors;
446
    Vector<WriteBarrier<Unknown>> m_constantRegisters;
456
    Vector<WriteBarrier<Unknown>> m_constantRegisters;
447
    Vector<ConstantIndentifierSetEntry> m_constantIdentifierSets;
457
    Vector<ConstantIdentifierSetEntry> m_constantIdentifierSets;
448
    Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation;
458
    Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation;
449
    typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector;
459
    typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector;
450
    FunctionExpressionVector m_functionDecls;
460
    FunctionExpressionVector m_functionDecls;
(-)a/Source/JavaScriptCore/bytecode/UnlinkedEvalCodeBlock.h (+6 lines)
Lines 29-34 Link Here
29
29
30
namespace JSC {
30
namespace JSC {
31
31
32
struct CachedEvalCodeBlock;
33
32
class UnlinkedEvalCodeBlock final : public UnlinkedGlobalCodeBlock {
34
class UnlinkedEvalCodeBlock final : public UnlinkedGlobalCodeBlock {
33
public:
35
public:
34
    typedef UnlinkedGlobalCodeBlock Base;
36
    typedef UnlinkedGlobalCodeBlock Base;
Lines 59-69 public: Link Here
59
        m_functionHoistingCandidates = WTFMove(functionHoistingCandidates);
61
        m_functionHoistingCandidates = WTFMove(functionHoistingCandidates);
60
    }
62
    }
61
private:
63
private:
64
    friend CachedEvalCodeBlock;
65
62
    UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info, DebuggerMode debuggerMode)
66
    UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info, DebuggerMode debuggerMode)
63
        : Base(vm, structure, EvalCode, info, debuggerMode)
67
        : Base(vm, structure, EvalCode, info, debuggerMode)
64
    {
68
    {
65
    }
69
    }
66
70
71
    UnlinkedEvalCodeBlock(Decoder&, const CachedEvalCodeBlock&);
72
67
    Vector<Identifier, 0, UnsafeVectorOverflow> m_variables;
73
    Vector<Identifier, 0, UnsafeVectorOverflow> m_variables;
68
    Vector<Identifier, 0, UnsafeVectorOverflow> m_functionHoistingCandidates;
74
    Vector<Identifier, 0, UnsafeVectorOverflow> m_functionHoistingCandidates;
69
75
(-)a/Source/JavaScriptCore/bytecode/UnlinkedFunctionCodeBlock.h (+6 lines)
Lines 29-34 Link Here
29
29
30
namespace JSC {
30
namespace JSC {
31
31
32
struct CachedFunctionCodeBlock;
33
32
class UnlinkedFunctionCodeBlock final : public UnlinkedCodeBlock {
34
class UnlinkedFunctionCodeBlock final : public UnlinkedCodeBlock {
33
public:
35
public:
34
    typedef UnlinkedCodeBlock Base;
36
    typedef UnlinkedCodeBlock Base;
Lines 44-53 public: Link Here
44
    static void destroy(JSCell*);
46
    static void destroy(JSCell*);
45
47
46
private:
48
private:
49
    friend CachedFunctionCodeBlock;
50
47
    UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info, DebuggerMode debuggerMode)
51
    UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info, DebuggerMode debuggerMode)
48
        : Base(vm, structure, codeType, info, debuggerMode)
52
        : Base(vm, structure, codeType, info, debuggerMode)
49
    {
53
    {
50
    }
54
    }
55
56
    UnlinkedFunctionCodeBlock(Decoder&, const CachedFunctionCodeBlock&);
51
    
57
    
52
public:
58
public:
53
    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
59
    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
(-)a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h (+4 lines)
Lines 39-49 Link Here
39
39
40
namespace JSC {
40
namespace JSC {
41
41
42
class Decoder;
42
class FunctionMetadataNode;
43
class FunctionMetadataNode;
43
class FunctionExecutable;
44
class FunctionExecutable;
44
class ParserError;
45
class ParserError;
45
class SourceProvider;
46
class SourceProvider;
46
class UnlinkedFunctionCodeBlock;
47
class UnlinkedFunctionCodeBlock;
48
struct CachedFunctionExecutable;
47
49
48
enum UnlinkedFunctionKind {
50
enum UnlinkedFunctionKind {
49
    UnlinkedNormalFunction,
51
    UnlinkedNormalFunction,
Lines 54-59 class UnlinkedFunctionExecutable final : public JSCell { Link Here
54
public:
56
public:
55
    friend class CodeCache;
57
    friend class CodeCache;
56
    friend class VM;
58
    friend class VM;
59
    friend CachedFunctionExecutable;
57
60
58
    typedef JSCell Base;
61
    typedef JSCell Base;
59
    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
62
    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
Lines 147-152 public: Link Here
147
150
148
private:
151
private:
149
    UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, VariableEnvironment&,  JSC::DerivedContextType, bool isBuiltinDefaultClassConstructor);
152
    UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, VariableEnvironment&,  JSC::DerivedContextType, bool isBuiltinDefaultClassConstructor);
153
    UnlinkedFunctionExecutable(Decoder&, VariableEnvironment&, const CachedFunctionExecutable&);
150
154
151
    unsigned m_firstLineOffset;
155
    unsigned m_firstLineOffset;
152
    unsigned m_lineCount;
156
    unsigned m_lineCount;
(-)a/Source/JavaScriptCore/bytecode/UnlinkedGlobalCodeBlock.h (+6 lines)
Lines 38-43 protected: Link Here
38
        : Base(vm, structure, codeType, info, debuggerMode)
38
        : Base(vm, structure, codeType, info, debuggerMode)
39
    {
39
    {
40
    }
40
    }
41
42
    template<typename CodeBlockType, typename CachedCodeBlockType>
43
    UnlinkedGlobalCodeBlock(Decoder& decoder, Structure* structure, const CachedCodeBlock<CodeBlockType, CachedCodeBlockType>& cachedCodeBlock)
44
        : Base(decoder, structure, cachedCodeBlock)
45
    {
46
    }
41
};
47
};
42
48
43
}
49
}
(-)a/Source/JavaScriptCore/bytecode/UnlinkedMetadataTable.h (+1 lines)
Lines 35-40 class MetadataTable; Link Here
35
class UnlinkedMetadataTable {
35
class UnlinkedMetadataTable {
36
    friend class LLIntOffsetsExtractor;
36
    friend class LLIntOffsetsExtractor;
37
    friend class MetadataTable;
37
    friend class MetadataTable;
38
    friend struct CachedMetadataTable;
38
39
39
public:
40
public:
40
    UnlinkedMetadataTable();
41
    UnlinkedMetadataTable();
(-)a/Source/JavaScriptCore/bytecode/UnlinkedModuleProgramCodeBlock.h (+7 lines)
Lines 29-34 Link Here
29
29
30
namespace JSC {
30
namespace JSC {
31
31
32
class Decoder;
33
struct CachedModuleCodeBlock;
34
32
class UnlinkedModuleProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
35
class UnlinkedModuleProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
33
public:
36
public:
34
    typedef UnlinkedGlobalCodeBlock Base;
37
    typedef UnlinkedGlobalCodeBlock Base;
Lines 74-84 public: Link Here
74
    }
77
    }
75
78
76
private:
79
private:
80
    friend CachedModuleCodeBlock;
81
77
    UnlinkedModuleProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info, DebuggerMode debuggerMode)
82
    UnlinkedModuleProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info, DebuggerMode debuggerMode)
78
        : Base(vm, structure, ModuleCode, info, debuggerMode)
83
        : Base(vm, structure, ModuleCode, info, debuggerMode)
79
    {
84
    {
80
    }
85
    }
81
86
87
    UnlinkedModuleProgramCodeBlock(Decoder&, const CachedModuleCodeBlock&);
88
82
    int m_moduleEnvironmentSymbolTableConstantRegisterOffset { 0 };
89
    int m_moduleEnvironmentSymbolTableConstantRegisterOffset { 0 };
83
90
84
public:
91
public:
(-)a/Source/JavaScriptCore/bytecode/UnlinkedProgramCodeBlock.h (+6 lines)
Lines 29-34 Link Here
29
29
30
namespace JSC {
30
namespace JSC {
31
31
32
struct CachedProgramCodeBlock;
33
32
class UnlinkedProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
34
class UnlinkedProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
33
public:
35
public:
34
    typedef UnlinkedGlobalCodeBlock Base;
36
    typedef UnlinkedGlobalCodeBlock Base;
Lines 50-60 public: Link Here
50
    const VariableEnvironment& lexicalDeclarations() const { return m_lexicalDeclarations; }
52
    const VariableEnvironment& lexicalDeclarations() const { return m_lexicalDeclarations; }
51
53
52
private:
54
private:
55
    friend CachedProgramCodeBlock;
56
53
    UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info, DebuggerMode debuggerMode)
57
    UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info, DebuggerMode debuggerMode)
54
        : Base(vm, structure, GlobalCode, info, debuggerMode)
58
        : Base(vm, structure, GlobalCode, info, debuggerMode)
55
    {
59
    {
56
    }
60
    }
57
61
62
    UnlinkedProgramCodeBlock(Decoder&, const CachedProgramCodeBlock&);
63
58
    VariableEnvironment m_varDeclarations;
64
    VariableEnvironment m_varDeclarations;
59
    VariableEnvironment m_lexicalDeclarations;
65
    VariableEnvironment m_lexicalDeclarations;
60
66
(-)a/Source/JavaScriptCore/interpreter/Interpreter.cpp (+2 lines)
Lines 35-40 Link Here
35
#include "CallFrameClosure.h"
35
#include "CallFrameClosure.h"
36
#include "CatchScope.h"
36
#include "CatchScope.h"
37
#include "CodeBlock.h"
37
#include "CodeBlock.h"
38
#include "CodeCache.h"
38
#include "DirectArguments.h"
39
#include "DirectArguments.h"
39
#include "Heap.h"
40
#include "Heap.h"
40
#include "Debugger.h"
41
#include "Debugger.h"
Lines 830-835 failedJSONP: Link Here
830
    // Execute the code:
831
    // Execute the code:
831
    throwScope.release();
832
    throwScope.release();
832
    JSValue result = program->generatedJITCode()->execute(&vm, &protoCallFrame);
833
    JSValue result = program->generatedJITCode()->execute(&vm, &protoCallFrame);
834
    vm.codeCache()->write(vm);
833
    return checkedReturn(result);
835
    return checkedReturn(result);
834
}
836
}
835
837
(-)a/Source/JavaScriptCore/parser/SourceCode.h (+2 lines)
Lines 33-38 Link Here
33
namespace JSC {
33
namespace JSC {
34
34
35
    class SourceCode : public UnlinkedSourceCode {
35
    class SourceCode : public UnlinkedSourceCode {
36
        friend struct CachedSourceCode;
37
36
    public:
38
    public:
37
        SourceCode()
39
        SourceCode()
38
            : UnlinkedSourceCode()
40
            : UnlinkedSourceCode()
(-)a/Source/JavaScriptCore/parser/SourceCodeKey.h (+9 lines)
Lines 37-42 enum class TypeProfilerEnabled { No, Yes }; Link Here
37
enum class ControlFlowProfilerEnabled { No, Yes };
37
enum class ControlFlowProfilerEnabled { No, Yes };
38
38
39
class SourceCodeFlags {
39
class SourceCodeFlags {
40
    friend struct CachedSourceCodeKey;
41
40
public:
42
public:
41
    SourceCodeFlags() = default;
43
    SourceCodeFlags() = default;
42
44
Lines 70-75 private: Link Here
70
};
72
};
71
73
72
class SourceCodeKey {
74
class SourceCodeKey {
75
    friend struct CachedSourceCodeKey;
76
73
public:
77
public:
74
    SourceCodeKey()
78
    SourceCodeKey()
75
    {
79
    {
Lines 112-117 public: Link Here
112
            && string() == other.string();
116
            && string() == other.string();
113
    }
117
    }
114
118
119
    bool operator!=(const SourceCodeKey& other) const
120
    {
121
        return !(*this == other);
122
    }
123
115
    struct Hash {
124
    struct Hash {
116
        static unsigned hash(const SourceCodeKey& key) { return key.hash(); }
125
        static unsigned hash(const SourceCodeKey& key) { return key.hash(); }
117
        static bool equal(const SourceCodeKey& a, const SourceCodeKey& b) { return a == b; }
126
        static bool equal(const SourceCodeKey& a, const SourceCodeKey& b) { return a == b; }
(-)a/Source/JavaScriptCore/parser/UnlinkedSourceCode.h (+3 lines)
Lines 35-40 Link Here
35
namespace JSC {
35
namespace JSC {
36
36
37
    class UnlinkedSourceCode {
37
    class UnlinkedSourceCode {
38
        template<typename SourceType, typename CacheType>
39
        friend struct CachedUnlinkedSourceCodeShape;
40
38
    public:
41
    public:
39
        UnlinkedSourceCode()
42
        UnlinkedSourceCode()
40
            : m_provider(0)
43
            : m_provider(0)
(-)a/Source/JavaScriptCore/parser/VariableEnvironment.h (+2 lines)
Lines 116-121 public: Link Here
116
    bool isEverythingCaptured() const { return m_isEverythingCaptured; }
116
    bool isEverythingCaptured() const { return m_isEverythingCaptured; }
117
117
118
private:
118
private:
119
    friend struct CachedVariableEnvironment;
120
119
    Map m_map;
121
    Map m_map;
120
    bool m_isEverythingCaptured { false };
122
    bool m_isEverythingCaptured { false };
121
};
123
};
(-)a/Source/JavaScriptCore/runtime/CachedTypes.h (+1780 lines)
Line 0 Link Here
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
43
namespace JSC {
44
45
template <typename T, typename = void>
46
struct SourceTypeImpl {
47
    using type = T;
48
};
49
50
template<typename T>
51
struct 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
56
template<typename T>
57
using SourceType = typename SourceTypeImpl<T>::type;
58
59
class Encoder {
60
    WTF_MAKE_NONCOPYABLE(Encoder);
61
62
public:
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
    std::optional<ptrdiff_t> offsetForPtr(const void* ptr)
114
    {
115
        auto it = m_ptrToOffsetMap.find(ptr);
116
        if (it == m_ptrToOffsetMap.end())
117
            return std::nullopt;
118
        return { it->value };
119
    }
120
121
private:
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
130
class Decoder {
131
    WTF_MAKE_NONCOPYABLE(Decoder);
132
133
public:
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
    std::optional<void*> ptrForOffset(ptrdiff_t offset)
165
    {
166
        auto it = m_offsetToPtrMap.find(offset);
167
        if (it == m_offsetToPtrMap.end())
168
            return std::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
178
private:
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
188
template<typename T>
189
static 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
194
template<typename T>
195
static 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
200
template<typename T, typename... Args>
201
static 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
206
template<typename T, typename... Args>
207
static 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
212
template<typename T>
213
static std::enable_if_t<std::is_same<T, SourceType<T>>::value, T> decode(Decoder&, T src)
214
{
215
    return src;
216
}
217
218
template<typename T>
219
static 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
224
template<typename Source, typename Dst>
225
struct 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
260
template<typename Source, typename Dst>
261
struct VariableLengthObject : public CachedObject<Source, Dst> {
262
private:
263
    constexpr static ptrdiff_t s_invalidOffset = PTRDIFF_MAX;
264
public:
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
307
template<typename T, typename SourceType = SourceType<T>>
308
struct 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 (std::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 (std::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
357
template<typename T, typename SourceType = SourceType<T>>
358
struct 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
385
template<typename T, typename SourceType = SourceType<T>>
386
struct 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
402
template<typename T, size_t IC = 0, typename OH = CrashOnOverflow>
403
struct 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
424
template<typename Fst, typename Snd>
425
struct 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
442
template<typename Key, typename Value, typename HashArg = typename DefaultHash<SourceType<Key>>::Hash, typename KeyTraitsArg = HashTraits<SourceType<Key>>, typename MappedTraitsArg = HashTraits<SourceType<Value>>>
443
struct 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
469
struct 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
529
struct 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
543
struct 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
562
struct 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
585
template<typename T>
586
struct CachedOptional : public VariableLengthObject<std::optional<SourceType<T>>, CachedOptional<T>> {
587
    bool isEmpty;
588
589
    void encode(Encoder& encoder, const std::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
    std::optional<SourceType<T>> decode(Decoder& decoder) const
600
    {
601
        if (isEmpty)
602
            return std::nullopt;
603
604
        return { this->template buffer<T>()->decode(decoder) };
605
    }
606
607
    void decode(Decoder& decoder, std::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, std::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
629
struct 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
646
struct 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
660
struct 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
697
struct 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
714
template<typename T, typename HashArg = typename DefaultHash<T>::Hash>
715
struct 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
736
struct 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
753
struct 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
771
template<typename T, typename SourceType = SourceType<T>>
772
struct 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
789
struct 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
807
struct 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
821
struct 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
857
struct CachedJSValue;
858
struct 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
887
struct 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
904
struct 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
924
struct 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::createWithLength(decoder.vm(), length);
944
        bigInt->setSign(sign);
945
        memcpy(bigInt->dataStorage(), this->buffer(), sizeof(JSBigInt::Digit[length]));
946
        return bigInt;
947
    }
948
};
949
950
struct 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
1051
struct 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
1067
struct 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.m_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.m_buffer[i] = metadata[i];
1088
    }
1089
};
1090
1091
struct 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
1105
struct 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
1121
template <typename SourceType, typename CachedType>
1122
struct 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
1149
struct 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)
1174
struct 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
1201
struct 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
1238
template<typename SourceType, typename CacheType>
1239
struct 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
1260
struct CachedUnlinkedSourceCode : public CachedUnlinkedSourceCodeShape<UnlinkedSourceCode, CachedUnlinkedSourceCode> { };
1261
1262
struct 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
1283
struct 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
1324
template<typename CodeBlockType, typename CachedCodeBlockType>
1325
struct 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
1382
struct 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
1407
struct 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
1429
struct 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
1454
struct 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
1471
ALWAYS_INLINE UnlinkedFunctionCodeBlock::UnlinkedFunctionCodeBlock(Decoder& decoder, const CachedFunctionCodeBlock& cachedCodeBlock)
1472
    : Base(decoder, decoder.vm().unlinkedFunctionCodeBlockStructure.get(), cachedCodeBlock)
1473
{
1474
}
1475
1476
template<typename T>
1477
struct CachedCodeBlockTypeImpl;
1478
1479
template<>
1480
struct CachedCodeBlockTypeImpl<UnlinkedProgramCodeBlock> {
1481
    using type = CachedProgramCodeBlock;
1482
};
1483
1484
template<>
1485
struct CachedCodeBlockTypeImpl<UnlinkedModuleProgramCodeBlock> {
1486
    using type = CachedModuleCodeBlock;
1487
};
1488
1489
template<>
1490
struct CachedCodeBlockTypeImpl<UnlinkedEvalCodeBlock> {
1491
    using type = CachedEvalCodeBlock;
1492
};
1493
1494
template<typename T>
1495
using CachedCodeBlockType = typename CachedCodeBlockTypeImpl<T>::type;
1496
1497
template<typename CodeBlockType, typename CachedCodeBlockType>
1498
ALWAYS_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
1535
template<typename CodeBlockType, typename CachedCodeBlockType>
1536
ALWAYS_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
1555
ALWAYS_INLINE UnlinkedProgramCodeBlock::UnlinkedProgramCodeBlock(Decoder& decoder, const CachedProgramCodeBlock& cachedCodeBlock)
1556
    : Base(decoder, decoder.vm().unlinkedProgramCodeBlockStructure.get(), cachedCodeBlock)
1557
{
1558
}
1559
1560
ALWAYS_INLINE UnlinkedModuleProgramCodeBlock::UnlinkedModuleProgramCodeBlock(Decoder& decoder, const CachedModuleCodeBlock& cachedCodeBlock)
1561
    : Base(decoder, decoder.vm().unlinkedModuleProgramCodeBlockStructure.get(), cachedCodeBlock)
1562
{
1563
}
1564
1565
ALWAYS_INLINE UnlinkedEvalCodeBlock::UnlinkedEvalCodeBlock(Decoder& decoder, const CachedEvalCodeBlock& cachedCodeBlock)
1566
    : Base(decoder, decoder.vm().unlinkedEvalCodeBlockStructure.get(), cachedCodeBlock)
1567
{
1568
}
1569
1570
///////////
1571
1572
ALWAYS_INLINE void CachedFunctionExecutable::encode(Encoder& encoder, const UnlinkedFunctionExecutable& executable)
1573
{
1574
    firstLineOffset = executable.m_firstLineOffset;
1575
    lineCount = executable.m_lineCount;
1576
    unlinkedFunctionNameStart = executable.m_unlinkedFunctionNameStart;
1577
    unlinkedBodyStartColumn = executable.m_unlinkedBodyStartColumn;
1578
    unlinkedBodyEndColumn = executable.m_unlinkedBodyEndColumn;
1579
    startOffset = executable.m_startOffset;
1580
    sourceLength = executable.m_sourceLength;
1581
    parametersStartOffset = executable.m_parametersStartOffset;
1582
    typeProfilingStartOffset = executable.m_typeProfilingStartOffset;
1583
    typeProfilingEndOffset = executable.m_typeProfilingEndOffset;
1584
    parameterCount = executable.m_parameterCount;
1585
1586
    features = executable.m_features;
1587
    sourceParseMode = executable.m_sourceParseMode;
1588
1589
    isInStrictContext = executable.m_isInStrictContext;
1590
    hasCapturedVariables = executable.m_hasCapturedVariables;
1591
    isBuiltinFunction = executable.m_isBuiltinFunction;
1592
    isBuiltinDefaultClassConstructor = executable.m_isBuiltinDefaultClassConstructor;
1593
    constructAbility = executable.m_constructAbility;
1594
    constructorKind = executable.m_constructorKind;
1595
    functionMode = executable.m_functionMode;
1596
    scriptMode = executable.m_scriptMode;
1597
    superBinding = executable.m_superBinding;
1598
    derivedContextType = executable.m_derivedContextType;
1599
1600
    classSource.encode(encoder, executable.m_classSource);
1601
1602
    name.encode(encoder, executable.name());
1603
    ecmaName.encode(encoder, executable.ecmaName());
1604
    inferredName.encode(encoder, executable.inferredName());
1605
1606
    parentScopeTDZVariables.encode(encoder, executable.parentScopeTDZVariables());
1607
1608
    unlinkedCodeBlockForCall.encode(encoder, executable.m_unlinkedCodeBlockForCall);
1609
    unlinkedCodeBlockForConstruct.encode(encoder, executable.m_unlinkedCodeBlockForConstruct);
1610
}
1611
1612
ALWAYS_INLINE UnlinkedFunctionExecutable* CachedFunctionExecutable::decode(Decoder& decoder) const
1613
{
1614
    VariableEnvironment env;
1615
    parentScopeTDZVariables.decode(decoder, env);
1616
1617
    UnlinkedFunctionExecutable* executable = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(decoder.vm().heap)) UnlinkedFunctionExecutable(decoder, env, *this);
1618
    executable->finishCreation(decoder.vm());
1619
1620
    classSource.decode(decoder, executable->m_classSource);
1621
    unlinkedCodeBlockForCall.decode(decoder, executable->m_unlinkedCodeBlockForCall, executable);
1622
    unlinkedCodeBlockForConstruct.decode(decoder, executable->m_unlinkedCodeBlockForConstruct, executable);
1623
1624
    return executable;
1625
}
1626
1627
ALWAYS_INLINE UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(Decoder& decoder, VariableEnvironment& parentScopeTDZVariables, const CachedFunctionExecutable& cachedExecutable)
1628
    : Base(decoder.vm(), decoder.vm().unlinkedFunctionExecutableStructure.get())
1629
    , m_firstLineOffset(cachedExecutable.firstLineOffset)
1630
    , m_lineCount(cachedExecutable.lineCount)
1631
    , m_unlinkedFunctionNameStart(cachedExecutable.unlinkedFunctionNameStart)
1632
    , m_unlinkedBodyStartColumn(cachedExecutable.unlinkedBodyStartColumn)
1633
    , m_unlinkedBodyEndColumn(cachedExecutable.unlinkedBodyEndColumn)
1634
    , m_startOffset(cachedExecutable.startOffset)
1635
    , m_sourceLength(cachedExecutable.sourceLength)
1636
    , m_parametersStartOffset(cachedExecutable.parametersStartOffset)
1637
    , m_typeProfilingStartOffset(cachedExecutable.typeProfilingStartOffset)
1638
    , m_typeProfilingEndOffset(cachedExecutable.typeProfilingEndOffset)
1639
    , m_parameterCount(cachedExecutable.parameterCount)
1640
    , m_features(cachedExecutable.features)
1641
    , m_sourceParseMode(cachedExecutable.sourceParseMode)
1642
    , m_isInStrictContext(cachedExecutable.isInStrictContext)
1643
    , m_hasCapturedVariables(cachedExecutable.hasCapturedVariables)
1644
    , m_isBuiltinFunction(cachedExecutable.isBuiltinFunction)
1645
    , m_isBuiltinDefaultClassConstructor(cachedExecutable.isBuiltinDefaultClassConstructor)
1646
    , m_constructAbility(cachedExecutable.constructAbility)
1647
    , m_constructorKind(cachedExecutable.constructorKind)
1648
    , m_functionMode(cachedExecutable.functionMode)
1649
    , m_scriptMode(cachedExecutable.scriptMode)
1650
    , m_superBinding(cachedExecutable.superBinding)
1651
    , m_derivedContextType(cachedExecutable.derivedContextType)
1652
1653
    , m_name(cachedExecutable.name.decode(decoder))
1654
    , m_ecmaName(cachedExecutable.ecmaName.decode(decoder))
1655
    , m_inferredName(cachedExecutable.inferredName.decode(decoder))
1656
1657
    , m_parentScopeTDZVariables(decoder.vm().m_compactVariableMap->get(parentScopeTDZVariables))
1658
{
1659
}
1660
1661
template<typename CodeBlockType, typename CachedCodeBlockType>
1662
ALWAYS_INLINE void CachedCodeBlock<CodeBlockType, CachedCodeBlockType>::encode(Encoder& encoder, const UnlinkedCodeBlock& codeBlock)
1663
{
1664
    thisRegister = codeBlock.m_thisRegister;
1665
    scopeRegister = codeBlock.m_scopeRegister;
1666
    globalObjectRegister = codeBlock.m_globalObjectRegister;
1667
    usesEval = codeBlock.m_usesEval;
1668
    isStrictMode = codeBlock.m_isStrictMode;
1669
    isConstructor = codeBlock.m_isConstructor;
1670
    hasCapturedVariables = codeBlock.m_hasCapturedVariables;
1671
    isBuiltinFunction = codeBlock.m_isBuiltinFunction;
1672
    superBinding = codeBlock.m_superBinding;
1673
    scriptMode = codeBlock.m_scriptMode;
1674
    isArrowFunctionContext = codeBlock.m_isArrowFunctionContext;
1675
    isClassContext = codeBlock.m_isClassContext;
1676
    wasCompiledWithDebuggingOpcodes = codeBlock.m_wasCompiledWithDebuggingOpcodes;
1677
    constructorKind = codeBlock.m_constructorKind;
1678
    derivedContextType = codeBlock.m_derivedContextType;
1679
    evalContextType = codeBlock.m_evalContextType;
1680
    hasTailCalls = codeBlock.m_hasTailCalls;
1681
    lineCount = codeBlock.m_lineCount;
1682
    endColumn = codeBlock.m_endColumn;
1683
    numVars = codeBlock.m_numVars;
1684
    numCalleeLocals = codeBlock.m_numCalleeLocals;
1685
    numParameters = codeBlock.m_numParameters;
1686
    features = codeBlock.m_features;
1687
    parseMode = codeBlock.m_parseMode;
1688
    codeType = codeBlock.m_codeType;
1689
1690
    for (unsigned i = LinkTimeConstantCount; i--;)
1691
        linkTimeConstants[i] = codeBlock.m_linkTimeConstants[i];
1692
1693
    metadata.encode(encoder, codeBlock.m_metadata);
1694
    rareData.encode(encoder, codeBlock.m_rareData);
1695
1696
    sourceURLDirective.encode(encoder, codeBlock.m_sourceURLDirective.impl());
1697
    sourceMappingURLDirective.encode(encoder, codeBlock.m_sourceURLDirective.impl());
1698
1699
    instructions.encode(encoder, codeBlock.m_instructions.get());
1700
    propertyAccessInstructions.encode(encoder, codeBlock.m_propertyAccessInstructions);
1701
    constantRegisters.encode(encoder, codeBlock.m_constantRegisters);
1702
    constantsSourceCodeRepresentation.encode(encoder, codeBlock.m_constantsSourceCodeRepresentation);
1703
    expressionInfo.encode(encoder, codeBlock.m_expressionInfo);
1704
    jumpTargets.encode(encoder, codeBlock.m_jumpTargets);
1705
    outOfLineJumpTargets.encode(encoder, codeBlock.m_outOfLineJumpTargets);
1706
1707
    constantIdentifierSets.encode(encoder, codeBlock.m_constantIdentifierSets);
1708
    identifiers.encode(encoder, codeBlock.m_identifiers);
1709
    bitVectors.encode(encoder, codeBlock.m_bitVectors);
1710
    functionDecls.encode(encoder, codeBlock.m_functionDecls);
1711
    functionExprs.encode(encoder, codeBlock.m_functionExprs);
1712
}
1713
1714
struct CachedSourceCodeKey : public CachedObject<SourceCodeKey, CachedSourceCodeKey> {
1715
    CachedUnlinkedSourceCode sourceCode;
1716
    CachedString name;
1717
    unsigned flags;
1718
    unsigned hash;
1719
1720
    void encode(Encoder& encoder, const SourceCodeKey& key)
1721
    {
1722
        sourceCode.encode(encoder, key.m_sourceCode);
1723
        name.encode(encoder, key.m_name);
1724
        flags = key.m_flags.m_flags;
1725
        hash = key.hash();
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
    }
1735
};
1736
1737
template<typename UnlinkedCodeBlockType>
1738
struct CacheEntry {
1739
    CachedSourceCodeKey key;
1740
    CachedPtr<CachedCodeBlockType<UnlinkedCodeBlockType>> codeBlock;
1741
1742
    void encode(Encoder& encoder, std::pair<SourceCodeKey, const UnlinkedCodeBlockType*> pair)
1743
    {
1744
        key.encode(encoder, pair.first);
1745
        codeBlock.encode(encoder, pair.second);
1746
    }
1747
1748
    std::pair<SourceCodeKey, UnlinkedCodeBlockType*> decode(Decoder& decoder) const
1749
    {
1750
        SourceCodeKey decodedKey;
1751
        key.decode(decoder, decodedKey);
1752
        return { WTFMove(decodedKey), codeBlock.decode(decoder) };
1753
    }
1754
};
1755
1756
template<typename UnlinkedCodeBlockType>
1757
ALWAYS_INLINE void encodeCodeBlock(Encoder& encoder, SourceCodeKey key, const UnlinkedCodeBlock* codeBlock)
1758
{
1759
    auto* entry = encoder.template malloc<CacheEntry<UnlinkedCodeBlockType>>();
1760
    entry->encode(encoder,  { key, jsCast<const UnlinkedCodeBlockType*>(codeBlock) });
1761
}
1762
1763
ALWAYS_INLINE void encodeCodeBlock(Encoder& encoder, SourceCodeKey key, const UnlinkedCodeBlock* codeBlock)
1764
{
1765
    const ClassInfo* classInfo = codeBlock->classInfo(encoder.vm());
1766
1767
    if (classInfo == UnlinkedProgramCodeBlock::info()) {
1768
        encodeCodeBlock<UnlinkedProgramCodeBlock>(encoder, key, codeBlock);
1769
        return;
1770
    }
1771
1772
    if (classInfo == UnlinkedModuleProgramCodeBlock::info()) {
1773
        encodeCodeBlock<UnlinkedModuleProgramCodeBlock>(encoder, key, codeBlock);
1774
        return;
1775
    }
1776
1777
    ASSERT(classInfo == UnlinkedEvalCodeBlock::info());
1778
}
1779
1780
} // namespace JSC
(-)a/Source/JavaScriptCore/runtime/CodeCache.cpp (-7 / +24 lines)
Lines 58-66 UnlinkedCodeBlockType* CodeCache::getUnlinkedGlobalCodeBlock(VM& vm, ExecutableT Link Here
58
        derivedContextType, evalContextType, isArrowFunctionContext, debuggerMode, 
58
        derivedContextType, evalContextType, isArrowFunctionContext, debuggerMode, 
59
        vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No, 
59
        vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No, 
60
        vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No);
60
        vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No);
61
    SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key);
61
    UnlinkedCodeBlockType* unlinkedCodeBlock = m_sourceCode.findCacheAndUpdateAge<UnlinkedCodeBlockType>(vm, key);
62
    if (cache && Options::useCodeCache()) {
62
    if (unlinkedCodeBlock && Options::useCodeCache()) {
63
        UnlinkedCodeBlockType* unlinkedCodeBlock = jsCast<UnlinkedCodeBlockType*>(cache->cell.get());
64
        unsigned lineCount = unlinkedCodeBlock->lineCount();
63
        unsigned lineCount = unlinkedCodeBlock->lineCount();
65
        unsigned startColumn = unlinkedCodeBlock->startColumn() + source.startColumn().oneBasedInt();
64
        unsigned startColumn = unlinkedCodeBlock->startColumn() + source.startColumn().oneBasedInt();
66
        bool endColumnIsOnStartLine = !lineCount;
65
        bool endColumnIsOnStartLine = !lineCount;
Lines 72-78 UnlinkedCodeBlockType* CodeCache::getUnlinkedGlobalCodeBlock(VM& vm, ExecutableT Link Here
72
    }
71
    }
73
    
72
    
74
    VariableEnvironment variablesUnderTDZ;
73
    VariableEnvironment variablesUnderTDZ;
75
    UnlinkedCodeBlockType* unlinkedCodeBlock = generateUnlinkedCodeBlock<UnlinkedCodeBlockType, ExecutableType>(vm, executable, source, strictMode, scriptMode, debuggerMode, error, evalContextType, &variablesUnderTDZ);
74
    unlinkedCodeBlock = generateUnlinkedCodeBlock<UnlinkedCodeBlockType, ExecutableType>(vm, executable, source, strictMode, scriptMode, debuggerMode, error, evalContextType, &variablesUnderTDZ);
76
75
77
    if (unlinkedCodeBlock && Options::useCodeCache())
76
    if (unlinkedCodeBlock && Options::useCodeCache())
78
        m_sourceCode.addCache(key, SourceCodeValue(vm, unlinkedCodeBlock, m_sourceCode.age()));
77
        m_sourceCode.addCache(key, SourceCodeValue(vm, unlinkedCodeBlock, m_sourceCode.age()));
Lines 108-116 UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& v Link Here
108
        debuggerMode, 
107
        debuggerMode, 
109
        vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No, 
108
        vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No, 
110
        vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No);
109
        vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No);
111
    SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key);
110
    UnlinkedFunctionExecutable* executable = m_sourceCode.findCacheAndUpdateAge<UnlinkedFunctionExecutable>(vm, key);
112
    if (cache && Options::useCodeCache()) {
111
    if (executable && Options::useCodeCache()) {
113
        UnlinkedFunctionExecutable* executable = jsCast<UnlinkedFunctionExecutable*>(cache->cell.get());
114
        source.provider()->setSourceURLDirective(executable->sourceURLDirective());
112
        source.provider()->setSourceURLDirective(executable->sourceURLDirective());
115
        source.provider()->setSourceMappingURLDirective(executable->sourceMappingURLDirective());
113
        source.provider()->setSourceMappingURLDirective(executable->sourceMappingURLDirective());
116
        return executable;
114
        return executable;
Lines 164-167 UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& v Link Here
164
    return functionExecutable;
162
    return functionExecutable;
165
}
163
}
166
164
165
void CodeCache::write(VM& vm)
166
{
167
    for (const auto& it : m_sourceCode) {
168
        unsigned hash = it.key.hash();
169
        char filename[256];
170
        snprintf(filename, 256, "/tmp/%u.cache", hash);
171
172
        Encoder encoder(vm);
173
        UnlinkedCodeBlock* codeBlock = jsCast<UnlinkedCodeBlock*>(it.value.cell.get());
174
        encodeCodeBlock(encoder, it.key, codeBlock);
175
176
        int fd = open(filename, O_CREAT | O_WRONLY, 0666);
177
        int rc = flock(fd, LOCK_EX | LOCK_NB);
178
        if (!rc)
179
            ::write(fd, encoder.buffer(), encoder.size());
180
        close(fd);
181
    }
182
}
183
167
}
184
}
(-)a/Source/JavaScriptCore/runtime/CodeCache.h (-3 / +53 lines)
Lines 26-31 Link Here
26
#pragma once
26
#pragma once
27
27
28
#include "BytecodeGenerator.h"
28
#include "BytecodeGenerator.h"
29
#include "CachedTypes.h"
29
#include "ExecutableInfo.h"
30
#include "ExecutableInfo.h"
30
#include "JSCInlines.h"
31
#include "JSCInlines.h"
31
#include "Parser.h"
32
#include "Parser.h"
Lines 37-42 Link Here
37
#include "UnlinkedEvalCodeBlock.h"
38
#include "UnlinkedEvalCodeBlock.h"
38
#include "UnlinkedModuleProgramCodeBlock.h"
39
#include "UnlinkedModuleProgramCodeBlock.h"
39
#include "UnlinkedProgramCodeBlock.h"
40
#include "UnlinkedProgramCodeBlock.h"
41
#include <sys/stat.h>
40
#include <wtf/Forward.h>
42
#include <wtf/Forward.h>
41
#include <wtf/text/WTFString.h>
43
#include <wtf/text/WTFString.h>
42
44
Lines 89-101 public: Link Here
89
    {
91
    {
90
    }
92
    }
91
93
92
    SourceCodeValue* findCacheAndUpdateAge(const SourceCodeKey& key)
94
    iterator begin() { return m_map.begin(); }
95
    iterator end() { return m_map.end(); }
96
97
    template<typename UnlinkedCodeBlockType>
98
    std::enable_if_t<std::is_base_of<UnlinkedCodeBlock, UnlinkedCodeBlockType>::value && !std::is_same<UnlinkedCodeBlockType, UnlinkedEvalCodeBlock>::value, UnlinkedCodeBlockType*>
99
    fetchFromDisk(VM& vm, const SourceCodeKey& key)
100
    {
101
        unsigned hash = key.hash();
102
        char filename[256];
103
        snprintf(filename, 256, "/tmp/%u.cache", hash);
104
        int fd = open(filename, O_RDONLY);
105
106
        if (fd == -1)
107
            return nullptr;
108
109
        int rc = flock(fd, LOCK_SH | LOCK_NB);
110
        if (rc) {
111
            close(fd);
112
            return nullptr;
113
        }
114
115
        struct stat sb;
116
        int res = fstat(fd, &sb);
117
        if (res || !sb.st_size)
118
            return nullptr;
119
120
        const void* buffer = mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
121
        const auto* cachedCodeBlock = reinterpret_cast<const CacheEntry<UnlinkedCodeBlockType>*>(buffer);
122
        Decoder decoder(vm, cachedCodeBlock, sb.st_size);
123
        std::pair<SourceCodeKey, UnlinkedCodeBlockType*> entry;
124
        {
125
            DeferGC deferGC(vm.heap);
126
            entry = cachedCodeBlock->decode(decoder);
127
        }
128
129
        if (entry.first != key)
130
            return nullptr;
131
132
        addCache(key, SourceCodeValue(vm, entry.second, m_age));
133
        return entry.second;
134
    }
135
136
    template<typename T>
137
    std::enable_if_t<!std::is_base_of<UnlinkedCodeBlock, T>::value || std::is_same<T, UnlinkedEvalCodeBlock>::value, T*>
138
    fetchFromDisk(VM&, const SourceCodeKey&) { return nullptr; }
139
140
    template<typename UnlinkedCodeBlockType>
141
    UnlinkedCodeBlockType* findCacheAndUpdateAge(VM& vm, const SourceCodeKey& key)
93
    {
142
    {
94
        prune();
143
        prune();
95
144
96
        iterator findResult = m_map.find(key);
145
        iterator findResult = m_map.find(key);
97
        if (findResult == m_map.end())
146
        if (findResult == m_map.end())
98
            return nullptr;
147
            return fetchFromDisk<UnlinkedCodeBlockType>(vm, key);
99
148
100
        int64_t age = m_age - findResult->value.age;
149
        int64_t age = m_age - findResult->value.age;
101
        if (age > m_capacity) {
150
        if (age > m_capacity) {
Lines 115-121 public: Link Here
115
        findResult->value.age = m_age;
164
        findResult->value.age = m_age;
116
        m_age += key.length();
165
        m_age += key.length();
117
166
118
        return &findResult->value;
167
        return jsCast<UnlinkedCodeBlockType*>(findResult->value.cell.get());
119
    }
168
    }
120
169
121
    AddResult addCache(const SourceCodeKey& key, const SourceCodeValue& value)
170
    AddResult addCache(const SourceCodeKey& key, const SourceCodeValue& value)
Lines 197-202 public: Link Here
197
    UnlinkedFunctionExecutable* getUnlinkedGlobalFunctionExecutable(VM&, const Identifier&, const SourceCode&, DebuggerMode, ParserError&);
246
    UnlinkedFunctionExecutable* getUnlinkedGlobalFunctionExecutable(VM&, const Identifier&, const SourceCode&, DebuggerMode, ParserError&);
198
247
199
    void clear() { m_sourceCode.clear(); }
248
    void clear() { m_sourceCode.clear(); }
249
    void write(VM&);
200
250
201
private:
251
private:
202
    template <class UnlinkedCodeBlockType, class ExecutableType> 
252
    template <class UnlinkedCodeBlockType, class ExecutableType> 
(-)a/Source/JavaScriptCore/runtime/JSBigInt.cpp (-10 lines)
Lines 1472-1482 bool JSBigInt::getPrimitiveNumber(ExecState* exec, double& number, JSValue& resu Link Here
1472
    return true;
1472
    return true;
1473
}
1473
}
1474
1474
1475
inline size_t JSBigInt::offsetOfData()
1476
{
1477
    return WTF::roundUpToMultipleOf<sizeof(Digit)>(sizeof(JSBigInt));
1478
}
1479
1480
template <typename CharType>
1475
template <typename CharType>
1481
JSBigInt* JSBigInt::parseInt(ExecState* exec, CharType*  data, unsigned length, ErrorParseMode errorParseMode)
1476
JSBigInt* JSBigInt::parseInt(ExecState* exec, CharType*  data, unsigned length, ErrorParseMode errorParseMode)
1482
{
1477
{
Lines 1579-1589 JSBigInt* JSBigInt::parseInt(ExecState* exec, VM& vm, CharType* data, unsigned l Link Here
1579
    return nullptr;
1574
    return nullptr;
1580
}
1575
}
1581
1576
1582
inline JSBigInt::Digit* JSBigInt::dataStorage()
1583
{
1584
    return reinterpret_cast<Digit*>(reinterpret_cast<char*>(this) + offsetOfData());
1585
}
1586
1587
inline JSBigInt::Digit JSBigInt::digit(unsigned n)
1577
inline JSBigInt::Digit JSBigInt::digit(unsigned n)
1588
{
1578
{
1589
    ASSERT(n < length());
1579
    ASSERT(n < length());
(-)a/Source/JavaScriptCore/runtime/JSBigInt.h (-2 / +10 lines)
Lines 39-44 namespace JSC { Link Here
39
class JSBigInt final : public JSCell {
39
class JSBigInt final : public JSCell {
40
    using Base = JSCell;
40
    using Base = JSCell;
41
    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal | OverridesToThis;
41
    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal | OverridesToThis;
42
    friend struct CachedBigInt;
42
43
43
public:
44
public:
44
45
Lines 207-214 private: Link Here
207
    static JSBigInt* absoluteSub(VM&, JSBigInt* x, JSBigInt* y, bool resultSign);
208
    static JSBigInt* absoluteSub(VM&, JSBigInt* x, JSBigInt* y, bool resultSign);
208
    
209
    
209
    static size_t allocationSize(unsigned length);
210
    static size_t allocationSize(unsigned length);
210
    static size_t offsetOfData();
211
    inline static size_t offsetOfData()
211
    Digit* dataStorage();
212
    {
213
        return WTF::roundUpToMultipleOf<sizeof(Digit)>(sizeof(JSBigInt));
214
    }
215
216
    inline Digit* dataStorage()
217
    {
218
        return reinterpret_cast<Digit*>(reinterpret_cast<char*>(this) + offsetOfData());
219
    }
212
220
213
    Digit digit(unsigned);
221
    Digit digit(unsigned);
214
    void setDigit(unsigned, Digit);
222
    void setDigit(unsigned, Digit);
(-)a/Source/JavaScriptCore/runtime/RegExp.h (+2 lines)
Lines 41-46 class VM; Link Here
41
JS_EXPORT_PRIVATE RegExpFlags regExpFlags(const String&);
41
JS_EXPORT_PRIVATE RegExpFlags regExpFlags(const String&);
42
42
43
class RegExp final : public JSCell {
43
class RegExp final : public JSCell {
44
    friend struct CachedRegExp;
45
44
public:
46
public:
45
    typedef JSCell Base;
47
    typedef JSCell Base;
46
    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
48
    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
(-)a/Source/JavaScriptCore/runtime/ScopedArgumentsTable.h (+2 lines)
Lines 39-44 namespace JSC { Link Here
39
// makes sense because such modifications are so uncommon. You'd have to do something crazy like
39
// makes sense because such modifications are so uncommon. You'd have to do something crazy like
40
// "delete arguments[i]" or some variant of defineOwnProperty.
40
// "delete arguments[i]" or some variant of defineOwnProperty.
41
class ScopedArgumentsTable final : public JSCell {
41
class ScopedArgumentsTable final : public JSCell {
42
    friend struct CachedScopedArgumentsTable;
43
42
public:
44
public:
43
    typedef JSCell Base;
45
    typedef JSCell Base;
44
    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
46
    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
(-)a/Source/JavaScriptCore/runtime/SymbolTable.h (+4 lines)
Lines 73-78 static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int> Link Here
73
// copy:     SymbolTableEntry --> FatEntry -----^
73
// copy:     SymbolTableEntry --> FatEntry -----^
74
74
75
struct SymbolTableEntry {
75
struct SymbolTableEntry {
76
    friend struct CachedSymbolTableEntry;
77
76
private:
78
private:
77
    static VarOffset varOffsetFromBits(intptr_t bits)
79
    static VarOffset varOffsetFromBits(intptr_t bits)
78
    {
80
    {
Lines 436-441 struct SymbolTableIndexHashTraits : HashTraits<SymbolTableEntry> { Link Here
436
};
438
};
437
439
438
class SymbolTable final : public JSCell {
440
class SymbolTable final : public JSCell {
441
    friend struct CachedSymbolTable;
442
439
public:
443
public:
440
    typedef JSCell Base;
444
    typedef JSCell Base;
441
    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
445
    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
(-)a/Source/WTF/wtf/BitVector.h (+6 lines)
Lines 33-38 Link Here
33
#include <wtf/PrintStream.h>
33
#include <wtf/PrintStream.h>
34
#include <wtf/StdLibExtras.h>
34
#include <wtf/StdLibExtras.h>
35
35
36
namespace JSC {
37
struct CachedBitVector;
38
}
39
36
namespace WTF {
40
namespace WTF {
37
41
38
// This is a space-efficient, resizeable bitvector class. In the common case it
42
// This is a space-efficient, resizeable bitvector class. In the common case it
Lines 338-343 public: Link Here
338
    iterator end() const { return iterator(*this, size()); }
342
    iterator end() const { return iterator(*this, size()); }
339
        
343
        
340
private:
344
private:
345
    friend struct JSC::CachedBitVector;
346
341
    static unsigned bitsInPointer()
347
    static unsigned bitsInPointer()
342
    {
348
    {
343
        return sizeof(void*) << 3;
349
        return sizeof(void*) << 3;

Return to bug 192782