75a966c68c22a9f73fade5f1cf86ed2335dee0f2
[WebKit-https.git] / Source / JavaScriptCore / bytecode / UnlinkedCodeBlock.h
1 /*
2  * Copyright (C) 2012-2015 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 #ifndef UnlinkedCodeBlock_h
27 #define UnlinkedCodeBlock_h
28
29 #include "BytecodeConventions.h"
30 #include "CodeSpecializationKind.h"
31 #include "CodeType.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 "SymbolTable.h"
41 #include "VariableEnvironment.h"
42 #include "VirtualRegister.h"
43
44 #include <wtf/RefCountedArray.h>
45 #include <wtf/Vector.h>
46
47 namespace JSC {
48
49 class Debugger;
50 class FunctionBodyNode;
51 class FunctionExecutable;
52 class JSScope;
53 class ParserError;
54 class ScriptExecutable;
55 class SourceCode;
56 class SourceProvider;
57 class SymbolTable;
58 class UnlinkedCodeBlock;
59 class UnlinkedFunctionCodeBlock;
60 class UnlinkedInstructionStream;
61
62 typedef unsigned UnlinkedValueProfile;
63 typedef unsigned UnlinkedArrayProfile;
64 typedef unsigned UnlinkedArrayAllocationProfile;
65 typedef unsigned UnlinkedObjectAllocationProfile;
66 typedef unsigned UnlinkedLLIntCallLinkInfo;
67
68 struct ExecutableInfo {
69     ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, ConstructorKind constructorKind)
70         : m_needsActivation(needsActivation)
71         , m_usesEval(usesEval)
72         , m_isStrictMode(isStrictMode)
73         , m_isConstructor(isConstructor)
74         , m_isBuiltinFunction(isBuiltinFunction)
75         , m_constructorKind(static_cast<unsigned>(constructorKind))
76     {
77         ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind));
78     }
79
80     bool needsActivation() const { return m_needsActivation; }
81     bool usesEval() const { return m_usesEval; }
82     bool isStrictMode() const { return m_isStrictMode; }
83     bool isConstructor() const { return m_isConstructor; }
84     bool isBuiltinFunction() const { return m_isBuiltinFunction; }
85     ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
86
87 private:
88     unsigned m_needsActivation : 1;
89     unsigned m_usesEval : 1;
90     unsigned m_isStrictMode : 1;
91     unsigned m_isConstructor : 1;
92     unsigned m_isBuiltinFunction : 1;
93     unsigned m_constructorKind : 2;
94 };
95
96 enum UnlinkedFunctionKind {
97     UnlinkedNormalFunction,
98     UnlinkedBuiltinFunction,
99 };
100
101 class UnlinkedFunctionExecutable final : public JSCell {
102 public:
103     friend class BuiltinExecutables;
104     friend class CodeCache;
105     friend class VM;
106
107     typedef JSCell Base;
108     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
109
110     static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionBodyNode* node, UnlinkedFunctionKind unlinkedFunctionKind, VariableEnvironment& parentScopeTDZVariables, RefPtr<SourceProvider>&& sourceOverride = nullptr)
111     {
112         UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap))
113             UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, WTF::move(sourceOverride), node, unlinkedFunctionKind, parentScopeTDZVariables);
114         instance->finishCreation(*vm);
115         return instance;
116     }
117
118     const Identifier& name() const { return m_name; }
119     const Identifier& inferredName() const { return m_inferredName; }
120     JSString* nameValue() const { return m_nameValue.get(); }
121     unsigned parameterCount() const { return m_parameterCount; };
122     FunctionParseMode parseMode() const { return m_parseMode; };
123     bool isInStrictContext() const { return m_isInStrictContext; }
124     FunctionMode functionMode() const { return static_cast<FunctionMode>(m_functionMode); }
125     ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
126
127     unsigned unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; }
128     unsigned unlinkedBodyStartColumn() const { return m_unlinkedBodyStartColumn; }
129     unsigned unlinkedBodyEndColumn() const { return m_unlinkedBodyEndColumn; }
130     unsigned startOffset() const { return m_startOffset; }
131     unsigned sourceLength() { return m_sourceLength; }
132     unsigned parametersStartOffset() const { return m_parametersStartOffset; }
133     unsigned typeProfilingStartOffset() const { return m_typeProfilingStartOffset; }
134     unsigned typeProfilingEndOffset() const { return m_typeProfilingEndOffset; }
135
136     UnlinkedFunctionCodeBlock* codeBlockFor(
137         VM&, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, 
138         ParserError&);
139
140     static UnlinkedFunctionExecutable* fromGlobalCode(
141         const Identifier&, ExecState&, const SourceCode&, JSObject*& exception, 
142         int overrideLineNumber);
143
144     FunctionExecutable* link(VM&, const SourceCode&, int overrideLineNumber = -1);
145
146     void clearCodeForRecompilation()
147     {
148         m_codeBlockForCall.clear();
149         m_codeBlockForConstruct.clear();
150     }
151
152     void recordParse(CodeFeatures features, bool hasCapturedVariables)
153     {
154         m_features = features;
155         m_hasCapturedVariables = hasCapturedVariables;
156     }
157
158     CodeFeatures features() const { return m_features; }
159     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
160
161     static const bool needsDestruction = true;
162     static void destroy(JSCell*);
163
164     bool isBuiltinFunction() const { return m_isBuiltinFunction; }
165     bool isClassConstructorFunction() const { return constructorKind() != ConstructorKind::None; }
166     const VariableEnvironment* parentScopeTDZVariables() const { return &m_parentScopeTDZVariables; }
167
168 private:
169     UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, RefPtr<SourceProvider>&& sourceOverride, FunctionBodyNode*, UnlinkedFunctionKind, VariableEnvironment&);
170     WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
171     WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;
172
173     Identifier m_name;
174     Identifier m_inferredName;
175     WriteBarrier<JSString> m_nameValue;
176     RefPtr<SourceProvider> m_sourceOverride;
177     VariableEnvironment m_parentScopeTDZVariables;
178     unsigned m_firstLineOffset;
179     unsigned m_lineCount;
180     unsigned m_unlinkedFunctionNameStart;
181     unsigned m_unlinkedBodyStartColumn;
182     unsigned m_unlinkedBodyEndColumn;
183     unsigned m_startOffset;
184     unsigned m_sourceLength;
185     unsigned m_parametersStartOffset;
186     unsigned m_typeProfilingStartOffset;
187     unsigned m_typeProfilingEndOffset;
188     unsigned m_parameterCount;
189     FunctionParseMode m_parseMode;
190
191     CodeFeatures m_features;
192
193     unsigned m_isInStrictContext : 1;
194     unsigned m_hasCapturedVariables : 1;
195     unsigned m_isBuiltinFunction : 1;
196     unsigned m_constructorKind : 2;
197     unsigned m_functionMode : 1; // FunctionMode
198
199 protected:
200     void finishCreation(VM& vm)
201     {
202         Base::finishCreation(vm);
203         m_nameValue.set(vm, this, jsString(&vm, name().string()));
204     }
205
206     static void visitChildren(JSCell*, SlotVisitor&);
207
208 public:
209     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
210     {
211         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionExecutableType, StructureFlags), info());
212     }
213
214     DECLARE_EXPORT_INFO;
215 };
216
217 struct UnlinkedStringJumpTable {
218     typedef HashMap<RefPtr<StringImpl>, int32_t> StringOffsetTable;
219     StringOffsetTable offsetTable;
220
221     inline int32_t offsetForValue(StringImpl* value, int32_t defaultOffset)
222     {
223         StringOffsetTable::const_iterator end = offsetTable.end();
224         StringOffsetTable::const_iterator loc = offsetTable.find(value);
225         if (loc == end)
226             return defaultOffset;
227         return loc->value;
228     }
229
230 };
231
232 struct UnlinkedSimpleJumpTable {
233     Vector<int32_t> branchOffsets;
234     int32_t min;
235
236     int32_t offsetForValue(int32_t value, int32_t defaultOffset);
237     void add(int32_t key, int32_t offset)
238     {
239         if (!branchOffsets[key])
240             branchOffsets[key] = offset;
241     }
242 };
243
244 struct UnlinkedInstruction {
245     UnlinkedInstruction() { u.operand = 0; }
246     UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
247     UnlinkedInstruction(int operand) { u.operand = operand; }
248     union {
249         OpcodeID opcode;
250         int32_t operand;
251         unsigned index;
252     } u;
253 };
254
255 class UnlinkedCodeBlock : public JSCell {
256 public:
257     typedef JSCell Base;
258     static const unsigned StructureFlags = Base::StructureFlags;
259
260     static const bool needsDestruction = true;
261
262     enum { CallFunction, ApplyFunction };
263
264     bool isConstructor() const { return m_isConstructor; }
265     bool isStrictMode() const { return m_isStrictMode; }
266     bool usesEval() const { return m_usesEval; }
267
268     bool needsFullScopeChain() const { return m_needsFullScopeChain; }
269
270     void addExpressionInfo(unsigned instructionOffset, int divot,
271         int startOffset, int endOffset, unsigned line, unsigned column);
272
273     void addTypeProfilerExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot);
274
275     bool hasExpressionInfo() { return m_expressionInfo.size(); }
276
277     // Special registers
278     void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; }
279     void setScopeRegister(VirtualRegister scopeRegister) { m_scopeRegister = scopeRegister; }
280     void setActivationRegister(VirtualRegister activationRegister) { m_lexicalEnvironmentRegister = activationRegister; }
281
282     bool usesGlobalObject() const { return m_globalObjectRegister.isValid(); }
283     void setGlobalObjectRegister(VirtualRegister globalObjectRegister) { m_globalObjectRegister = globalObjectRegister; }
284     VirtualRegister globalObjectRegister() const { return m_globalObjectRegister; }
285
286     // Parameter information
287     void setNumParameters(int newValue) { m_numParameters = newValue; }
288     void addParameter() { m_numParameters++; }
289     unsigned numParameters() const { return m_numParameters; }
290
291     unsigned addRegExp(RegExp* r)
292     {
293         createRareDataIfNecessary();
294         unsigned size = m_rareData->m_regexps.size();
295         m_rareData->m_regexps.append(WriteBarrier<RegExp>(*m_vm, this, r));
296         return size;
297     }
298     unsigned numberOfRegExps() const
299     {
300         if (!m_rareData)
301             return 0;
302         return m_rareData->m_regexps.size();
303     }
304     RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
305
306     // Constant Pools
307
308     size_t numberOfIdentifiers() const { return m_identifiers.size(); }
309     void addIdentifier(const Identifier& i) { return m_identifiers.append(i); }
310     const Identifier& identifier(int index) const { return m_identifiers[index]; }
311     const Vector<Identifier>& identifiers() const { return m_identifiers; }
312
313     unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other)
314     {
315         unsigned result = m_constantRegisters.size();
316         m_constantRegisters.append(WriteBarrier<Unknown>());
317         m_constantRegisters.last().set(*m_vm, this, v);
318         m_constantsSourceCodeRepresentation.append(sourceCodeRepresentation);
319         return result;
320     }
321     unsigned addConstant(LinkTimeConstant type)
322     {
323         unsigned result = m_constantRegisters.size();
324         ASSERT(result);
325         unsigned index = static_cast<unsigned>(type);
326         ASSERT(index < LinkTimeConstantCount);
327         m_linkTimeConstants[index] = result;
328         m_constantRegisters.append(WriteBarrier<Unknown>());
329         m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
330         return result;
331     }
332     unsigned registerIndexForLinkTimeConstant(LinkTimeConstant type)
333     {
334         unsigned index = static_cast<unsigned>(type);
335         ASSERT(index < LinkTimeConstantCount);
336         return m_linkTimeConstants[index];
337     }
338     const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; }
339     const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
340     ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
341     const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation() { return m_constantsSourceCodeRepresentation; }
342
343     // Jumps
344     size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
345     void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
346     unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
347     unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
348
349     bool isBuiltinFunction() const { return m_isBuiltinFunction; }
350
351     ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
352
353     void shrinkToFit()
354     {
355         m_jumpTargets.shrinkToFit();
356         m_identifiers.shrinkToFit();
357         m_constantRegisters.shrinkToFit();
358         m_constantsSourceCodeRepresentation.shrinkToFit();
359         m_functionDecls.shrinkToFit();
360         m_functionExprs.shrinkToFit();
361         m_propertyAccessInstructions.shrinkToFit();
362         m_expressionInfo.shrinkToFit();
363
364 #if ENABLE(BYTECODE_COMMENTS)
365         m_bytecodeComments.shrinkToFit();
366 #endif
367         if (m_rareData) {
368             m_rareData->m_exceptionHandlers.shrinkToFit();
369             m_rareData->m_regexps.shrinkToFit();
370             m_rareData->m_constantBuffers.shrinkToFit();
371             m_rareData->m_switchJumpTables.shrinkToFit();
372             m_rareData->m_stringSwitchJumpTables.shrinkToFit();
373             m_rareData->m_expressionInfoFatPositions.shrinkToFit();
374         }
375     }
376
377     void setInstructions(std::unique_ptr<UnlinkedInstructionStream>);
378     const UnlinkedInstructionStream& instructions() const;
379
380     int m_numVars;
381     int m_numCapturedVars;
382     int m_numCalleeRegisters;
383
384     // Jump Tables
385
386     size_t numberOfSwitchJumpTables() const { return m_rareData ? m_rareData->m_switchJumpTables.size() : 0; }
387     UnlinkedSimpleJumpTable& addSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_switchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_switchJumpTables.last(); }
388     UnlinkedSimpleJumpTable& switchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_switchJumpTables[tableIndex]; }
389
390     size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }
391     UnlinkedStringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(UnlinkedStringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
392     UnlinkedStringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
393
394     unsigned addFunctionDecl(UnlinkedFunctionExecutable* n)
395     {
396         unsigned size = m_functionDecls.size();
397         m_functionDecls.append(WriteBarrier<UnlinkedFunctionExecutable>());
398         m_functionDecls.last().set(*m_vm, this, n);
399         return size;
400     }
401     UnlinkedFunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
402     size_t numberOfFunctionDecls() { return m_functionDecls.size(); }
403     unsigned addFunctionExpr(UnlinkedFunctionExecutable* n)
404     {
405         unsigned size = m_functionExprs.size();
406         m_functionExprs.append(WriteBarrier<UnlinkedFunctionExecutable>());
407         m_functionExprs.last().set(*m_vm, this, n);
408         return size;
409     }
410     UnlinkedFunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
411     size_t numberOfFunctionExprs() { return m_functionExprs.size(); }
412
413     // Exception handling support
414     size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
415     void addExceptionHandler(const UnlinkedHandlerInfo& handler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(handler); }
416     UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
417
418     void setSymbolTableConstantIndex(int index) { m_symbolTableConstantIndex = index; }
419     int symbolTableConstantIndex() const { return m_symbolTableConstantIndex; }
420
421     VM* vm() const { return m_vm; }
422
423     UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; }
424     unsigned numberOfArrayProfiles() { return m_arrayProfileCount; }
425     UnlinkedArrayAllocationProfile addArrayAllocationProfile() { return m_arrayAllocationProfileCount++; }
426     unsigned numberOfArrayAllocationProfiles() { return m_arrayAllocationProfileCount; }
427     UnlinkedObjectAllocationProfile addObjectAllocationProfile() { return m_objectAllocationProfileCount++; }
428     unsigned numberOfObjectAllocationProfiles() { return m_objectAllocationProfileCount; }
429     UnlinkedValueProfile addValueProfile() { return m_valueProfileCount++; }
430     unsigned numberOfValueProfiles() { return m_valueProfileCount; }
431
432     UnlinkedLLIntCallLinkInfo addLLIntCallLinkInfo() { return m_llintCallLinkInfoCount++; }
433     unsigned numberOfLLintCallLinkInfos() { return m_llintCallLinkInfoCount; }
434
435     CodeType codeType() const { return m_codeType; }
436
437     VirtualRegister thisRegister() const { return m_thisRegister; }
438     VirtualRegister scopeRegister() const { return m_scopeRegister; }
439     VirtualRegister activationRegister() const { return m_lexicalEnvironmentRegister; }
440     bool hasActivationRegister() const { return m_lexicalEnvironmentRegister.isValid(); }
441
442     void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
443     {
444         m_propertyAccessInstructions.append(propertyAccessInstruction);
445     }
446
447     size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); }
448     const Vector<unsigned>& propertyAccessInstructions() const { return m_propertyAccessInstructions; }
449
450     typedef Vector<JSValue> ConstantBuffer;
451
452     size_t constantBufferCount() { ASSERT(m_rareData); return m_rareData->m_constantBuffers.size(); }
453     unsigned addConstantBuffer(unsigned length)
454     {
455         createRareDataIfNecessary();
456         unsigned size = m_rareData->m_constantBuffers.size();
457         m_rareData->m_constantBuffers.append(Vector<JSValue>(length));
458         return size;
459     }
460
461     const ConstantBuffer& constantBuffer(unsigned index) const
462     {
463         ASSERT(m_rareData);
464         return m_rareData->m_constantBuffers[index];
465     }
466
467     ConstantBuffer& constantBuffer(unsigned index)
468     {
469         ASSERT(m_rareData);
470         return m_rareData->m_constantBuffers[index];
471     }
472
473     bool hasRareData() const { return m_rareData.get(); }
474
475     int lineNumberForBytecodeOffset(unsigned bytecodeOffset);
476
477     void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,
478         int& startOffset, int& endOffset, unsigned& line, unsigned& column);
479
480     bool typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot);
481
482     void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount, unsigned endColumn)
483     {
484         m_features = features;
485         m_hasCapturedVariables = hasCapturedVariables;
486         m_firstLine = firstLine;
487         m_lineCount = lineCount;
488         // For the UnlinkedCodeBlock, startColumn is always 0.
489         m_endColumn = endColumn;
490     }
491
492     CodeFeatures codeFeatures() const { return m_features; }
493     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
494     unsigned firstLine() const { return m_firstLine; }
495     unsigned lineCount() const { return m_lineCount; }
496     ALWAYS_INLINE unsigned startColumn() const { return 0; }
497     unsigned endColumn() const { return m_endColumn; }
498
499     void addOpProfileControlFlowBytecodeOffset(size_t offset) { m_opProfileControlFlowBytecodeOffsets.append(offset); }
500     const Vector<size_t>& opProfileControlFlowBytecodeOffsets() const { return m_opProfileControlFlowBytecodeOffsets; }
501
502     void dumpExpressionRangeInfo(); // For debugging purpose only.
503
504 protected:
505     UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&);
506     ~UnlinkedCodeBlock();
507
508     void finishCreation(VM& vm)
509     {
510         Base::finishCreation(vm);
511         if (codeType() == GlobalCode)
512             return;
513         m_symbolTable.set(vm, this, SymbolTable::create(vm));
514     }
515
516 private:
517
518     void createRareDataIfNecessary()
519     {
520         if (!m_rareData)
521             m_rareData = std::make_unique<RareData>();
522     }
523
524     void getLineAndColumn(ExpressionRangeInfo&, unsigned& line, unsigned& column);
525
526     std::unique_ptr<UnlinkedInstructionStream> m_unlinkedInstructions;
527
528     int m_numParameters;
529     VM* m_vm;
530
531     VirtualRegister m_thisRegister;
532     VirtualRegister m_scopeRegister;
533     VirtualRegister m_lexicalEnvironmentRegister;
534     VirtualRegister m_globalObjectRegister;
535
536     unsigned m_needsFullScopeChain : 1;
537     unsigned m_usesEval : 1;
538     unsigned m_isStrictMode : 1;
539     unsigned m_isConstructor : 1;
540     unsigned m_hasCapturedVariables : 1;
541     unsigned m_isBuiltinFunction : 1;
542     unsigned m_constructorKind : 2;
543
544     unsigned m_firstLine;
545     unsigned m_lineCount;
546     unsigned m_endColumn;
547
548     CodeFeatures m_features;
549     CodeType m_codeType;
550
551     Vector<unsigned> m_jumpTargets;
552
553     // Constant Pools
554     Vector<Identifier> m_identifiers;
555     Vector<WriteBarrier<Unknown>> m_constantRegisters;
556     Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation;
557     std::array<unsigned, LinkTimeConstantCount> m_linkTimeConstants;
558     typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector;
559     FunctionExpressionVector m_functionDecls;
560     FunctionExpressionVector m_functionExprs;
561
562     WriteBarrier<SymbolTable> m_symbolTable;
563     int m_symbolTableConstantIndex { 0 };
564
565     Vector<unsigned> m_propertyAccessInstructions;
566
567 #if ENABLE(BYTECODE_COMMENTS)
568     Vector<Comment>  m_bytecodeComments;
569     size_t m_bytecodeCommentIterator;
570 #endif
571
572     unsigned m_arrayProfileCount;
573     unsigned m_arrayAllocationProfileCount;
574     unsigned m_objectAllocationProfileCount;
575     unsigned m_valueProfileCount;
576     unsigned m_llintCallLinkInfoCount;
577
578 public:
579     struct RareData {
580         WTF_MAKE_FAST_ALLOCATED;
581     public:
582         Vector<UnlinkedHandlerInfo> m_exceptionHandlers;
583
584         // Rare Constants
585         Vector<WriteBarrier<RegExp>> m_regexps;
586
587         // Buffers used for large array literals
588         Vector<ConstantBuffer> m_constantBuffers;
589
590         // Jump Tables
591         Vector<UnlinkedSimpleJumpTable> m_switchJumpTables;
592         Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables;
593
594         Vector<ExpressionRangeInfo::FatPosition> m_expressionInfoFatPositions;
595     };
596
597 private:
598     std::unique_ptr<RareData> m_rareData;
599     Vector<ExpressionRangeInfo> m_expressionInfo;
600     struct TypeProfilerExpressionRange {
601         unsigned m_startDivot;
602         unsigned m_endDivot;
603     };
604     HashMap<unsigned, TypeProfilerExpressionRange> m_typeProfilerInfoMap;
605     Vector<size_t> m_opProfileControlFlowBytecodeOffsets;
606
607 protected:
608     static void visitChildren(JSCell*, SlotVisitor&);
609
610 public:
611     DECLARE_INFO;
612 };
613
614 class UnlinkedGlobalCodeBlock : public UnlinkedCodeBlock {
615 public:
616     typedef UnlinkedCodeBlock Base;
617
618 protected:
619     UnlinkedGlobalCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
620         : Base(vm, structure, codeType, info)
621     {
622     }
623
624     DECLARE_INFO;
625 };
626
627 class UnlinkedProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
628 private:
629     friend class CodeCache;
630     static UnlinkedProgramCodeBlock* create(VM* vm, const ExecutableInfo& info)
631     {
632         UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedProgramCodeBlock>(vm->heap)) UnlinkedProgramCodeBlock(vm, vm->unlinkedProgramCodeBlockStructure.get(), info);
633         instance->finishCreation(*vm);
634         return instance;
635     }
636
637 public:
638     typedef UnlinkedGlobalCodeBlock Base;
639     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
640
641     static void destroy(JSCell*);
642
643     void setVariableDeclarations(const VariableEnvironment& environment) { m_varDeclarations = environment; }
644     const VariableEnvironment& variableDeclarations() const { return m_varDeclarations; }
645
646     static void visitChildren(JSCell*, SlotVisitor&);
647
648 private:
649     UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
650         : Base(vm, structure, GlobalCode, info)
651     {
652     }
653
654     VariableEnvironment m_varDeclarations;
655
656 public:
657     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
658     {
659         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedProgramCodeBlockType, StructureFlags), info());
660     }
661
662     DECLARE_INFO;
663 };
664
665 class UnlinkedEvalCodeBlock final : public UnlinkedGlobalCodeBlock {
666 private:
667     friend class CodeCache;
668
669     static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo& info)
670     {
671         UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell<UnlinkedEvalCodeBlock>(vm->heap)) UnlinkedEvalCodeBlock(vm, vm->unlinkedEvalCodeBlockStructure.get(), info);
672         instance->finishCreation(*vm);
673         return instance;
674     }
675
676 public:
677     typedef UnlinkedGlobalCodeBlock Base;
678     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
679
680     static void destroy(JSCell*);
681
682     const Identifier& variable(unsigned index) { return m_variables[index]; }
683     unsigned numVariables() { return m_variables.size(); }
684     void adoptVariables(Vector<Identifier, 0, UnsafeVectorOverflow>& variables)
685     {
686         ASSERT(m_variables.isEmpty());
687         m_variables.swap(variables);
688     }
689
690 private:
691     UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
692         : Base(vm, structure, EvalCode, info)
693     {
694     }
695
696     Vector<Identifier, 0, UnsafeVectorOverflow> m_variables;
697
698 public:
699     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
700     {
701         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedEvalCodeBlockType, StructureFlags), info());
702     }
703
704     DECLARE_INFO;
705 };
706
707 class UnlinkedFunctionCodeBlock final : public UnlinkedCodeBlock {
708 public:
709     typedef UnlinkedCodeBlock Base;
710     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
711
712     static UnlinkedFunctionCodeBlock* create(VM* vm, CodeType codeType, const ExecutableInfo& info)
713     {
714         UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell<UnlinkedFunctionCodeBlock>(vm->heap)) UnlinkedFunctionCodeBlock(vm, vm->unlinkedFunctionCodeBlockStructure.get(), codeType, info);
715         instance->finishCreation(*vm);
716         return instance;
717     }
718
719     static void destroy(JSCell*);
720
721 private:
722     UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
723         : Base(vm, structure, codeType, info)
724     {
725     }
726     
727 public:
728     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
729     {
730         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionCodeBlockType, StructureFlags), info());
731     }
732
733     DECLARE_INFO;
734 };
735
736 }
737
738 #endif // UnlinkedCodeBlock_h