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
48namespace JSC {
49
50class Debugger;
51class FunctionMetadataNode;
52class FunctionExecutable;
53class JSScope;
54class ParserError;
55class ScriptExecutable;
56class SourceCode;
57class SourceProvider;
58class UnlinkedCodeBlock;
59class UnlinkedFunctionCodeBlock;
60class UnlinkedFunctionExecutable;
61class UnlinkedInstructionStream;
62struct ExecutableInfo;
63
64typedef unsigned UnlinkedValueProfile;
65typedef unsigned UnlinkedArrayProfile;
66typedef unsigned UnlinkedArrayAllocationProfile;
67typedef unsigned UnlinkedObjectAllocationProfile;
68typedef unsigned UnlinkedLLIntCallLinkInfo;
69
70struct 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
85struct 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
97struct 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
108class UnlinkedCodeBlock : public JSCell {
109public:
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 DerivedContextType derivedContextType() const { return static_cast<DerivedContextType>(m_derivedContextType); }
123 bool isArrowFunctionContext() const { return m_isArrowFunctionContext; }
124 bool isClassContext() const { return m_isClassContext; }
125
126 void addExpressionInfo(unsigned instructionOffset, int divot,
127 int startOffset, int endOffset, unsigned line, unsigned column);
128
129 void addTypeProfilerExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot);
130
131 bool hasExpressionInfo() { return m_expressionInfo.size(); }
132 const Vector<ExpressionRangeInfo>& expressionInfo() { return m_expressionInfo; }
133
134 // Special registers
135 void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; }
136 void setScopeRegister(VirtualRegister scopeRegister) { m_scopeRegister = scopeRegister; }
137
138 bool usesGlobalObject() const { return m_globalObjectRegister.isValid(); }
139 void setGlobalObjectRegister(VirtualRegister globalObjectRegister) { m_globalObjectRegister = globalObjectRegister; }
140 VirtualRegister globalObjectRegister() const { return m_globalObjectRegister; }
141
142 // Parameter information
143 void setNumParameters(int newValue) { m_numParameters = newValue; }
144 void addParameter() { m_numParameters++; }
145 unsigned numParameters() const { return m_numParameters; }
146
147 unsigned addRegExp(RegExp* r)
148 {
149 createRareDataIfNecessary();
150 unsigned size = m_rareData->m_regexps.size();
151 m_rareData->m_regexps.append(WriteBarrier<RegExp>(*vm(), this, r));
152 return size;
153 }
154 unsigned numberOfRegExps() const
155 {
156 if (!m_rareData)
157 return 0;
158 return m_rareData->m_regexps.size();
159 }
160 RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
161
162 // Constant Pools
163
164 size_t numberOfIdentifiers() const { return m_identifiers.size(); }
165 void addIdentifier(const Identifier& i) { return m_identifiers.append(i); }
166 const Identifier& identifier(int index) const { return m_identifiers[index]; }
167 const Vector<Identifier>& identifiers() const { return m_identifiers; }
168
169 unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other)
170 {
171 unsigned result = m_constantRegisters.size();
172 m_constantRegisters.append(WriteBarrier<Unknown>());
173 m_constantRegisters.last().set(*vm(), this, v);
174 m_constantsSourceCodeRepresentation.append(sourceCodeRepresentation);
175 return result;
176 }
177 unsigned addConstant(LinkTimeConstant type)
178 {
179 unsigned result = m_constantRegisters.size();
180 ASSERT(result);
181 unsigned index = static_cast<unsigned>(type);
182 ASSERT(index < LinkTimeConstantCount);
183 m_linkTimeConstants[index] = result;
184 m_constantRegisters.append(WriteBarrier<Unknown>());
185 m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
186 return result;
187 }
188 unsigned registerIndexForLinkTimeConstant(LinkTimeConstant type)
189 {
190 unsigned index = static_cast<unsigned>(type);
191 ASSERT(index < LinkTimeConstantCount);
192 return m_linkTimeConstants[index];
193 }
194 const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; }
195 const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
196 ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
197 const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation() { return m_constantsSourceCodeRepresentation; }
198
199 // Jumps
200 size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
201 void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
202 unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
203 unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
204
205 bool isBuiltinFunction() const { return m_isBuiltinFunction; }
206
207 ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
208 SuperBinding superBinding() const { return static_cast<SuperBinding>(m_superBinding); }
209
210 void shrinkToFit()
211 {
212 m_jumpTargets.shrinkToFit();
213 m_identifiers.shrinkToFit();
214 m_constantRegisters.shrinkToFit();
215 m_constantsSourceCodeRepresentation.shrinkToFit();
216 m_functionDecls.shrinkToFit();
217 m_functionExprs.shrinkToFit();
218 m_propertyAccessInstructions.shrinkToFit();
219 m_expressionInfo.shrinkToFit();
220
221 if (m_rareData) {
222 m_rareData->m_exceptionHandlers.shrinkToFit();
223 m_rareData->m_regexps.shrinkToFit();
224 m_rareData->m_constantBuffers.shrinkToFit();
225 m_rareData->m_switchJumpTables.shrinkToFit();
226 m_rareData->m_stringSwitchJumpTables.shrinkToFit();
227 m_rareData->m_expressionInfoFatPositions.shrinkToFit();
228 }
229 }
230
231 void setInstructions(std::unique_ptr<UnlinkedInstructionStream>);
232 const UnlinkedInstructionStream& instructions() const;
233
234 int m_numVars;
235 int m_numCapturedVars;
236 int m_numCalleeLocals;
237
238 // Jump Tables
239
240 size_t numberOfSwitchJumpTables() const { return m_rareData ? m_rareData->m_switchJumpTables.size() : 0; }
241 UnlinkedSimpleJumpTable& addSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_switchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_switchJumpTables.last(); }
242 UnlinkedSimpleJumpTable& switchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_switchJumpTables[tableIndex]; }
243
244 size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }
245 UnlinkedStringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(UnlinkedStringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
246 UnlinkedStringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
247
248 unsigned addFunctionDecl(UnlinkedFunctionExecutable* n)
249 {
250 unsigned size = m_functionDecls.size();
251 m_functionDecls.append(WriteBarrier<UnlinkedFunctionExecutable>());
252 m_functionDecls.last().set(*vm(), this, n);
253 return size;
254 }
255 UnlinkedFunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
256 size_t numberOfFunctionDecls() { return m_functionDecls.size(); }
257 unsigned addFunctionExpr(UnlinkedFunctionExecutable* n)
258 {
259 unsigned size = m_functionExprs.size();
260 m_functionExprs.append(WriteBarrier<UnlinkedFunctionExecutable>());
261 m_functionExprs.last().set(*vm(), this, n);
262 return size;
263 }
264 UnlinkedFunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
265 size_t numberOfFunctionExprs() { return m_functionExprs.size(); }
266
267 // Exception handling support
268 size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
269 void addExceptionHandler(const UnlinkedHandlerInfo& handler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(handler); }
270 UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
271
272 VM* vm() const;
273
274 UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; }
275 unsigned numberOfArrayProfiles() { return m_arrayProfileCount; }
276 UnlinkedArrayAllocationProfile addArrayAllocationProfile() { return m_arrayAllocationProfileCount++; }
277 unsigned numberOfArrayAllocationProfiles() { return m_arrayAllocationProfileCount; }
278 UnlinkedObjectAllocationProfile addObjectAllocationProfile() { return m_objectAllocationProfileCount++; }
279 unsigned numberOfObjectAllocationProfiles() { return m_objectAllocationProfileCount; }
280 UnlinkedValueProfile addValueProfile() { return m_valueProfileCount++; }
281 unsigned numberOfValueProfiles() { return m_valueProfileCount; }
282
283 UnlinkedLLIntCallLinkInfo addLLIntCallLinkInfo() { return m_llintCallLinkInfoCount++; }
284 unsigned numberOfLLintCallLinkInfos() { return m_llintCallLinkInfoCount; }
285
286 CodeType codeType() const { return m_codeType; }
287
288 VirtualRegister thisRegister() const { return m_thisRegister; }
289 VirtualRegister scopeRegister() const { return m_scopeRegister; }
290
291 void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
292 {
293 m_propertyAccessInstructions.append(propertyAccessInstruction);
294 }
295
296 size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); }
297 const Vector<unsigned>& propertyAccessInstructions() const { return m_propertyAccessInstructions; }
298
299 typedef Vector<JSValue> ConstantBuffer;
300
301 size_t constantBufferCount() { ASSERT(m_rareData); return m_rareData->m_constantBuffers.size(); }
302 unsigned addConstantBuffer(unsigned length)
303 {
304 createRareDataIfNecessary();
305 unsigned size = m_rareData->m_constantBuffers.size();
306 m_rareData->m_constantBuffers.append(Vector<JSValue>(length));
307 return size;
308 }
309
310 const ConstantBuffer& constantBuffer(unsigned index) const
311 {
312 ASSERT(m_rareData);
313 return m_rareData->m_constantBuffers[index];
314 }
315
316 ConstantBuffer& constantBuffer(unsigned index)
317 {
318 ASSERT(m_rareData);
319 return m_rareData->m_constantBuffers[index];
320 }
321
322 bool hasRareData() const { return m_rareData.get(); }
323
324 int lineNumberForBytecodeOffset(unsigned bytecodeOffset);
325
326 void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,
327 int& startOffset, int& endOffset, unsigned& line, unsigned& column);
328
329 bool typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot);
330
331 void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount, unsigned endColumn)
332 {
333 m_features = features;
334 m_hasCapturedVariables = hasCapturedVariables;
335 m_firstLine = firstLine;
336 m_lineCount = lineCount;
337 // For the UnlinkedCodeBlock, startColumn is always 0.
338 m_endColumn = endColumn;
339 }
340
341 CodeFeatures codeFeatures() const { return m_features; }
342 bool hasCapturedVariables() const { return m_hasCapturedVariables; }
343 unsigned firstLine() const { return m_firstLine; }
344 unsigned lineCount() const { return m_lineCount; }
345 ALWAYS_INLINE unsigned startColumn() const { return 0; }
346 unsigned endColumn() const { return m_endColumn; }
347
348 void addOpProfileControlFlowBytecodeOffset(size_t offset)
349 {
350 createRareDataIfNecessary();
351 m_rareData->m_opProfileControlFlowBytecodeOffsets.append(offset);
352 }
353 const Vector<size_t>& opProfileControlFlowBytecodeOffsets() const
354 {
355 ASSERT(m_rareData);
356 return m_rareData->m_opProfileControlFlowBytecodeOffsets;
357 }
358 bool hasOpProfileControlFlowBytecodeOffsets() const
359 {
360 return m_rareData && !m_rareData->m_opProfileControlFlowBytecodeOffsets.isEmpty();
361 }
362
363 void dumpExpressionRangeInfo(); // For debugging purpose only.
364
365protected:
366 UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&);
367 ~UnlinkedCodeBlock();
368
369 void finishCreation(VM& vm)
370 {
371 Base::finishCreation(vm);
372 }
373
374private:
375
376 void createRareDataIfNecessary()
377 {
378 if (!m_rareData)
379 m_rareData = std::make_unique<RareData>();
380 }
381
382 void getLineAndColumn(ExpressionRangeInfo&, unsigned& line, unsigned& column);
383
384 int m_numParameters;
385
386 std::unique_ptr<UnlinkedInstructionStream> m_unlinkedInstructions;
387
388 VirtualRegister m_thisRegister;
389 VirtualRegister m_scopeRegister;
390 VirtualRegister m_globalObjectRegister;
391
392 unsigned m_usesEval : 1;
393 unsigned m_isStrictMode : 1;
394 unsigned m_isConstructor : 1;
395 unsigned m_hasCapturedVariables : 1;
396 unsigned m_isBuiltinFunction : 1;
397 unsigned m_constructorKind : 2;
398 unsigned m_superBinding : 1;
399 unsigned m_derivedContextType : 2;
400 unsigned m_isArrowFunctionContext : 1;
401 unsigned m_isClassContext : 1;
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 Vector<unsigned> m_propertyAccessInstructions;
413
414 // Constant Pools
415 Vector<Identifier> m_identifiers;
416 Vector<WriteBarrier<Unknown>> m_constantRegisters;
417 Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation;
418 typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector;
419 FunctionExpressionVector m_functionDecls;
420 FunctionExpressionVector m_functionExprs;
421 std::array<unsigned, LinkTimeConstantCount> m_linkTimeConstants;
422
423 unsigned m_arrayProfileCount;
424 unsigned m_arrayAllocationProfileCount;
425 unsigned m_objectAllocationProfileCount;
426 unsigned m_valueProfileCount;
427 unsigned m_llintCallLinkInfoCount;
428
429public:
430 struct RareData {
431 WTF_MAKE_FAST_ALLOCATED;
432 public:
433 Vector<UnlinkedHandlerInfo> m_exceptionHandlers;
434
435 // Rare Constants
436 Vector<WriteBarrier<RegExp>> m_regexps;
437
438 // Buffers used for large array literals
439 Vector<ConstantBuffer> m_constantBuffers;
440
441 // Jump Tables
442 Vector<UnlinkedSimpleJumpTable> m_switchJumpTables;
443 Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables;
444
445 Vector<ExpressionRangeInfo::FatPosition> m_expressionInfoFatPositions;
446
447 struct TypeProfilerExpressionRange {
448 unsigned m_startDivot;
449 unsigned m_endDivot;
450 };
451 HashMap<unsigned, TypeProfilerExpressionRange> m_typeProfilerInfoMap;
452 Vector<size_t> m_opProfileControlFlowBytecodeOffsets;
453 };
454
455private:
456 std::unique_ptr<RareData> m_rareData;
457 Vector<ExpressionRangeInfo> m_expressionInfo;
458
459protected:
460 static void visitChildren(JSCell*, SlotVisitor&);
461 static size_t estimatedSize(JSCell*);
462
463public:
464 DECLARE_INFO;
465};
466
467class UnlinkedGlobalCodeBlock : public UnlinkedCodeBlock {
468public:
469 typedef UnlinkedCodeBlock Base;
470
471protected:
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
480class UnlinkedProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
481private:
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
490public:
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
504private:
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
513public:
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
522class UnlinkedModuleProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
523private:
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
532public:
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
570private:
571 UnlinkedModuleProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
572 : Base(vm, structure, ModuleCode, info)
573 {
574 }
575
576 int m_moduleEnvironmentSymbolTableConstantRegisterOffset { 0 };
577
578public:
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
587class UnlinkedEvalCodeBlock final : public UnlinkedGlobalCodeBlock {
588private:
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
598public:
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
612private:
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
620public:
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
629class UnlinkedFunctionCodeBlock final : public UnlinkedCodeBlock {
630public:
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
643private:
644 UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
645 : Base(vm, structure, codeType, info)
646 {
647 }
648
649public:
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
661