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