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