[go: nahoru, domu]

Source/JavaScriptCore/ChangeLog

 12018-12-27 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 Add the logic to serialize and deserialize the new JSC bytecode. For now,
 10 the cache is only used for tests. Also, during decoding, the cached objects
 11 are mmap'd from disk, but only used for creating instances of the respective
 12 in-memory version of each object. Ideally, the mmap'd objects should be used
 13 at runtime in the future.
 14
 15 * JavaScriptCore.xcodeproj/project.pbxproj:
 16 * builtins/BuiltinNames.cpp:
 17 (JSC::BuiltinNames::BuiltinNames):
 18 * builtins/BuiltinNames.h:
 19 * bytecode/CodeBlock.cpp:
 20 (JSC::CodeBlock::setConstantIdentifierSetRegisters):
 21 * bytecode/CodeBlock.h:
 22 * bytecode/HandlerInfo.h:
 23 (JSC::UnlinkedHandlerInfo::UnlinkedHandlerInfo):
 24 * bytecode/InstructionStream.h:
 25 * bytecode/UnlinkedCodeBlock.h:
 26 (JSC::UnlinkedCodeBlock::addSetConstant):
 27 (JSC::UnlinkedCodeBlock::constantIdentifierSets):
 28 * bytecode/UnlinkedEvalCodeBlock.h:
 29 * bytecode/UnlinkedFunctionCodeBlock.h:
 30 * bytecode/UnlinkedFunctionExecutable.h:
 31 * bytecode/UnlinkedGlobalCodeBlock.h:
 32 (JSC::UnlinkedGlobalCodeBlock::UnlinkedGlobalCodeBlock):
 33 * bytecode/UnlinkedMetadataTable.h:
 34 * bytecode/UnlinkedModuleProgramCodeBlock.h:
 35 * bytecode/UnlinkedProgramCodeBlock.h:
 36 * interpreter/Interpreter.cpp:
 37 * jsc.cpp:
 38 (functionQuit):
 39 (runJSC):
 40 * parser/SourceCode.h:
 41 * parser/SourceCodeKey.h:
 42 (JSC::SourceCodeKey::operator!= const):
 43 * parser/UnlinkedSourceCode.h:
 44 * parser/VariableEnvironment.h:
 45 * runtime/CachedTypes.h: Added.
 46 (JSC::Encoder::Encoder):
 47 (JSC::Encoder::~Encoder):
 48 (JSC::Encoder::vm):
 49 (JSC::Encoder::buffer const):
 50 (JSC::Encoder::size const):
 51 (JSC::Encoder::mallocOffset):
 52 (JSC::Encoder::malloc):
 53 (JSC::Encoder::offsetOf):
 54 (JSC::Encoder::cachePtr):
 55 (JSC::Encoder::offsetForPtr):
 56 (JSC::Decoder::Decoder):
 57 (JSC::Decoder::~Decoder):
 58 (JSC::Decoder::vm):
 59 (JSC::Decoder::offsetOf):
 60 (JSC::Decoder::cacheOffset):
 61 (JSC::Decoder::addFinalizer):
 62 (JSC::encode):
 63 (JSC::decode):
 64 (JSC::CachedObject::sizeOf):
 65 (JSC::CachedObject::cast):
 66 (JSC::VariableLengthObject::buffer const):
 67 (JSC::VariableLengthObject::buffer):
 68 (JSC::VariableLengthObject::allocate):
 69 (JSC::CachedPtr::encode):
 70 (JSC::CachedPtr::decode const):
 71 (JSC::CachedPtr::operator->):
 72 (JSC::CachedPtr::operator-> const):
 73 (JSC::CachedRefPtr::encode):
 74 (JSC::CachedRefPtr::decode const):
 75 (JSC::CachedWriteBarrier::encode):
 76 (JSC::CachedWriteBarrier::decode const):
 77 (JSC::CachedVector::encode):
 78 (JSC::CachedVector::decode const):
 79 (JSC::CachedPair::encode):
 80 (JSC::CachedPair::decode const):
 81 (JSC::CachedHashMap::encode):
 82 (JSC::CachedHashMap::decode const):
 83 (JSC::CachedUniquedStringImpl::encode):
 84 (JSC::CachedUniquedStringImpl::decode const):
 85 (JSC::CachedStringImpl::encode):
 86 (JSC::CachedStringImpl::decode const):
 87 (JSC::CachedString::encode):
 88 (JSC::CachedString::decode const):
 89 (JSC::CachedIdentifier::encode):
 90 (JSC::CachedIdentifier::decode const):
 91 (JSC::CachedOptional::encode):
 92 (JSC::CachedOptional::decode const):
 93 (JSC::CachedOptional::decodeAsPtr const):
 94 (JSC::CachedSimpleJumpTable::encode):
 95 (JSC::CachedSimpleJumpTable::decode const):
 96 (JSC::CachedStringJumpTable::encode):
 97 (JSC::CachedStringJumpTable::decode const):
 98 (JSC::CachedRareData::encode):
 99 (JSC::CachedRareData::decode const):
 100 (JSC::CachedBitVector::encode):
 101 (JSC::CachedBitVector::decode const):
 102 (JSC::CachedHashSet::encode):
 103 (JSC::CachedHashSet::decode const):
 104 (JSC::CachedConstantIdentifierSetEntry::encode):
 105 (JSC::CachedConstantIdentifierSetEntry::decode const):
 106 (JSC::CachedVariableEnvironment::encode):
 107 (JSC::CachedVariableEnvironment::decode const):
 108 (JSC::CachedArray::encode):
 109 (JSC::CachedArray::decode const):
 110 (JSC::CachedScopedArgumentsTable::encode):
 111 (JSC::CachedScopedArgumentsTable::decode const):
 112 (JSC::CachedSymbolTableEntry::encode):
 113 (JSC::CachedSymbolTableEntry::decode const):
 114 (JSC::CachedSymbolTable::encode):
 115 (JSC::CachedSymbolTable::decode const):
 116 (JSC::CachedImmutableButterfly::encode):
 117 (JSC::CachedImmutableButterfly::decode const):
 118 (JSC::CachedRegExp::encode):
 119 (JSC::CachedRegExp::decode const):
 120 (JSC::CachedTemplateObjectDescriptor::encode):
 121 (JSC::CachedTemplateObjectDescriptor::decode const):
 122 (JSC::CachedBigInt::encode):
 123 (JSC::CachedBigInt::decode const):
 124 (JSC::CachedJSValue::encode):
 125 (JSC::CachedJSValue::decode const):
 126 (JSC::CachedInstructionStream::encode):
 127 (JSC::CachedInstructionStream::decode const):
 128 (JSC::CachedMetadataTable::encode):
 129 (JSC::CachedMetadataTable::decode const):
 130 (JSC::CachedSourceOrigin::encode):
 131 (JSC::CachedSourceOrigin::decode const):
 132 (JSC::CachedTextPosition::encode):
 133 (JSC::CachedTextPosition::decode const):
 134 (JSC::CachedSourceProviderShape::encode):
 135 (JSC::CachedSourceProviderShape::decode const):
 136 (JSC::CachedStringSourceProvider::encode):
 137 (JSC::CachedStringSourceProvider::decode const):
 138 (JSC::CachedWebAssemblySourceProvider::encode):
 139 (JSC::CachedWebAssemblySourceProvider::decode const):
 140 (JSC::CachedSourceProvider::encode):
 141 (JSC::CachedSourceProvider::decode const):
 142 (JSC::CachedUnlinkedSourceCodeShape::encode):
 143 (JSC::CachedUnlinkedSourceCodeShape::decode const):
 144 (JSC::CachedSourceCode::encode):
 145 (JSC::CachedSourceCode::decode const):
 146 (JSC::CachedProgramCodeBlock::encode):
 147 (JSC::CachedProgramCodeBlock::decode const):
 148 (JSC::CachedModuleCodeBlock::encode):
 149 (JSC::CachedModuleCodeBlock::decode const):
 150 (JSC::CachedEvalCodeBlock::encode):
 151 (JSC::CachedEvalCodeBlock::decode const):
 152 (JSC::CachedFunctionCodeBlock::encode):
 153 (JSC::CachedFunctionCodeBlock::decode const):
 154 (JSC::UnlinkedFunctionCodeBlock::UnlinkedFunctionCodeBlock):
 155 (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
 156 (JSC::CachedCodeBlockType>::decode const):
 157 (JSC::UnlinkedProgramCodeBlock::UnlinkedProgramCodeBlock):
 158 (JSC::UnlinkedModuleProgramCodeBlock::UnlinkedModuleProgramCodeBlock):
 159 (JSC::UnlinkedEvalCodeBlock::UnlinkedEvalCodeBlock):
 160 (JSC::CachedFunctionExecutable::encode):
 161 (JSC::CachedFunctionExecutable::decode const):
 162 (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
 163 (JSC::CachedCodeBlockType>::encode):
 164 (JSC::CachedSourceCodeKey::encode):
 165 (JSC::CachedSourceCodeKey::decode const):
 166 (JSC::CacheEntry::encode):
 167 (JSC::CacheEntry:: const):
 168 (JSC::encodeCodeBlock):
 169 * runtime/CodeCache.cpp:
 170 (JSC::CodeCacheMap::pruneSlowCase):
 171 (JSC::CodeCache::getUnlinkedGlobalCodeBlock):
 172 (JSC::CodeCache::getUnlinkedGlobalFunctionExecutable):
 173 (JSC::CodeCache::write):
 174 * runtime/CodeCache.h:
 175 (JSC::CodeCacheMap::begin):
 176 (JSC::CodeCacheMap::end):
 177 (JSC::CodeCacheMap::fetchFromDiskImpl):
 178 (JSC::CodeCacheMap::findCacheAndUpdateAge):
 179 (JSC::writeCodeBlock):
 180 * runtime/JSBigInt.cpp:
 181 * runtime/JSBigInt.h:
 182 * runtime/Options.cpp:
 183 (JSC::recomputeDependentOptions):
 184 * runtime/Options.h:
 185 * runtime/RegExp.h:
 186 * runtime/ScopedArgumentsTable.h:
 187 * runtime/SymbolTable.h:
 188
11892018-12-25 Fujii Hironori <Hironori.Fujii@sony.com>
2190
3191 [JSC][Win][Clang] warning: implicit conversion from 'size_t' (aka 'unsigned long long') to 'int32_t' (aka 'int') changes value from 18446744073709551552 to -64 [-Wconstant-conversion]

Source/WTF/ChangeLog

 12018-12-27 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 BitVectors have to be friends with JSC::CacheBitVector to allow
 10 serializing its buffer as part of the bytecode cache encoding.
 11
 12 * wtf/BitVector.h:
 13
1142018-12-21 Dan Bernstein <mitz@apple.com>
215
316 Fixed building for macOS 10.13 using the macOS 10.14 SDK.

Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

31393139 14386A731DD69895008652C4 /* DirectEvalExecutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectEvalExecutable.h; sourceTree = "<group>"; };
31403140 14386A761DD6989C008652C4 /* IndirectEvalExecutable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndirectEvalExecutable.cpp; sourceTree = "<group>"; };
31413141 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>"; };
31423143 1440051F0A531D3B0005F061 /* Node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Node.h; path = tests/Node.h; sourceTree = "<group>"; };
31433144 144005200A531D3B0005F061 /* Node.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Node.c; path = tests/Node.c; sourceTree = "<group>"; };
31443145 144007480A536CC20005F061 /* NodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NodeList.h; path = tests/NodeList.h; sourceTree = "<group>"; };

65816582 9E729409190F0306001A91B5 /* BundlePath.mm */,
65826583 0FB7F38B15ED8E3800F167B2 /* Butterfly.h */,
65836584 0FB7F38C15ED8E3800F167B2 /* ButterflyInlines.h */,
 6585 143BE26521C857770020CD17 /* CachedTypes.h */,
65846586 0FEC3C5F1F379F5300F59B6C /* CagedBarrierPtr.h */,
65856587 BCA62DFE0E2826230004F30D /* CallData.cpp */,
65866588 145C507F0D9DF63B0088F6B9 /* CallData.h */,

Source/JavaScriptCore/builtins/BuiltinNames.cpp

@@BuiltinNames::BuiltinNames(VM* vm, CommonIdentifiers* commonIdentifiers)
6363 JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PRIVATE_TO_PUBLIC_ENTRY)
6464 JSC_FOREACH_BUILTIN_FUNCTION_NAME(INITIALIZE_PUBLIC_TO_PRIVATE_ENTRY)
6565 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)
6667 JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(INITIALIZE_SYMBOL_PUBLIC_TO_PRIVATE_ENTRY)
6768 m_privateToPublicMap.add(m_dollarVMPrivateName.impl(), &m_dollarVMName);
6869 m_publicToPrivateMap.add(m_dollarVMName.impl(), &m_dollarVMPrivateName);

Source/JavaScriptCore/builtins/BuiltinNames.h

@@extern SymbolImpl::StaticSymbolImpl polyProtoPrivateName;
213213// We commandeer the publicToPrivateMap to allow us to convert private symbol names into the appropriate symbol.
214214// e.g. @iteratorSymbol points to Symbol.iterator in this map rather than to a an actual private name.
215215// 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);
216217#define INITIALIZE_SYMBOL_PUBLIC_TO_PRIVATE_ENTRY(name) m_publicToPrivateMap.add(m_##name##SymbolPrivateIdentifier.impl(), &m_##name##Symbol);
217218
218219class BuiltinNames {

Source/JavaScriptCore/bytecode/CodeBlock.cpp

@@CodeBlock::~CodeBlock()
864864#endif // ENABLE(JIT)
865865}
866866
867 void CodeBlock::setConstantIdentifierSetRegisters(VM& vm, const Vector<ConstantIndentifierSetEntry>& constants)
 867void CodeBlock::setConstantIdentifierSetRegisters(VM& vm, const Vector<ConstantIdentifierSetEntry>& constants)
868868{
869869 auto scope = DECLARE_THROW_SCOPE(vm);
870870 JSGlobalObject* globalObject = m_globalObject.get();

Source/JavaScriptCore/bytecode/CodeBlock.h

@@private:
892892
893893 void updateAllPredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles);
894894
895  void setConstantIdentifierSetRegisters(VM&, const Vector<ConstantIndentifierSetEntry>& constants);
 895 void setConstantIdentifierSetRegisters(VM&, const Vector<ConstantIdentifierSetEntry>& constants);
896896
897897 void setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation);
898898

Source/JavaScriptCore/bytecode/HandlerInfo.h

@@struct HandlerInfoBase {
8989};
9090
9191struct UnlinkedHandlerInfo : public HandlerInfoBase {
 92 UnlinkedHandlerInfo()
 93 {
 94 }
 95
9296 UnlinkedHandlerInfo(uint32_t start, uint32_t end, uint32_t target, HandlerType handlerType)
9397 {
9498 this->start = start;

Source/JavaScriptCore/bytecode/InstructionStream.h

@@class InstructionStream {
3939 using InstructionBuffer = Vector<uint8_t, 0, UnsafeVectorOverflow>;
4040
4141 friend class InstructionStreamWriter;
 42 friend struct CachedInstructionStream;
4243public:
4344 size_t sizeInBytes() const;
4445

Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h

@@class UnlinkedFunctionCodeBlock;
6565class UnlinkedFunctionExecutable;
6666struct ExecutableInfo;
6767
 68template<typename CodeBlockType, typename CachedCodeBlockType>
 69struct CachedCodeBlock;
 70
6871typedef unsigned UnlinkedValueProfile;
6972typedef unsigned UnlinkedArrayProfile;
7073typedef unsigned UnlinkedArrayAllocationProfile;
7174typedef unsigned UnlinkedObjectAllocationProfile;
7275typedef unsigned UnlinkedLLIntCallLinkInfo;
73 using ConstantIndentifierSetEntry = std::pair<IdentifierSet, unsigned>;
 76using ConstantIdentifierSetEntry = std::pair<IdentifierSet, unsigned>;
7477
7578struct UnlinkedStringJumpTable {
7679 struct OffsetLocation {

@@public:
168171 unsigned result = m_constantRegisters.size();
169172 m_constantRegisters.append(WriteBarrier<Unknown>());
170173 m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
171  m_constantIdentifierSets.append(ConstantIndentifierSetEntry(set, result));
 174 m_constantIdentifierSets.append(ConstantIdentifierSetEntry(set, result));
172175 }
173176
174177 unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other)

@@public:
202205 return m_linkTimeConstants[index];
203206 }
204207 const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; }
205  const Vector<ConstantIndentifierSetEntry>& constantIdentifierSets() { return m_constantIdentifierSets; }
 208 const Vector<ConstantIdentifierSetEntry>& constantIdentifierSets() { return m_constantIdentifierSets; }
206209 const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
207210 ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
208211 ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }

@@public:
367370
368371protected:
369372 UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&, DebuggerMode);
 373
 374 template<typename CodeBlockType, typename CachedCodeBlockType>
 375 UnlinkedCodeBlock(Decoder&, Structure*, const CachedCodeBlock<CodeBlockType, CachedCodeBlockType>&);
 376
370377 ~UnlinkedCodeBlock();
371378
372379 void finishCreation(VM& vm)

@@private:
378385 friend class BytecodeRewriter;
379386 friend class BytecodeGenerator;
380387
 388 template<typename CodeBlockType, typename CachedCodeBlockType>
 389 friend struct CachedCodeBlock;
 390
381391 void applyModification(BytecodeRewriter&, InstructionStreamWriter&);
382392
383393 void createRareDataIfNecessary()

@@private:
444454 Vector<Identifier> m_identifiers;
445455 Vector<BitVector> m_bitVectors;
446456 Vector<WriteBarrier<Unknown>> m_constantRegisters;
447  Vector<ConstantIndentifierSetEntry> m_constantIdentifierSets;
 457 Vector<ConstantIdentifierSetEntry> m_constantIdentifierSets;
448458 Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation;
449459 typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector;
450460 FunctionExpressionVector m_functionDecls;

Source/JavaScriptCore/bytecode/UnlinkedEvalCodeBlock.h

2929
3030namespace JSC {
3131
 32struct CachedEvalCodeBlock;
 33
3234class UnlinkedEvalCodeBlock final : public UnlinkedGlobalCodeBlock {
3335public:
3436 typedef UnlinkedGlobalCodeBlock Base;

@@public:
5961 m_functionHoistingCandidates = WTFMove(functionHoistingCandidates);
6062 }
6163private:
 64 friend CachedEvalCodeBlock;
 65
6266 UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info, DebuggerMode debuggerMode)
6367 : Base(vm, structure, EvalCode, info, debuggerMode)
6468 {
6569 }
6670
 71 UnlinkedEvalCodeBlock(Decoder&, const CachedEvalCodeBlock&);
 72
6773 Vector<Identifier, 0, UnsafeVectorOverflow> m_variables;
6874 Vector<Identifier, 0, UnsafeVectorOverflow> m_functionHoistingCandidates;
6975

Source/JavaScriptCore/bytecode/UnlinkedFunctionCodeBlock.h

2929
3030namespace JSC {
3131
 32struct CachedFunctionCodeBlock;
 33
3234class UnlinkedFunctionCodeBlock final : public UnlinkedCodeBlock {
3335public:
3436 typedef UnlinkedCodeBlock Base;

@@public:
4446 static void destroy(JSCell*);
4547
4648private:
 49 friend CachedFunctionCodeBlock;
 50
4751 UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info, DebuggerMode debuggerMode)
4852 : Base(vm, structure, codeType, info, debuggerMode)
4953 {
5054 }
 55
 56 UnlinkedFunctionCodeBlock(Decoder&, const CachedFunctionCodeBlock&);
5157
5258public:
5359 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)

Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h

3939
4040namespace JSC {
4141
 42class Decoder;
4243class FunctionMetadataNode;
4344class FunctionExecutable;
4445class ParserError;
4546class SourceProvider;
4647class UnlinkedFunctionCodeBlock;
 48struct CachedFunctionExecutable;
4749
4850enum UnlinkedFunctionKind {
4951 UnlinkedNormalFunction,

@@class UnlinkedFunctionExecutable final : public JSCell {
5456public:
5557 friend class CodeCache;
5658 friend class VM;
 59 friend CachedFunctionExecutable;
5760
5861 typedef JSCell Base;
5962 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;

@@public:
147150
148151private:
149152 UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, VariableEnvironment&, JSC::DerivedContextType, bool isBuiltinDefaultClassConstructor);
 153 UnlinkedFunctionExecutable(Decoder&, VariableEnvironment&, const CachedFunctionExecutable&);
150154
151155 unsigned m_firstLineOffset;
152156 unsigned m_lineCount;

Source/JavaScriptCore/bytecode/UnlinkedGlobalCodeBlock.h

@@protected:
3838 : Base(vm, structure, codeType, info, debuggerMode)
3939 {
4040 }
 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 }
4147};
4248
4349}

Source/JavaScriptCore/bytecode/UnlinkedMetadataTable.h

@@class MetadataTable;
3535class UnlinkedMetadataTable {
3636 friend class LLIntOffsetsExtractor;
3737 friend class MetadataTable;
 38 friend struct CachedMetadataTable;
3839
3940public:
4041 struct LinkingData {

Source/JavaScriptCore/bytecode/UnlinkedModuleProgramCodeBlock.h

2929
3030namespace JSC {
3131
 32class Decoder;
 33struct CachedModuleCodeBlock;
 34
3235class UnlinkedModuleProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
3336public:
3437 typedef UnlinkedGlobalCodeBlock Base;

@@public:
7477 }
7578
7679private:
 80 friend CachedModuleCodeBlock;
 81
7782 UnlinkedModuleProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info, DebuggerMode debuggerMode)
7883 : Base(vm, structure, ModuleCode, info, debuggerMode)
7984 {
8085 }
8186
 87 UnlinkedModuleProgramCodeBlock(Decoder&, const CachedModuleCodeBlock&);
 88
8289 int m_moduleEnvironmentSymbolTableConstantRegisterOffset { 0 };
8390
8491public:

Source/JavaScriptCore/bytecode/UnlinkedProgramCodeBlock.h

2929
3030namespace JSC {
3131
 32struct CachedProgramCodeBlock;
 33
3234class UnlinkedProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
3335public:
3436 typedef UnlinkedGlobalCodeBlock Base;

@@public:
5052 const VariableEnvironment& lexicalDeclarations() const { return m_lexicalDeclarations; }
5153
5254private:
 55 friend CachedProgramCodeBlock;
 56
5357 UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info, DebuggerMode debuggerMode)
5458 : Base(vm, structure, GlobalCode, info, debuggerMode)
5559 {
5660 }
5761
 62 UnlinkedProgramCodeBlock(Decoder&, const CachedProgramCodeBlock&);
 63
5864 VariableEnvironment m_varDeclarations;
5965 VariableEnvironment m_lexicalDeclarations;
6066

Source/JavaScriptCore/interpreter/Interpreter.cpp

3535#include "CallFrameClosure.h"
3636#include "CatchScope.h"
3737#include "CodeBlock.h"
 38#include "CodeCache.h"
3839#include "DirectArguments.h"
3940#include "Heap.h"
4041#include "Debugger.h"

Source/JavaScriptCore/jsc.cpp

2828#include "ButterflyInlines.h"
2929#include "CatchScope.h"
3030#include "CodeBlock.h"
 31#include "CodeCache.h"
3132#include "Completion.h"
3233#include "ConfigFile.h"
3334#include "Disassembler.h"

@@EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState* exec)
19811982 return JSValue::encode(jsUndefined());
19821983}
19831984
1984 EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
 1985EncodedJSValue JSC_HOST_CALL functionQuit(ExecState* exec)
19851986{
 1987 VM& vm = exec->vm();
 1988 vm.codeCache()->write(vm);
 1989
19861990 jscExit(EXIT_SUCCESS);
19871991
19881992#if COMPILER(MSVC)

@@int runJSC(const CommandLine& options, bool isWorker, const Func& func)
28432847#endif
28442848 }
28452849
 2850 vm.codeCache()->write(vm);
 2851
28462852 if (isWorker) {
28472853 JSLockHolder locker(vm);
28482854 // This is needed because we don't want the worker's main

Source/JavaScriptCore/parser/SourceCode.h

3333namespace JSC {
3434
3535 class SourceCode : public UnlinkedSourceCode {
 36 friend struct CachedSourceCode;
 37
3638 public:
3739 SourceCode()
3840 : UnlinkedSourceCode()

Source/JavaScriptCore/parser/SourceCodeKey.h

@@enum class TypeProfilerEnabled { No, Yes };
3737enum class ControlFlowProfilerEnabled { No, Yes };
3838
3939class SourceCodeFlags {
 40 friend struct CachedSourceCodeKey;
 41
4042public:
4143 SourceCodeFlags() = default;
4244

@@private:
7072};
7173
7274class SourceCodeKey {
 75 friend struct CachedSourceCodeKey;
 76
7377public:
7478 SourceCodeKey()
7579 {

@@public:
114118 && string() == other.string();
115119 }
116120
 121 bool operator!=(const SourceCodeKey& other) const
 122 {
 123 return !(*this == other);
 124 }
 125
117126 struct Hash {
118127 static unsigned hash(const SourceCodeKey& key) { return key.hash(); }
119128 static bool equal(const SourceCodeKey& a, const SourceCodeKey& b) { return a == b; }

Source/JavaScriptCore/parser/UnlinkedSourceCode.h

3535namespace JSC {
3636
3737 class UnlinkedSourceCode {
 38 template<typename SourceType, typename CacheType>
 39 friend struct CachedUnlinkedSourceCodeShape;
 40
3841 public:
3942 UnlinkedSourceCode()
4043 : m_provider(0)

Source/JavaScriptCore/parser/VariableEnvironment.h

@@public:
116116 bool isEverythingCaptured() const { return m_isEverythingCaptured; }
117117
118118private:
 119 friend struct CachedVariableEnvironment;
 120
119121 Map m_map;
120122 bool m_isEverythingCaptured { false };
121123};

Source/JavaScriptCore/runtime/CachedTypes.h

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

Source/JavaScriptCore/runtime/CodeCache.cpp

@@void CodeCacheMap::pruneSlowCase()
4343
4444 while (m_size > m_capacity || !canPruneQuickly()) {
4545 MapType::iterator it = m_map.begin();
 46
 47 writeCodeBlock(*it->value.cell->vm(), it->key, it->value);
 48
4649 m_size -= it->key.length();
4750 m_map.remove(it);
4851 }

@@UnlinkedCodeBlockType* CodeCache::getUnlinkedGlobalCodeBlock(VM& vm, ExecutableT
5962 vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No,
6063 vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No,
6164 WTF::nullopt);
62  SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key);
63  if (cache && Options::useCodeCache()) {
64  UnlinkedCodeBlockType* unlinkedCodeBlock = jsCast<UnlinkedCodeBlockType*>(cache->cell.get());
 65 UnlinkedCodeBlockType* unlinkedCodeBlock = m_sourceCode.findCacheAndUpdateAge<UnlinkedCodeBlockType>(vm, key);
 66 if (unlinkedCodeBlock && Options::useCodeCache()) {
6567 unsigned lineCount = unlinkedCodeBlock->lineCount();
6668 unsigned startColumn = unlinkedCodeBlock->startColumn() + source.startColumn().oneBasedInt();
6769 bool endColumnIsOnStartLine = !lineCount;

@@UnlinkedCodeBlockType* CodeCache::getUnlinkedGlobalCodeBlock(VM& vm, ExecutableT
7173 source.provider()->setSourceMappingURLDirective(unlinkedCodeBlock->sourceMappingURLDirective());
7274 return unlinkedCodeBlock;
7375 }
74 
 76
7577 VariableEnvironment variablesUnderTDZ;
76  UnlinkedCodeBlockType* unlinkedCodeBlock = generateUnlinkedCodeBlock<UnlinkedCodeBlockType, ExecutableType>(vm, executable, source, strictMode, scriptMode, debuggerMode, error, evalContextType, &variablesUnderTDZ);
 78 unlinkedCodeBlock = generateUnlinkedCodeBlock<UnlinkedCodeBlockType, ExecutableType>(vm, executable, source, strictMode, scriptMode, debuggerMode, error, evalContextType, &variablesUnderTDZ);
7779
7880 if (unlinkedCodeBlock && Options::useCodeCache())
7981 m_sourceCode.addCache(key, SourceCodeValue(vm, unlinkedCodeBlock, m_sourceCode.age()));

@@UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& v
110112 vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No,
111113 vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No,
112114 functionConstructorParametersEndPosition);
113  SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key);
114  if (cache && Options::useCodeCache()) {
115  UnlinkedFunctionExecutable* executable = jsCast<UnlinkedFunctionExecutable*>(cache->cell.get());
 115 UnlinkedFunctionExecutable* executable = m_sourceCode.findCacheAndUpdateAge<UnlinkedFunctionExecutable>(vm, key);
 116 if (executable && Options::useCodeCache()) {
116117 source.provider()->setSourceURLDirective(executable->sourceURLDirective());
117118 source.provider()->setSourceMappingURLDirective(executable->sourceMappingURLDirective());
118119 return executable;

@@UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& v
155156 return functionExecutable;
156157}
157158
 159void CodeCache::write(VM& vm)
 160{
 161 for (const auto& it : m_sourceCode)
 162 writeCodeBlock(vm, it.key, it.value);
 163}
 164
158165}

Source/JavaScriptCore/runtime/CodeCache.h

2626#pragma once
2727
2828#include "BytecodeGenerator.h"
 29#include "CachedTypes.h"
2930#include "ExecutableInfo.h"
3031#include "JSCInlines.h"
3132#include "Parser.h"

3738#include "UnlinkedEvalCodeBlock.h"
3839#include "UnlinkedModuleProgramCodeBlock.h"
3940#include "UnlinkedProgramCodeBlock.h"
 41#include <sys/stat.h>
4042#include <wtf/Forward.h>
4143#include <wtf/text/WTFString.h>
4244

@@public:
8991 {
9092 }
9193
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 UnlinkedCodeBlockType* fetchFromDiskImpl(VM& vm, const SourceCodeKey& key)
 99 {
 100 const char* cachePath = Options::diskCachePath();
 101 if (!cachePath)
 102 return nullptr;
 103
 104 unsigned hash = key.hash();
 105 char filename[512];
 106 int count = snprintf(filename, 512, "%s/%u.cache", cachePath, hash);
 107 if (count < 0 || count > 512)
 108 return nullptr;
 109
 110 int fd = open(filename, O_RDONLY);
 111 if (fd == -1)
 112 return nullptr;
 113
 114 int rc = flock(fd, LOCK_SH | LOCK_NB);
 115 if (rc) {
 116 close(fd);
 117 return nullptr;
 118 }
 119
 120 struct stat sb;
 121 int res = fstat(fd, &sb);
 122 if (res || !sb.st_size)
 123 return nullptr;
 124
 125 const void* buffer = mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
 126 const auto* cachedCodeBlock = reinterpret_cast<const CacheEntry<UnlinkedCodeBlockType>*>(buffer);
 127 Decoder decoder(vm, cachedCodeBlock, sb.st_size);
 128 std::pair<SourceCodeKey, UnlinkedCodeBlockType*> entry;
 129 {
 130 DeferGC deferGC(vm.heap);
 131 entry = cachedCodeBlock->decode(decoder);
 132 }
 133
 134 if (entry.first != key)
 135 return nullptr;
 136
 137 addCache(key, SourceCodeValue(vm, entry.second, m_age));
 138 return entry.second;
 139 }
 140
 141 template<typename UnlinkedCodeBlockType>
 142 std::enable_if_t<std::is_base_of<UnlinkedCodeBlock, UnlinkedCodeBlockType>::value && !std::is_same<UnlinkedCodeBlockType, UnlinkedEvalCodeBlock>::value, UnlinkedCodeBlockType*>
 143 fetchFromDisk(VM& vm, const SourceCodeKey& key)
 144 {
 145 UnlinkedCodeBlockType* codeBlock = fetchFromDiskImpl<UnlinkedCodeBlockType>(vm, key);
 146 if (UNLIKELY(Options::forceDiskCache()))
 147 RELEASE_ASSERT(codeBlock);
 148 return codeBlock;
 149 }
 150
 151 template<typename T>
 152 std::enable_if_t<!std::is_base_of<UnlinkedCodeBlock, T>::value || std::is_same<T, UnlinkedEvalCodeBlock>::value, T*>
 153 fetchFromDisk(VM&, const SourceCodeKey&) { return nullptr; }
 154
 155 template<typename UnlinkedCodeBlockType>
 156 UnlinkedCodeBlockType* findCacheAndUpdateAge(VM& vm, const SourceCodeKey& key)
93157 {
94158 prune();
95159
96160 iterator findResult = m_map.find(key);
97161 if (findResult == m_map.end())
98  return nullptr;
 162 return fetchFromDisk<UnlinkedCodeBlockType>(vm, key);
99163
100164 int64_t age = m_age - findResult->value.age;
101165 if (age > m_capacity) {

@@public:
115179 findResult->value.age = m_age;
116180 m_age += key.length();
117181
118  return &findResult->value;
 182 return jsCast<UnlinkedCodeBlockType*>(findResult->value.cell.get());
119183 }
120184
121185 AddResult addCache(const SourceCodeKey& key, const SourceCodeValue& value)

@@public:
197261 UnlinkedFunctionExecutable* getUnlinkedGlobalFunctionExecutable(VM&, const Identifier&, const SourceCode&, DebuggerMode, Optional<int> functionConstructorParametersEndPosition, ParserError&);
198262
199263 void clear() { m_sourceCode.clear(); }
 264 JS_EXPORT_PRIVATE void write(VM&);
200265
201266private:
202267 template <class UnlinkedCodeBlockType, class ExecutableType>

@@UnlinkedCodeBlockType* generateUnlinkedCodeBlock(VM& vm, ExecutableType* executa
256321 return unlinkedCodeBlock;
257322}
258323
 324ALWAYS_INLINE static void writeCodeBlock(VM& vm, const SourceCodeKey& key, const SourceCodeValue& value)
 325{
 326 const char* cachePath = Options::diskCachePath();
 327 if (LIKELY(!cachePath))
 328 return;
 329
 330 UnlinkedCodeBlock* codeBlock = jsDynamicCast<UnlinkedCodeBlock*>(vm, value.cell.get());
 331 if (!codeBlock)
 332 return;
 333
 334 unsigned hash = key.hash();
 335 char filename[512];
 336 int count = snprintf(filename, 512, "%s/%u.cache", cachePath, hash);
 337 if (count < 0 || count > 512)
 338 return;
 339
 340 Encoder encoder(vm);
 341 encodeCodeBlock(encoder, key, codeBlock);
 342
 343 int fd = open(filename, O_CREAT | O_WRONLY, 0666);
 344 int rc = flock(fd, LOCK_EX | LOCK_NB);
 345 if (!rc)
 346 ::write(fd, encoder.buffer(), encoder.size());
 347 close(fd);
 348}
 349
 350
259351} // namespace JSC

Source/JavaScriptCore/runtime/JSBigInt.cpp

@@bool JSBigInt::getPrimitiveNumber(ExecState* exec, double& number, JSValue& resu
16881688 return true;
16891689}
16901690
1691 inline size_t JSBigInt::offsetOfData()
1692 {
1693  return WTF::roundUpToMultipleOf<sizeof(Digit)>(sizeof(JSBigInt));
1694 }
1695 
16961691template <typename CharType>
16971692JSBigInt* JSBigInt::parseInt(ExecState* exec, CharType* data, unsigned length, ErrorParseMode errorParseMode)
16981693{

@@JSBigInt* JSBigInt::parseInt(ExecState* exec, VM& vm, CharType* data, unsigned l
17951790 return nullptr;
17961791}
17971792
1798 inline JSBigInt::Digit* JSBigInt::dataStorage()
1799 {
1800  return reinterpret_cast<Digit*>(reinterpret_cast<char*>(this) + offsetOfData());
1801 }
1802 
18031793inline JSBigInt::Digit JSBigInt::digit(unsigned n)
18041794{
18051795 ASSERT(n < length());

Source/JavaScriptCore/runtime/JSBigInt.h

@@namespace JSC {
3838class JSBigInt final : public JSCell {
3939 using Base = JSCell;
4040 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal | OverridesToThis;
 41 friend struct CachedBigInt;
4142
4243public:
4344

@@private:
228229 static Optional<Digit> toShiftAmount(JSBigInt* x);
229230
230231 static size_t allocationSize(unsigned length);
231  static size_t offsetOfData();
232  Digit* dataStorage();
 232 inline static size_t offsetOfData()
 233 {
 234 return WTF::roundUpToMultipleOf<sizeof(Digit)>(sizeof(JSBigInt));
 235 }
 236
 237 inline Digit* dataStorage()
 238 {
 239 return reinterpret_cast<Digit*>(reinterpret_cast<char*>(this) + offsetOfData());
 240 }
233241
234242 Digit digit(unsigned);
235243 void setDigit(unsigned, Digit);

Source/JavaScriptCore/runtime/Options.cpp

@@static void recomputeDependentOptions()
517517 // https://bugs.webkit.org/show_bug.cgi?id=177956
518518 Options::useProbeOSRExit() = false;
519519#endif
 520
 521 if (!Options::useCodeCache())
 522 Options::diskCachePath() = nullptr;
 523
 524 if (!Options::diskCachePath())
 525 Options::forceDiskCache() = false;
520526}
521527
522528void Options::initialize()

Source/JavaScriptCore/runtime/Options.h

@@constexpr bool enableWebAssemblyStreamingApi = false;
508508 v(bool, traceLLIntExecution, false, Configurable, nullptr) \
509509 v(bool, traceLLIntSlowPath, false, Configurable, nullptr) \
510510 v(bool, traceBaselineJITExecution, false, Normal, nullptr) \
 511 v(optionString, diskCachePath, nullptr, Restricted, "") \
 512 v(bool, forceDiskCache, false, Restricted, "") \
511513
512514
513515enum OptionEquivalence {

Source/JavaScriptCore/runtime/RegExp.h

@@class VM;
4141JS_EXPORT_PRIVATE RegExpFlags regExpFlags(const String&);
4242
4343class RegExp final : public JSCell {
 44 friend struct CachedRegExp;
 45
4446public:
4547 typedef JSCell Base;
4648 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;

Source/JavaScriptCore/runtime/ScopedArgumentsTable.h

@@namespace JSC {
3939// makes sense because such modifications are so uncommon. You'd have to do something crazy like
4040// "delete arguments[i]" or some variant of defineOwnProperty.
4141class ScopedArgumentsTable final : public JSCell {
 42 friend struct CachedScopedArgumentsTable;
 43
4244public:
4345 typedef JSCell Base;
4446 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;

Source/JavaScriptCore/runtime/SymbolTable.h

@@static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int>
7373// copy: SymbolTableEntry --> FatEntry -----^
7474
7575struct SymbolTableEntry {
 76 friend struct CachedSymbolTableEntry;
 77
7678private:
7779 static VarOffset varOffsetFromBits(intptr_t bits)
7880 {

@@struct SymbolTableIndexHashTraits : HashTraits<SymbolTableEntry> {
436438};
437439
438440class SymbolTable final : public JSCell {
 441 friend struct CachedSymbolTable;
 442
439443public:
440444 typedef JSCell Base;
441445 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;

Source/WTF/wtf/BitVector.h

3333#include <wtf/PrintStream.h>
3434#include <wtf/StdLibExtras.h>
3535
 36namespace JSC {
 37struct CachedBitVector;
 38}
 39
3640namespace WTF {
3741
3842// This is a space-efficient, resizeable bitvector class. In the common case it

@@public:
338342 iterator end() const { return iterator(*this, size()); }
339343
340344private:
 345 friend struct JSC::CachedBitVector;
 346
341347 static unsigned bitsInPointer()
342348 {
343349 return sizeof(void*) << 3;

Tools/ChangeLog

 12018-12-27 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 Add test helper to execute bytecode-cache tests: it executes each test
 10 twice, the first with JSC_diskCachePath set to a temporary directory
 11 and second with JSC_forceDiskCache=true (in addition to the cache path)
 12 to guarantee that only the disk cache is being used and no new
 13 UnlinkedCodeBlocks are being created.
 14
 15 * Scripts/jsc-stress-test-helpers/bytecode-cache-test-helper: Added.
 16 * Scripts/run-jsc-stress-tests:
 17
1182018-12-26 Adrian Perez de Castro <aperez@igalia.com>
219
320 [Tools] Remove references to Bison and Flex

Tools/Scripts/jsc-stress-test-helpers/bytecode-cache-test-helper

 1#!/usr/bin/env ruby
 2
 3# Copyright (C) 2018 Apple Inc. All rights reserved.
 4#
 5# Redistribution and use in source and binary forms, with or without
 6# modification, are permitted provided that the following conditions
 7# are met:
 8#
 9# 1. Redistributions of source code must retain the above copyright
 10# notice, this list of conditions and the following disclaimer.
 11# 2. Redistributions in binary form must reproduce the above copyright
 12# notice, this list of conditions and the following disclaimer in the
 13# documentation and/or other materials provided with the distribution.
 14#
 15# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 16# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 17# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 18# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 19# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 20# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 21# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 22# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 23# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 24# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 25
 26require 'rubygems'
 27require 'fileutils'
 28require 'json'
 29require 'shellwords'
 30require 'tmpdir'
 31
 32def mysys(*cmd)
 33 raise "Command #{cmd.inspect} failed: #{$?.inspect}" unless system(*cmd)
 34end
 35
 36pathToVM = ARGV[0]
 37inputFile = ARGV[1]
 38extraOptions = ARGV[2..-1]
 39diskCachePath = Dir.mktmpdir [inputFile, 'bytecode-cache']
 40
 41begin
 42 ENV["JSC_diskCachePath"] = diskCachePath
 43 mysys(pathToVM, inputFile, *extraOptions)
 44 ENV["JSC_forceDiskCache"] = "true"
 45 mysys(pathToVM, inputFile, *extraOptions)
 46ensure
 47 FileUtils.rm_rf(diskCachePath)
 48end

Tools/Scripts/run-jsc-stress-tests

@@def runDefault(*optionalTestSpecificOptions)
655655 run("default", *(FTL_OPTIONS + optionalTestSpecificOptions))
656656end
657657
 658def runBytecodeCache(*optionalTestSpecificOptions)
 659 options = BASE_OPTIONS + $testSpecificRequiredOptions + FTL_OPTIONS + optionalTestSpecificOptions
 660 addRunCommand("bytecode-cache", ["ruby", (pathToHelpers + "bytecode-cache-test-helper").to_s, pathToVM.to_s, $benchmark.to_s] + options, silentOutputHandler, simpleErrorHandler)
 661end
 662
658663def runBigIntEnabled(*optionalTestSpecificOptions)
659664 # FIXME: <rdar://problem/40331121>
660665 if $remote or ($architecture !~ /x86/i and $hostOS == "darwin")

@@def defaultRun
751756 defaultQuickRun
752757 else
753758 runDefault
 759 runBytecodeCache
754760 if $jitTests
755761 runNoLLInt
756762 runNoCJITValidatePhases