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