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