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