1 | /* |
2 | * Copyright (C) 2012-2016 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 "BytecodeConventions.h" |
29 | #include "CodeType.h" |
30 | #include "DFGExitProfile.h" |
31 | #include "ExpressionRangeInfo.h" |
32 | #include "HandlerInfo.h" |
33 | #include "Identifier.h" |
34 | #include "InstructionStream.h" |
35 | #include "JSCast.h" |
36 | #include "LockDuringMarking.h" |
37 | #include "Opcode.h" |
38 | #include "ParserModes.h" |
39 | #include "RegExp.h" |
40 | #include "SpecialPointer.h" |
41 | #include "UnlinkedFunctionExecutable.h" |
42 | #include "UnlinkedMetadataTable.h" |
43 | #include "VirtualRegister.h" |
44 | #include <algorithm> |
45 | #include <wtf/BitVector.h> |
46 | #include <wtf/HashSet.h> |
47 | #include <wtf/TriState.h> |
48 | #include <wtf/Vector.h> |
49 | #include <wtf/text/UniquedStringImpl.h> |
50 | |
51 | namespace JSC { |
52 | |
53 | class BytecodeGenerator; |
54 | class BytecodeLivenessAnalysis; |
55 | class BytecodeRewriter; |
56 | class CodeBlock; |
57 | class Debugger; |
58 | class FunctionExecutable; |
59 | class ParserError; |
60 | class ScriptExecutable; |
61 | class SourceCode; |
62 | class SourceProvider; |
63 | class UnlinkedCodeBlock; |
64 | class UnlinkedFunctionCodeBlock; |
65 | class UnlinkedFunctionExecutable; |
66 | struct ExecutableInfo; |
67 | |
68 | template<typename CodeBlockType> |
69 | class CachedCodeBlock; |
70 | |
71 | typedef unsigned UnlinkedValueProfile; |
72 | typedef unsigned UnlinkedArrayProfile; |
73 | typedef unsigned UnlinkedArrayAllocationProfile; |
74 | typedef unsigned UnlinkedObjectAllocationProfile; |
75 | typedef unsigned UnlinkedLLIntCallLinkInfo; |
76 | using ConstantIdentifierSetEntry = std::pair<IdentifierSet, unsigned>; |
77 | |
78 | struct UnlinkedStringJumpTable { |
79 | struct OffsetLocation { |
80 | int32_t branchOffset; |
81 | }; |
82 | |
83 | typedef HashMap<RefPtr<StringImpl>, OffsetLocation> StringOffsetTable; |
84 | StringOffsetTable offsetTable; |
85 | |
86 | inline int32_t offsetForValue(StringImpl* value, int32_t defaultOffset) |
87 | { |
88 | StringOffsetTable::const_iterator end = offsetTable.end(); |
89 | StringOffsetTable::const_iterator loc = offsetTable.find(value); |
90 | if (loc == end) |
91 | return defaultOffset; |
92 | return loc->value.branchOffset; |
93 | } |
94 | |
95 | }; |
96 | |
97 | struct UnlinkedSimpleJumpTable { |
98 | Vector<int32_t> branchOffsets; |
99 | int32_t min; |
100 | |
101 | int32_t offsetForValue(int32_t value, int32_t defaultOffset); |
102 | void add(int32_t key, int32_t offset) |
103 | { |
104 | if (!branchOffsets[key]) |
105 | branchOffsets[key] = offset; |
106 | } |
107 | }; |
108 | |
109 | class UnlinkedCodeBlock : public JSCell { |
110 | public: |
111 | typedef JSCell Base; |
112 | static const unsigned StructureFlags = Base::StructureFlags; |
113 | |
114 | static const bool needsDestruction = true; |
115 | |
116 | enum { CallFunction, ApplyFunction }; |
117 | |
118 | bool isConstructor() const { return m_isConstructor; } |
119 | bool isStrictMode() const { return m_isStrictMode; } |
120 | bool usesEval() const { return m_usesEval; } |
121 | SourceParseMode parseMode() const { return m_parseMode; } |
122 | bool isArrowFunction() const { return isArrowFunctionParseMode(parseMode()); } |
123 | DerivedContextType derivedContextType() const { return static_cast<DerivedContextType>(m_derivedContextType); } |
124 | EvalContextType evalContextType() const { return static_cast<EvalContextType>(m_evalContextType); } |
125 | bool isArrowFunctionContext() const { return m_isArrowFunctionContext; } |
126 | bool isClassContext() const { return m_isClassContext; } |
127 | bool hasTailCalls() const { return m_hasTailCalls; } |
128 | void setHasTailCalls() { m_hasTailCalls = true; } |
129 | bool allowDirectEvalCache() const { return !(m_features & NoEvalCacheFeature); } |
130 | |
131 | void addExpressionInfo(unsigned instructionOffset, int divot, |
132 | int startOffset, int endOffset, unsigned line, unsigned column); |
133 | |
134 | void addTypeProfilerExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot); |
135 | |
136 | bool hasExpressionInfo() { return m_expressionInfo.size(); } |
137 | const Vector<ExpressionRangeInfo>& expressionInfo() { return m_expressionInfo; } |
138 | |
139 | // Special registers |
140 | void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; } |
141 | void setScopeRegister(VirtualRegister scopeRegister) { m_scopeRegister = scopeRegister; } |
142 | |
143 | // Parameter information |
144 | void setNumParameters(int newValue) { m_numParameters = newValue; } |
145 | void addParameter() { m_numParameters++; } |
146 | unsigned numParameters() const { return m_numParameters; } |
147 | |
148 | // Constant Pools |
149 | |
150 | size_t numberOfIdentifiers() const { return m_identifiers.size(); } |
151 | void addIdentifier(const Identifier& i) { return m_identifiers.append(i); } |
152 | const Identifier& identifier(int index) const { return m_identifiers[index]; } |
153 | const Vector<Identifier>& identifiers() const { return m_identifiers; } |
154 | |
155 | BitVector& bitVector(size_t i) { ASSERT(m_rareData); return m_rareData->m_bitVectors[i]; } |
156 | unsigned addBitVector(BitVector&& bitVector) |
157 | { |
158 | createRareDataIfNecessary(); |
159 | m_rareData->m_bitVectors.append(WTFMove(bitVector)); |
160 | return m_rareData->m_bitVectors.size() - 1; |
161 | } |
162 | |
163 | void addSetConstant(IdentifierSet& set) |
164 | { |
165 | createRareDataIfNecessary(); |
166 | VM& vm = *this->vm(); |
167 | auto locker = lockDuringMarking(vm.heap, cellLock()); |
168 | unsigned result = m_constantRegisters.size(); |
169 | m_constantRegisters.append(WriteBarrier<Unknown>()); |
170 | m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other); |
171 | m_rareData->m_constantIdentifierSets.append(ConstantIdentifierSetEntry(set, result)); |
172 | } |
173 | |
174 | unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other) |
175 | { |
176 | VM& vm = *this->vm(); |
177 | auto locker = lockDuringMarking(vm.heap, cellLock()); |
178 | unsigned result = m_constantRegisters.size(); |
179 | m_constantRegisters.append(WriteBarrier<Unknown>()); |
180 | m_constantRegisters.last().set(vm, this, v); |
181 | m_constantsSourceCodeRepresentation.append(sourceCodeRepresentation); |
182 | return result; |
183 | } |
184 | unsigned addConstant(LinkTimeConstant type) |
185 | { |
186 | VM& vm = *this->vm(); |
187 | auto locker = lockDuringMarking(vm.heap, cellLock()); |
188 | unsigned result = m_constantRegisters.size(); |
189 | ASSERT(result); |
190 | unsigned index = static_cast<unsigned>(type); |
191 | ASSERT(index < LinkTimeConstantCount); |
192 | m_linkTimeConstants[index] = result; |
193 | m_constantRegisters.append(WriteBarrier<Unknown>()); |
194 | m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other); |
195 | return result; |
196 | } |
197 | |
198 | unsigned registerIndexForLinkTimeConstant(LinkTimeConstant type) |
199 | { |
200 | unsigned index = static_cast<unsigned>(type); |
201 | ASSERT(index < LinkTimeConstantCount); |
202 | return m_linkTimeConstants[index]; |
203 | } |
204 | |
205 | const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; } |
206 | const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; } |
207 | ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; } |
208 | ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); } |
209 | const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation() { return m_constantsSourceCodeRepresentation; } |
210 | |
211 | unsigned numberOfConstantIdentifierSets() const { return m_rareData ? m_rareData->m_constantIdentifierSets.size() : 0; } |
212 | const Vector<ConstantIdentifierSetEntry>& constantIdentifierSets() { ASSERT(m_rareData); return m_rareData->m_constantIdentifierSets; } |
213 | |
214 | // Jumps |
215 | size_t numberOfJumpTargets() const { return m_jumpTargets.size(); } |
216 | void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); } |
217 | unsigned jumpTarget(int index) const { return m_jumpTargets[index]; } |
218 | unsigned lastJumpTarget() const { return m_jumpTargets.last(); } |
219 | |
220 | UnlinkedHandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler = RequiredHandler::AnyHandler); |
221 | UnlinkedHandlerInfo* handlerForIndex(unsigned, RequiredHandler = RequiredHandler::AnyHandler); |
222 | |
223 | bool isBuiltinFunction() const { return m_isBuiltinFunction; } |
224 | |
225 | ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); } |
226 | SuperBinding superBinding() const { return static_cast<SuperBinding>(m_superBinding); } |
227 | JSParserScriptMode scriptMode() const { return static_cast<JSParserScriptMode>(m_scriptMode); } |
228 | |
229 | void shrinkToFit(); |
230 | |
231 | void setInstructions(std::unique_ptr<InstructionStream>); |
232 | const InstructionStream& instructions() const; |
233 | |
234 | int numCalleeLocals() const { return m_numCalleeLocals; } |
235 | int numVars() const { return m_numVars; } |
236 | |
237 | // Jump Tables |
238 | |
239 | size_t numberOfSwitchJumpTables() const { return m_rareData ? m_rareData->m_switchJumpTables.size() : 0; } |
240 | UnlinkedSimpleJumpTable& addSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_switchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_switchJumpTables.last(); } |
241 | UnlinkedSimpleJumpTable& switchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_switchJumpTables[tableIndex]; } |
242 | |
243 | size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; } |
244 | UnlinkedStringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(UnlinkedStringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); } |
245 | UnlinkedStringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; } |
246 | |
247 | unsigned addFunctionDecl(UnlinkedFunctionExecutable* n) |
248 | { |
249 | VM& vm = *this->vm(); |
250 | auto locker = lockDuringMarking(vm.heap, cellLock()); |
251 | unsigned size = m_functionDecls.size(); |
252 | m_functionDecls.append(WriteBarrier<UnlinkedFunctionExecutable>()); |
253 | m_functionDecls.last().set(vm, this, n); |
254 | return size; |
255 | } |
256 | UnlinkedFunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); } |
257 | size_t numberOfFunctionDecls() { return m_functionDecls.size(); } |
258 | unsigned addFunctionExpr(UnlinkedFunctionExecutable* n) |
259 | { |
260 | VM& vm = *this->vm(); |
261 | auto locker = lockDuringMarking(vm.heap, cellLock()); |
262 | unsigned size = m_functionExprs.size(); |
263 | m_functionExprs.append(WriteBarrier<UnlinkedFunctionExecutable>()); |
264 | m_functionExprs.last().set(vm, this, n); |
265 | return size; |
266 | } |
267 | UnlinkedFunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); } |
268 | size_t numberOfFunctionExprs() { return m_functionExprs.size(); } |
269 | |
270 | // Exception handling support |
271 | size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; } |
272 | void addExceptionHandler(const UnlinkedHandlerInfo& handler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(handler); } |
273 | UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; } |
274 | |
275 | CodeType codeType() const { return static_cast<CodeType>(m_codeType); } |
276 | |
277 | VirtualRegister thisRegister() const { return m_thisRegister; } |
278 | VirtualRegister scopeRegister() const { return m_scopeRegister; } |
279 | |
280 | void addPropertyAccessInstruction(InstructionStream::Offset propertyAccessInstruction) |
281 | { |
282 | m_propertyAccessInstructions.append(propertyAccessInstruction); |
283 | } |
284 | |
285 | size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); } |
286 | const Vector<InstructionStream::Offset>& propertyAccessInstructions() const { return m_propertyAccessInstructions; } |
287 | |
288 | bool hasRareData() const { return m_rareData.get(); } |
289 | |
290 | int lineNumberForBytecodeOffset(unsigned bytecodeOffset); |
291 | |
292 | void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, |
293 | int& startOffset, int& endOffset, unsigned& line, unsigned& column) const; |
294 | |
295 | bool typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot); |
296 | |
297 | void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned lineCount, unsigned endColumn) |
298 | { |
299 | m_features = features; |
300 | m_hasCapturedVariables = hasCapturedVariables; |
301 | m_lineCount = lineCount; |
302 | // For the UnlinkedCodeBlock, startColumn is always 0. |
303 | m_endColumn = endColumn; |
304 | } |
305 | |
306 | const String& sourceURLDirective() const { return m_sourceURLDirective; } |
307 | const String& sourceMappingURLDirective() const { return m_sourceMappingURLDirective; } |
308 | void setSourceURLDirective(const String& sourceURL) { m_sourceURLDirective = sourceURL; } |
309 | void setSourceMappingURLDirective(const String& sourceMappingURL) { m_sourceMappingURLDirective = sourceMappingURL; } |
310 | |
311 | CodeFeatures codeFeatures() const { return m_features; } |
312 | bool hasCapturedVariables() const { return m_hasCapturedVariables; } |
313 | unsigned lineCount() const { return m_lineCount; } |
314 | ALWAYS_INLINE unsigned startColumn() const { return 0; } |
315 | unsigned endColumn() const { return m_endColumn; } |
316 | |
317 | void addOpProfileControlFlowBytecodeOffset(InstructionStream::Offset offset) |
318 | { |
319 | createRareDataIfNecessary(); |
320 | m_rareData->m_opProfileControlFlowBytecodeOffsets.append(offset); |
321 | } |
322 | const Vector<InstructionStream::Offset>& opProfileControlFlowBytecodeOffsets() const |
323 | { |
324 | ASSERT(m_rareData); |
325 | return m_rareData->m_opProfileControlFlowBytecodeOffsets; |
326 | } |
327 | bool hasOpProfileControlFlowBytecodeOffsets() const |
328 | { |
329 | return m_rareData && !m_rareData->m_opProfileControlFlowBytecodeOffsets.isEmpty(); |
330 | } |
331 | |
332 | void dumpExpressionRangeInfo(); // For debugging purpose only. |
333 | |
334 | bool wasCompiledWithDebuggingOpcodes() const { return m_codeGenerationMode.contains(CodeGenerationMode::Debugger); } |
335 | bool wasCompiledWithTypeProfilerOpcodes() const { return m_codeGenerationMode.contains(CodeGenerationMode::TypeProfiler); } |
336 | bool wasCompiledWithControlFlowProfilerOpcodes() const { return m_codeGenerationMode.contains(CodeGenerationMode::ControlFlowProfiler); } |
337 | OptionSet<CodeGenerationMode> codeGenerationMode() const { return m_codeGenerationMode; } |
338 | |
339 | TriState didOptimize() const { return static_cast<TriState>(m_didOptimize); } |
340 | void setDidOptimize(TriState didOptimize) { m_didOptimize = static_cast<unsigned>(didOptimize); } |
341 | |
342 | static constexpr unsigned maxAge = 7; |
343 | |
344 | unsigned age() const { return m_age; } |
345 | void resetAge() { m_age = 0; } |
346 | |
347 | void dump(PrintStream&) const; |
348 | |
349 | BytecodeLivenessAnalysis& livenessAnalysis(CodeBlock* codeBlock) |
350 | { |
351 | if (m_liveness) |
352 | return *m_liveness; |
353 | return livenessAnalysisSlow(codeBlock); |
354 | } |
355 | |
356 | #if ENABLE(DFG_JIT) |
357 | bool hasExitSite(const ConcurrentJSLocker& locker, const DFG::FrequentExitSite& site) const |
358 | { |
359 | return m_exitProfile.hasExitSite(locker, site); |
360 | } |
361 | |
362 | bool hasExitSite(const DFG::FrequentExitSite& site) |
363 | { |
364 | ConcurrentJSLocker locker(m_lock); |
365 | return hasExitSite(locker, site); |
366 | } |
367 | |
368 | DFG::ExitProfile& exitProfile() { return m_exitProfile; } |
369 | #endif |
370 | |
371 | UnlinkedMetadataTable& metadata() { return m_metadata.get(); } |
372 | |
373 | size_t metadataSizeInBytes() |
374 | { |
375 | return m_metadata->sizeInBytes(); |
376 | } |
377 | |
378 | |
379 | protected: |
380 | UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&, OptionSet<CodeGenerationMode>); |
381 | |
382 | template<typename CodeBlockType> |
383 | UnlinkedCodeBlock(Decoder&, Structure*, const CachedCodeBlock<CodeBlockType>&); |
384 | |
385 | ~UnlinkedCodeBlock(); |
386 | |
387 | void finishCreation(VM& vm) |
388 | { |
389 | Base::finishCreation(vm); |
390 | } |
391 | |
392 | private: |
393 | friend class BytecodeRewriter; |
394 | friend class BytecodeGenerator; |
395 | |
396 | template<typename CodeBlockType> |
397 | friend class CachedCodeBlock; |
398 | |
399 | void applyModification(BytecodeRewriter&, InstructionStreamWriter&); |
400 | |
401 | void createRareDataIfNecessary() |
402 | { |
403 | if (!m_rareData) { |
404 | auto locker = lockDuringMarking(*heap(), cellLock()); |
405 | m_rareData = std::make_unique<RareData>(); |
406 | } |
407 | } |
408 | |
409 | void getLineAndColumn(const ExpressionRangeInfo&, unsigned& line, unsigned& column) const; |
410 | BytecodeLivenessAnalysis& livenessAnalysisSlow(CodeBlock*); |
411 | |
412 | |
413 | VirtualRegister m_thisRegister; |
414 | VirtualRegister m_scopeRegister; |
415 | |
416 | std::array<unsigned, LinkTimeConstantCount> m_linkTimeConstants; |
417 | |
418 | unsigned m_usesEval : 1; |
419 | unsigned m_isStrictMode : 1; |
420 | unsigned m_isConstructor : 1; |
421 | unsigned m_hasCapturedVariables : 1; |
422 | unsigned m_isBuiltinFunction : 1; |
423 | unsigned m_superBinding : 1; |
424 | unsigned m_scriptMode: 1; |
425 | unsigned m_isArrowFunctionContext : 1; |
426 | unsigned m_isClassContext : 1; |
427 | unsigned m_hasTailCalls : 1; |
428 | unsigned m_constructorKind : 2; |
429 | unsigned m_derivedContextType : 2; |
430 | unsigned m_evalContextType : 2; |
431 | unsigned m_codeType : 2; |
432 | unsigned m_didOptimize : 2; |
433 | unsigned m_age : 3; |
434 | static_assert(((1U << 3) - 1) >= maxAge); |
435 | public: |
436 | ConcurrentJSLock m_lock; |
437 | private: |
438 | CodeFeatures m_features { 0 }; |
439 | SourceParseMode m_parseMode; |
440 | OptionSet<CodeGenerationMode> m_codeGenerationMode; |
441 | |
442 | unsigned m_lineCount { 0 }; |
443 | unsigned m_endColumn { UINT_MAX }; |
444 | |
445 | int m_numVars { 0 }; |
446 | int m_numCalleeLocals { 0 }; |
447 | int m_numParameters { 0 }; |
448 | |
449 | String m_sourceURLDirective; |
450 | String m_sourceMappingURLDirective; |
451 | |
452 | Vector<InstructionStream::Offset> m_jumpTargets; |
453 | Ref<UnlinkedMetadataTable> m_metadata; |
454 | std::unique_ptr<InstructionStream> m_instructions; |
455 | std::unique_ptr<BytecodeLivenessAnalysis> m_liveness; |
456 | |
457 | |
458 | #if ENABLE(DFG_JIT) |
459 | DFG::ExitProfile m_exitProfile; |
460 | #endif |
461 | |
462 | |
463 | Vector<InstructionStream::Offset> m_propertyAccessInstructions; |
464 | |
465 | // Constant Pools |
466 | Vector<Identifier> m_identifiers; |
467 | Vector<WriteBarrier<Unknown>> m_constantRegisters; |
468 | Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation; |
469 | typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector; |
470 | FunctionExpressionVector m_functionDecls; |
471 | FunctionExpressionVector m_functionExprs; |
472 | |
473 | public: |
474 | struct RareData { |
475 | WTF_MAKE_STRUCT_FAST_ALLOCATED; |
476 | |
477 | Vector<UnlinkedHandlerInfo> m_exceptionHandlers; |
478 | |
479 | // Jump Tables |
480 | Vector<UnlinkedSimpleJumpTable> m_switchJumpTables; |
481 | Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables; |
482 | |
483 | Vector<ExpressionRangeInfo::FatPosition> m_expressionInfoFatPositions; |
484 | |
485 | struct TypeProfilerExpressionRange { |
486 | unsigned m_startDivot; |
487 | unsigned m_endDivot; |
488 | }; |
489 | HashMap<unsigned, TypeProfilerExpressionRange> m_typeProfilerInfoMap; |
490 | Vector<InstructionStream::Offset> m_opProfileControlFlowBytecodeOffsets; |
491 | Vector<BitVector> m_bitVectors; |
492 | Vector<ConstantIdentifierSetEntry> m_constantIdentifierSets; |
493 | }; |
494 | |
495 | void addOutOfLineJumpTarget(InstructionStream::Offset, int target); |
496 | int outOfLineJumpOffset(InstructionStream::Offset); |
497 | int outOfLineJumpOffset(const InstructionStream::Ref& instruction) |
498 | { |
499 | return outOfLineJumpOffset(instruction.offset()); |
500 | } |
501 | |
502 | private: |
503 | using OutOfLineJumpTargets = HashMap<InstructionStream::Offset, int>; |
504 | |
505 | OutOfLineJumpTargets replaceOutOfLineJumpTargets() |
506 | { |
507 | OutOfLineJumpTargets newJumpTargets; |
508 | std::swap(m_outOfLineJumpTargets, newJumpTargets); |
509 | return newJumpTargets; |
510 | } |
511 | |
512 | OutOfLineJumpTargets m_outOfLineJumpTargets; |
513 | std::unique_ptr<RareData> m_rareData; |
514 | Vector<ExpressionRangeInfo> m_expressionInfo; |
515 | |
516 | protected: |
517 | static void visitChildren(JSCell*, SlotVisitor&); |
518 | static size_t estimatedSize(JSCell*, VM&); |
519 | |
520 | public: |
521 | DECLARE_INFO; |
522 | }; |
523 | |
524 | } |
525 | |