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