bec6e08611dc5f094f79ab85c1335a911b9f911b
[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 "GeneratorThisMode.h"
35 #include "HandlerInfo.h"
36 #include "Identifier.h"
37 #include "JSCell.h"
38 #include "JSString.h"
39 #include "ParserModes.h"
40 #include "RegExp.h"
41 #include "SpecialPointer.h"
42 #include "UnlinkedFunctionExecutable.h"
43 #include "VariableEnvironment.h"
44 #include "VirtualRegister.h"
45 #include <wtf/FastBitVector.h>
46 #include <wtf/RefCountedArray.h>
47 #include <wtf/Vector.h>
48
49 namespace JSC {
50
51 class Debugger;
52 class FunctionMetadataNode;
53 class FunctionExecutable;
54 class JSScope;
55 class ParserError;
56 class ScriptExecutable;
57 class SourceCode;
58 class SourceProvider;
59 class UnlinkedCodeBlock;
60 class UnlinkedFunctionCodeBlock;
61 class UnlinkedFunctionExecutable;
62 class UnlinkedInstructionStream;
63 struct ExecutableInfo;
64
65 typedef unsigned UnlinkedValueProfile;
66 typedef unsigned UnlinkedArrayProfile;
67 typedef unsigned UnlinkedArrayAllocationProfile;
68 typedef unsigned UnlinkedObjectAllocationProfile;
69 typedef unsigned UnlinkedLLIntCallLinkInfo;
70
71 struct UnlinkedStringJumpTable {
72     typedef HashMap<RefPtr<StringImpl>, int32_t> 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;
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     bool isConstructor() const { return m_isConstructor; }
119     bool isStrictMode() const { return m_isStrictMode; }
120     bool usesEval() const { return m_usesEval; }
121     SourceParseMode parseMode() const { return m_parseMode; }
122     bool isArrowFunction() const { return m_parseMode == SourceParseMode::ArrowFunctionMode; }
123     bool isDerivedConstructorContext() const { return m_isDerivedConstructorContext; }
124     bool isArrowFunctionContext() const { return m_isArrowFunctionContext; }
125
126     bool needsFullScopeChain() const { return m_needsFullScopeChain; }
127
128     void addExpressionInfo(unsigned instructionOffset, int divot,
129         int startOffset, int endOffset, unsigned line, unsigned column);
130
131     void addTypeProfilerExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot);
132
133     bool hasExpressionInfo() { return m_expressionInfo.size(); }
134
135     // Special registers
136     void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; }
137     void setScopeRegister(VirtualRegister scopeRegister) { m_scopeRegister = scopeRegister; }
138     void setActivationRegister(VirtualRegister activationRegister) { m_lexicalEnvironmentRegister = activationRegister; }
139
140     bool usesGlobalObject() const { return m_globalObjectRegister.isValid(); }
141     void setGlobalObjectRegister(VirtualRegister globalObjectRegister) { m_globalObjectRegister = globalObjectRegister; }
142     VirtualRegister globalObjectRegister() const { return m_globalObjectRegister; }
143
144     // Parameter information
145     void setNumParameters(int newValue) { m_numParameters = newValue; }
146     void addParameter() { m_numParameters++; }
147     unsigned numParameters() const { return m_numParameters; }
148
149     unsigned addRegExp(RegExp* r)
150     {
151         createRareDataIfNecessary();
152         unsigned size = m_rareData->m_regexps.size();
153         m_rareData->m_regexps.append(WriteBarrier<RegExp>(*m_vm, this, r));
154         return size;
155     }
156     unsigned numberOfRegExps() const
157     {
158         if (!m_rareData)
159             return 0;
160         return m_rareData->m_regexps.size();
161     }
162     RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
163
164     // Constant Pools
165
166     size_t numberOfIdentifiers() const { return m_identifiers.size(); }
167     void addIdentifier(const Identifier& i) { return m_identifiers.append(i); }
168     const Identifier& identifier(int index) const { return m_identifiers[index]; }
169     const Vector<Identifier>& identifiers() const { return m_identifiers; }
170
171     unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other)
172     {
173         unsigned result = m_constantRegisters.size();
174         m_constantRegisters.append(WriteBarrier<Unknown>());
175         m_constantRegisters.last().set(*m_vm, this, v);
176         m_constantsSourceCodeRepresentation.append(sourceCodeRepresentation);
177         return result;
178     }
179     unsigned addConstant(LinkTimeConstant type)
180     {
181         unsigned result = m_constantRegisters.size();
182         ASSERT(result);
183         unsigned index = static_cast<unsigned>(type);
184         ASSERT(index < LinkTimeConstantCount);
185         m_linkTimeConstants[index] = result;
186         m_constantRegisters.append(WriteBarrier<Unknown>());
187         m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
188         return result;
189     }
190     unsigned registerIndexForLinkTimeConstant(LinkTimeConstant type)
191     {
192         unsigned index = static_cast<unsigned>(type);
193         ASSERT(index < LinkTimeConstantCount);
194         return m_linkTimeConstants[index];
195     }
196     const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; }
197     const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
198     ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
199     const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation() { return m_constantsSourceCodeRepresentation; }
200
201     // Jumps
202     size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
203     void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
204     unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
205     unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
206
207     bool isBuiltinFunction() const { return m_isBuiltinFunction; }
208
209     ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
210     GeneratorThisMode generatorThisMode() const { return static_cast<GeneratorThisMode>(m_generatorThisMode); }
211     SuperBinding superBinding() const { return static_cast<SuperBinding>(m_superBinding); }
212
213     void shrinkToFit()
214     {
215         m_jumpTargets.shrinkToFit();
216         m_identifiers.shrinkToFit();
217         m_constantRegisters.shrinkToFit();
218         m_constantsSourceCodeRepresentation.shrinkToFit();
219         m_functionDecls.shrinkToFit();
220         m_functionExprs.shrinkToFit();
221         m_propertyAccessInstructions.shrinkToFit();
222         m_expressionInfo.shrinkToFit();
223
224 #if ENABLE(BYTECODE_COMMENTS)
225         m_bytecodeComments.shrinkToFit();
226 #endif
227         if (m_rareData) {
228             m_rareData->m_exceptionHandlers.shrinkToFit();
229             m_rareData->m_regexps.shrinkToFit();
230             m_rareData->m_constantBuffers.shrinkToFit();
231             m_rareData->m_switchJumpTables.shrinkToFit();
232             m_rareData->m_stringSwitchJumpTables.shrinkToFit();
233             m_rareData->m_expressionInfoFatPositions.shrinkToFit();
234         }
235     }
236
237     void setInstructions(std::unique_ptr<UnlinkedInstructionStream>);
238     const UnlinkedInstructionStream& instructions() const;
239
240     int m_numVars;
241     int m_numCapturedVars;
242     int m_numCalleeLocals;
243
244     // Jump Tables
245
246     size_t numberOfSwitchJumpTables() const { return m_rareData ? m_rareData->m_switchJumpTables.size() : 0; }
247     UnlinkedSimpleJumpTable& addSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_switchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_switchJumpTables.last(); }
248     UnlinkedSimpleJumpTable& switchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_switchJumpTables[tableIndex]; }
249
250     size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }
251     UnlinkedStringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(UnlinkedStringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
252     UnlinkedStringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
253
254     unsigned addFunctionDecl(UnlinkedFunctionExecutable* n)
255     {
256         unsigned size = m_functionDecls.size();
257         m_functionDecls.append(WriteBarrier<UnlinkedFunctionExecutable>());
258         m_functionDecls.last().set(*m_vm, this, n);
259         return size;
260     }
261     UnlinkedFunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
262     size_t numberOfFunctionDecls() { return m_functionDecls.size(); }
263     unsigned addFunctionExpr(UnlinkedFunctionExecutable* n)
264     {
265         unsigned size = m_functionExprs.size();
266         m_functionExprs.append(WriteBarrier<UnlinkedFunctionExecutable>());
267         m_functionExprs.last().set(*m_vm, this, n);
268         return size;
269     }
270     UnlinkedFunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
271     size_t numberOfFunctionExprs() { return m_functionExprs.size(); }
272
273     // Exception handling support
274     size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
275     void addExceptionHandler(const UnlinkedHandlerInfo& handler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(handler); }
276     UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
277
278     VM* vm() const { return m_vm; }
279
280     UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; }
281     unsigned numberOfArrayProfiles() { return m_arrayProfileCount; }
282     UnlinkedArrayAllocationProfile addArrayAllocationProfile() { return m_arrayAllocationProfileCount++; }
283     unsigned numberOfArrayAllocationProfiles() { return m_arrayAllocationProfileCount; }
284     UnlinkedObjectAllocationProfile addObjectAllocationProfile() { return m_objectAllocationProfileCount++; }
285     unsigned numberOfObjectAllocationProfiles() { return m_objectAllocationProfileCount; }
286     UnlinkedValueProfile addValueProfile() { return m_valueProfileCount++; }
287     unsigned numberOfValueProfiles() { return m_valueProfileCount; }
288
289     UnlinkedLLIntCallLinkInfo addLLIntCallLinkInfo() { return m_llintCallLinkInfoCount++; }
290     unsigned numberOfLLintCallLinkInfos() { return m_llintCallLinkInfoCount; }
291
292     CodeType codeType() const { return m_codeType; }
293
294     VirtualRegister thisRegister() const { return m_thisRegister; }
295     VirtualRegister scopeRegister() const { return m_scopeRegister; }
296     VirtualRegister activationRegister() const { return m_lexicalEnvironmentRegister; }
297     bool hasActivationRegister() const { return m_lexicalEnvironmentRegister.isValid(); }
298
299     void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
300     {
301         m_propertyAccessInstructions.append(propertyAccessInstruction);
302     }
303
304     size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); }
305     const Vector<unsigned>& propertyAccessInstructions() const { return m_propertyAccessInstructions; }
306
307     typedef Vector<JSValue> ConstantBuffer;
308
309     size_t constantBufferCount() { ASSERT(m_rareData); return m_rareData->m_constantBuffers.size(); }
310     unsigned addConstantBuffer(unsigned length)
311     {
312         createRareDataIfNecessary();
313         unsigned size = m_rareData->m_constantBuffers.size();
314         m_rareData->m_constantBuffers.append(Vector<JSValue>(length));
315         return size;
316     }
317
318     const ConstantBuffer& constantBuffer(unsigned index) const
319     {
320         ASSERT(m_rareData);
321         return m_rareData->m_constantBuffers[index];
322     }
323
324     ConstantBuffer& constantBuffer(unsigned index)
325     {
326         ASSERT(m_rareData);
327         return m_rareData->m_constantBuffers[index];
328     }
329
330     bool hasRareData() const { return m_rareData.get(); }
331
332     int lineNumberForBytecodeOffset(unsigned bytecodeOffset);
333
334     void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,
335         int& startOffset, int& endOffset, unsigned& line, unsigned& column);
336
337     bool typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot);
338
339     void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount, unsigned endColumn)
340     {
341         m_features = features;
342         m_hasCapturedVariables = hasCapturedVariables;
343         m_firstLine = firstLine;
344         m_lineCount = lineCount;
345         // For the UnlinkedCodeBlock, startColumn is always 0.
346         m_endColumn = endColumn;
347     }
348
349     CodeFeatures codeFeatures() const { return m_features; }
350     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
351     unsigned firstLine() const { return m_firstLine; }
352     unsigned lineCount() const { return m_lineCount; }
353     ALWAYS_INLINE unsigned startColumn() const { return 0; }
354     unsigned endColumn() const { return m_endColumn; }
355
356     void addOpProfileControlFlowBytecodeOffset(size_t offset) { m_opProfileControlFlowBytecodeOffsets.append(offset); }
357     const Vector<size_t>& opProfileControlFlowBytecodeOffsets() const { return m_opProfileControlFlowBytecodeOffsets; }
358
359     void dumpExpressionRangeInfo(); // For debugging purpose only.
360
361 protected:
362     UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&);
363     ~UnlinkedCodeBlock();
364
365     void finishCreation(VM& vm)
366     {
367         Base::finishCreation(vm);
368     }
369
370 private:
371
372     void createRareDataIfNecessary()
373     {
374         if (!m_rareData)
375             m_rareData = std::make_unique<RareData>();
376     }
377
378     void getLineAndColumn(ExpressionRangeInfo&, unsigned& line, unsigned& column);
379
380     std::unique_ptr<UnlinkedInstructionStream> m_unlinkedInstructions;
381
382     int m_numParameters;
383     VM* m_vm;
384
385     VirtualRegister m_thisRegister;
386     VirtualRegister m_scopeRegister;
387     VirtualRegister m_lexicalEnvironmentRegister;
388     VirtualRegister m_globalObjectRegister;
389
390     unsigned m_needsFullScopeChain : 1;
391     unsigned m_usesEval : 1;
392     unsigned m_isStrictMode : 1;
393     unsigned m_isConstructor : 1;
394     unsigned m_hasCapturedVariables : 1;
395     unsigned m_isBuiltinFunction : 1;
396     unsigned m_constructorKind : 2;
397     unsigned m_generatorThisMode : 1;
398     unsigned m_superBinding : 1;
399     unsigned m_isDerivedConstructorContext : 1;
400     unsigned m_isArrowFunctionContext : 1;
401
402     unsigned m_firstLine;
403     unsigned m_lineCount;
404     unsigned m_endColumn;
405
406     SourceParseMode m_parseMode;
407     CodeFeatures m_features;
408     CodeType m_codeType;
409
410     Vector<unsigned> m_jumpTargets;
411
412     // Constant Pools
413     Vector<Identifier> m_identifiers;
414     Vector<WriteBarrier<Unknown>> m_constantRegisters;
415     Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation;
416     std::array<unsigned, LinkTimeConstantCount> m_linkTimeConstants;
417     typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector;
418     FunctionExpressionVector m_functionDecls;
419     FunctionExpressionVector m_functionExprs;
420
421     Vector<unsigned> m_propertyAccessInstructions;
422
423 #if ENABLE(BYTECODE_COMMENTS)
424     Vector<Comment>  m_bytecodeComments;
425     size_t m_bytecodeCommentIterator;
426 #endif
427
428     unsigned m_arrayProfileCount;
429     unsigned m_arrayAllocationProfileCount;
430     unsigned m_objectAllocationProfileCount;
431     unsigned m_valueProfileCount;
432     unsigned m_llintCallLinkInfoCount;
433
434 public:
435     struct RareData {
436         WTF_MAKE_FAST_ALLOCATED;
437     public:
438         Vector<UnlinkedHandlerInfo> m_exceptionHandlers;
439
440         // Rare Constants
441         Vector<WriteBarrier<RegExp>> m_regexps;
442
443         // Buffers used for large array literals
444         Vector<ConstantBuffer> m_constantBuffers;
445
446         // Jump Tables
447         Vector<UnlinkedSimpleJumpTable> m_switchJumpTables;
448         Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables;
449
450         Vector<ExpressionRangeInfo::FatPosition> m_expressionInfoFatPositions;
451     };
452
453 private:
454     std::unique_ptr<RareData> m_rareData;
455     Vector<ExpressionRangeInfo> m_expressionInfo;
456     struct TypeProfilerExpressionRange {
457         unsigned m_startDivot;
458         unsigned m_endDivot;
459     };
460     HashMap<unsigned, TypeProfilerExpressionRange> m_typeProfilerInfoMap;
461     Vector<size_t> m_opProfileControlFlowBytecodeOffsets;
462
463 protected:
464     static void visitChildren(JSCell*, SlotVisitor&);
465
466 public:
467     DECLARE_INFO;
468 };
469
470 class UnlinkedGlobalCodeBlock : public UnlinkedCodeBlock {
471 public:
472     typedef UnlinkedCodeBlock Base;
473
474 protected:
475     UnlinkedGlobalCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
476         : Base(vm, structure, codeType, info)
477     {
478     }
479
480     DECLARE_INFO;
481 };
482
483 class UnlinkedProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
484 private:
485     friend class CodeCache;
486     static UnlinkedProgramCodeBlock* create(VM* vm, const ExecutableInfo& info)
487     {
488         UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedProgramCodeBlock>(vm->heap)) UnlinkedProgramCodeBlock(vm, vm->unlinkedProgramCodeBlockStructure.get(), info);
489         instance->finishCreation(*vm);
490         return instance;
491     }
492
493 public:
494     typedef UnlinkedGlobalCodeBlock Base;
495     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
496
497     static void destroy(JSCell*);
498
499     void setVariableDeclarations(const VariableEnvironment& environment) { m_varDeclarations = environment; }
500     const VariableEnvironment& variableDeclarations() const { return m_varDeclarations; }
501
502     void setLexicalDeclarations(const VariableEnvironment& environment) { m_lexicalDeclarations = environment; }
503     const VariableEnvironment& lexicalDeclarations() const { return m_lexicalDeclarations; }
504
505     static void visitChildren(JSCell*, SlotVisitor&);
506
507 private:
508     UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
509         : Base(vm, structure, GlobalCode, info)
510     {
511     }
512
513     VariableEnvironment m_varDeclarations;
514     VariableEnvironment m_lexicalDeclarations;
515
516 public:
517     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
518     {
519         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedProgramCodeBlockType, StructureFlags), info());
520     }
521
522     DECLARE_INFO;
523 };
524
525 class UnlinkedModuleProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
526 private:
527     friend class CodeCache;
528     static UnlinkedModuleProgramCodeBlock* create(VM* vm, const ExecutableInfo& info)
529     {
530         UnlinkedModuleProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedModuleProgramCodeBlock>(vm->heap)) UnlinkedModuleProgramCodeBlock(vm, vm->unlinkedModuleProgramCodeBlockStructure.get(), info);
531         instance->finishCreation(*vm);
532         return instance;
533     }
534
535 public:
536     typedef UnlinkedGlobalCodeBlock Base;
537     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
538
539     static void destroy(JSCell*);
540
541     static void visitChildren(JSCell*, SlotVisitor&);
542
543     // This offset represents the constant register offset to the stored symbol table that represents the layout of the
544     // module environment. This symbol table is created by the byte code generator since the module environment includes
545     // the top-most lexical captured variables inside the module code. This means that, once the module environment is
546     // allocated and instantiated from this symbol table, it is titely coupled with the specific unlinked module program
547     // code block and the stored symbol table. So before executing the module code, we should not clear the unlinked module
548     // program code block in the module executable. This requirement is met because the garbage collector only clears
549     // unlinked code in (1) unmarked executables and (2) function executables.
550     //
551     // Since the function code may be executed repeatedly and the environment of each function execution is different,
552     // the function code need to allocate and instantiate the environment in the prologue of the function code. On the
553     // other hand, the module code is executed only once. So we can instantiate the module environment outside the module
554     // code. At that time, we construct the module environment by using the symbol table that is held by the module executable.
555     // The symbol table held by the executable is the cloned one from one in the unlinked code block. Instantiating the module
556     // environment before executing and linking the module code is required to link the imported bindings between the modules.
557     //
558     // The unlinked module program code block only holds the pre-cloned symbol table in its constant register pool. It does
559     // not hold the instantiated module environment. So while the module environment requires the specific unlinked module
560     // program code block, the unlinked module code block can be used for the module environment instantiated from this
561     // unlinked code block. There is 1:N relation between the unlinked module code block and the module environments. So the
562     // unlinked module program code block can be cached.
563     //
564     // On the other hand, the linked code block for the module environment includes the resolved references to the imported
565     // bindings. The imported binding references the other module environment, so the linked code block is titly coupled
566     // with the specific set of the module environments. Thus, the linked code block should not be cached.
567     int moduleEnvironmentSymbolTableConstantRegisterOffset() { return m_moduleEnvironmentSymbolTableConstantRegisterOffset; }
568     void setModuleEnvironmentSymbolTableConstantRegisterOffset(int offset)
569     {
570         m_moduleEnvironmentSymbolTableConstantRegisterOffset = offset;
571     }
572
573 private:
574     UnlinkedModuleProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
575         : Base(vm, structure, ModuleCode, info)
576     {
577     }
578
579     int m_moduleEnvironmentSymbolTableConstantRegisterOffset { 0 };
580
581 public:
582     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
583     {
584         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedModuleProgramCodeBlockType, StructureFlags), info());
585     }
586
587     DECLARE_INFO;
588 };
589
590 class UnlinkedEvalCodeBlock final : public UnlinkedGlobalCodeBlock {
591 private:
592     friend class CodeCache;
593
594     static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo& info)
595     {
596         UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell<UnlinkedEvalCodeBlock>(vm->heap)) UnlinkedEvalCodeBlock(vm, vm->unlinkedEvalCodeBlockStructure.get(), info);
597         instance->finishCreation(*vm);
598         return instance;
599     }
600
601 public:
602     typedef UnlinkedGlobalCodeBlock Base;
603     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
604
605     static void destroy(JSCell*);
606
607     const Identifier& variable(unsigned index) { return m_variables[index]; }
608     unsigned numVariables() { return m_variables.size(); }
609     void adoptVariables(Vector<Identifier, 0, UnsafeVectorOverflow>& variables)
610     {
611         ASSERT(m_variables.isEmpty());
612         m_variables.swap(variables);
613     }
614
615 private:
616     UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
617         : Base(vm, structure, EvalCode, info)
618     {
619     }
620
621     Vector<Identifier, 0, UnsafeVectorOverflow> m_variables;
622
623 public:
624     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
625     {
626         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedEvalCodeBlockType, StructureFlags), info());
627     }
628
629     DECLARE_INFO;
630 };
631
632 class UnlinkedFunctionCodeBlock final : public UnlinkedCodeBlock {
633 public:
634     typedef UnlinkedCodeBlock Base;
635     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
636
637     static UnlinkedFunctionCodeBlock* create(VM* vm, CodeType codeType, const ExecutableInfo& info)
638     {
639         UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell<UnlinkedFunctionCodeBlock>(vm->heap)) UnlinkedFunctionCodeBlock(vm, vm->unlinkedFunctionCodeBlockStructure.get(), codeType, info);
640         instance->finishCreation(*vm);
641         return instance;
642     }
643
644     static void destroy(JSCell*);
645
646 private:
647     UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
648         : Base(vm, structure, codeType, info)
649     {
650     }
651     
652 public:
653     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
654     {
655         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionCodeBlockType, StructureFlags), info());
656     }
657
658     DECLARE_INFO;
659 };
660
661 }
662
663 #endif // UnlinkedCodeBlock_h