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