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