Unreviewed, rolling out r156474.
[WebKit-https.git] / Source / JavaScriptCore / bytecode / UnlinkedCodeBlock.h
1 /*
2  * Copyright (C) 2012, 2013 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef UnlinkedCodeBlock_h
27 #define UnlinkedCodeBlock_h
28
29 #include "BytecodeConventions.h"
30 #include "CodeSpecializationKind.h"
31 #include "CodeType.h"
32 #include "ExpressionRangeInfo.h"
33 #include "Identifier.h"
34 #include "JSCell.h"
35 #include "JSString.h"
36 #include "LineInfo.h"
37 #include "ParserModes.h"
38 #include "RegExp.h"
39 #include "SpecialPointer.h"
40 #include "SymbolTable.h"
41 #include "VirtualRegister.h"
42
43 #include <wtf/Compression.h>
44 #include <wtf/RefCountedArray.h>
45 #include <wtf/Vector.h>
46
47 namespace JSC {
48
49 class Debugger;
50 class FunctionBodyNode;
51 class FunctionExecutable;
52 class FunctionParameters;
53 class JSScope;
54 struct ParserError;
55 class ScriptExecutable;
56 class SourceCode;
57 class SourceProvider;
58 class SharedSymbolTable;
59 class UnlinkedCodeBlock;
60 class UnlinkedFunctionCodeBlock;
61
62 typedef unsigned UnlinkedValueProfile;
63 typedef unsigned UnlinkedArrayProfile;
64 typedef unsigned UnlinkedArrayAllocationProfile;
65 typedef unsigned UnlinkedObjectAllocationProfile;
66 typedef unsigned UnlinkedLLIntCallLinkInfo;
67
68 struct ExecutableInfo {
69     ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor)
70         : m_needsActivation(needsActivation)
71         , m_usesEval(usesEval)
72         , m_isStrictMode(isStrictMode)
73         , m_isConstructor(isConstructor)
74     {
75     }
76     bool m_needsActivation;
77     bool m_usesEval;
78     bool m_isStrictMode;
79     bool m_isConstructor;
80 };
81
82 class UnlinkedFunctionExecutable : public JSCell {
83 public:
84     friend class CodeCache;
85     typedef JSCell Base;
86     static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionBodyNode* node)
87     {
88         UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap)) UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node);
89         instance->finishCreation(*vm);
90         return instance;
91     }
92
93     const Identifier& name() const { return m_name; }
94     const Identifier& inferredName() const { return m_inferredName; }
95     JSString* nameValue() const { return m_nameValue.get(); }
96     SharedSymbolTable* symbolTable(CodeSpecializationKind kind)
97     {
98         return (kind == CodeForCall) ? m_symbolTableForCall.get() : m_symbolTableForConstruct.get();
99     }
100     size_t parameterCount() const;
101     bool isInStrictContext() const { return m_isInStrictContext; }
102     FunctionNameIsInScopeToggle functionNameIsInScopeToggle() const { return m_functionNameIsInScopeToggle; }
103
104     unsigned firstLineOffset() const { return m_firstLineOffset; }
105     unsigned lineCount() const { return m_lineCount; }
106     unsigned functionStartOffset() const { return m_functionStartOffset; }
107     unsigned functionStartColumn() const { return m_functionStartColumn; }
108     unsigned startOffset() const { return m_startOffset; }
109     unsigned sourceLength() { return m_sourceLength; }
110
111     String paramString() const;
112
113     UnlinkedFunctionCodeBlock* codeBlockFor(VM&, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&);
114
115     static UnlinkedFunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
116
117     FunctionExecutable* link(VM&, const SourceCode&, size_t lineOffset, size_t sourceOffset);
118
119     void clearCodeForRecompilation()
120     {
121         m_symbolTableForCall.clear();
122         m_symbolTableForConstruct.clear();
123         m_codeBlockForCall.clear();
124         m_codeBlockForConstruct.clear();
125     }
126
127     FunctionParameters* parameters() { return m_parameters.get(); }
128
129     void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
130     {
131         m_features = features;
132         m_hasCapturedVariables = hasCapturedVariables;
133         m_lineCount = lastLine - firstLine;
134     }
135
136     bool forceUsesArguments() const { return m_forceUsesArguments; }
137
138     CodeFeatures features() const { return m_features; }
139     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
140
141     static const bool needsDestruction = true;
142     static const bool hasImmortalStructure = true;
143     static void destroy(JSCell*);
144
145 private:
146     UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionBodyNode*);
147     WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
148     WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;
149
150     unsigned m_numCapturedVariables : 29;
151     bool m_forceUsesArguments : 1;
152     bool m_isInStrictContext : 1;
153     bool m_hasCapturedVariables : 1;
154
155     Identifier m_name;
156     Identifier m_inferredName;
157     WriteBarrier<JSString> m_nameValue;
158     WriteBarrier<SharedSymbolTable> m_symbolTableForCall;
159     WriteBarrier<SharedSymbolTable> m_symbolTableForConstruct;
160     RefPtr<FunctionParameters> m_parameters;
161     unsigned m_firstLineOffset;
162     unsigned m_lineCount;
163     unsigned m_functionStartOffset;
164     unsigned m_functionStartColumn;
165     unsigned m_startOffset;
166     unsigned m_sourceLength;
167
168     CodeFeatures m_features;
169
170     FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle;
171
172 protected:
173     void finishCreation(VM& vm)
174     {
175         Base::finishCreation(vm);
176         m_nameValue.set(vm, this, jsString(&vm, name().string()));
177     }
178
179     static void visitChildren(JSCell*, SlotVisitor&);
180
181 public:
182     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
183     {
184         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionExecutableType, StructureFlags), info());
185     }
186
187     static const unsigned StructureFlags = OverridesVisitChildren | JSCell::StructureFlags;
188
189     DECLARE_INFO;
190 };
191
192 struct UnlinkedStringJumpTable {
193     typedef HashMap<RefPtr<StringImpl>, int32_t> StringOffsetTable;
194     StringOffsetTable offsetTable;
195
196     inline int32_t offsetForValue(StringImpl* value, int32_t defaultOffset)
197     {
198         StringOffsetTable::const_iterator end = offsetTable.end();
199         StringOffsetTable::const_iterator loc = offsetTable.find(value);
200         if (loc == end)
201             return defaultOffset;
202         return loc->value;
203     }
204
205 };
206
207 struct UnlinkedSimpleJumpTable {
208     Vector<int32_t> branchOffsets;
209     int32_t min;
210
211     int32_t offsetForValue(int32_t value, int32_t defaultOffset);
212     void add(int32_t key, int32_t offset)
213     {
214         if (!branchOffsets[key])
215             branchOffsets[key] = offset;
216     }
217 };
218
219 struct UnlinkedHandlerInfo {
220     uint32_t start;
221     uint32_t end;
222     uint32_t target;
223     uint32_t scopeDepth;
224 };
225
226 struct UnlinkedInstruction {
227     UnlinkedInstruction() { u.operand = 0; }
228     UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
229     UnlinkedInstruction(int operand) { u.operand = operand; }
230     union {
231         OpcodeID opcode;
232         int32_t operand;
233     } u;
234 };
235
236 class UnlinkedCodeBlock : public JSCell {
237 public:
238     typedef JSCell Base;
239     static const bool needsDestruction = true;
240     static const bool hasImmortalStructure = true;
241
242     enum { CallFunction, ApplyFunction };
243
244     bool isConstructor() const { return m_isConstructor; }
245     bool isStrictMode() const { return m_isStrictMode; }
246     bool usesEval() const { return m_usesEval; }
247
248     bool needsFullScopeChain() const { return m_needsFullScopeChain; }
249     void setNeedsFullScopeChain(bool needsFullScopeChain) { m_needsFullScopeChain = needsFullScopeChain; }
250
251     void addExpressionInfo(unsigned instructionOffset, int divot,
252         int startOffset, int endOffset, unsigned line, unsigned column);
253
254     bool hasExpressionInfo() { return m_expressionInfo.size(); }
255
256     // Special registers
257     void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
258     void setActivationRegister(int activationRegister) { m_activationRegister = activationRegister; }
259
260     void setArgumentsRegister(int argumentsRegister) { m_argumentsRegister = argumentsRegister; }
261     bool usesArguments() const { return m_argumentsRegister != (int)InvalidVirtualRegister; }
262     int argumentsRegister() const { return m_argumentsRegister; }
263
264
265     bool usesGlobalObject() const { return m_globalObjectRegister != (int)InvalidVirtualRegister; }
266     void setGlobalObjectRegister(int globalObjectRegister) { m_globalObjectRegister = globalObjectRegister; }
267     int globalObjectRegister() const { return m_globalObjectRegister; }
268
269     // Parameter information
270     void setNumParameters(int newValue) { m_numParameters = newValue; }
271     void addParameter() { m_numParameters++; }
272     unsigned numParameters() const { return m_numParameters; }
273
274     unsigned addRegExp(RegExp* r)
275     {
276         createRareDataIfNecessary();
277         unsigned size = m_rareData->m_regexps.size();
278         m_rareData->m_regexps.append(WriteBarrier<RegExp>(*m_vm, this, r));
279         return size;
280     }
281     unsigned numberOfRegExps() const
282     {
283         if (!m_rareData)
284             return 0;
285         return m_rareData->m_regexps.size();
286     }
287     RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
288
289     // Constant Pools
290
291     size_t numberOfIdentifiers() const { return m_identifiers.size(); }
292     void addIdentifier(const Identifier& i) { return m_identifiers.append(i); }
293     const Identifier& identifier(int index) const { return m_identifiers[index]; }
294     const Vector<Identifier>& identifiers() const { return m_identifiers; }
295
296     size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
297     unsigned addConstant(JSValue v)
298     {
299         unsigned result = m_constantRegisters.size();
300         m_constantRegisters.append(WriteBarrier<Unknown>());
301         m_constantRegisters.last().set(*m_vm, this, v);
302         return result;
303     }
304     unsigned addOrFindConstant(JSValue);
305     const Vector<WriteBarrier<Unknown> >& constantRegisters() { return m_constantRegisters; }
306     const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
307     ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
308     ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
309
310     // Jumps
311     size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
312     void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
313     unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
314     unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
315
316     void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
317     bool isNumericCompareFunction() const { return m_isNumericCompareFunction; }
318
319     void shrinkToFit()
320     {
321         m_jumpTargets.shrinkToFit();
322         m_identifiers.shrinkToFit();
323         m_constantRegisters.shrinkToFit();
324         m_functionDecls.shrinkToFit();
325         m_functionExprs.shrinkToFit();
326         m_propertyAccessInstructions.shrinkToFit();
327         m_expressionInfo.shrinkToFit();
328
329 #if ENABLE(BYTECODE_COMMENTS)
330         m_bytecodeComments.shrinkToFit();
331 #endif
332         if (m_rareData) {
333             m_rareData->m_exceptionHandlers.shrinkToFit();
334             m_rareData->m_regexps.shrinkToFit();
335             m_rareData->m_constantBuffers.shrinkToFit();
336             m_rareData->m_switchJumpTables.shrinkToFit();
337             m_rareData->m_stringSwitchJumpTables.shrinkToFit();
338             m_rareData->m_expressionInfoFatPositions.shrinkToFit();
339         }
340     }
341
342     unsigned numberOfInstructions() const { return m_unlinkedInstructions.size(); }
343     RefCountedArray<UnlinkedInstruction>& instructions() { return m_unlinkedInstructions; }
344     const RefCountedArray<UnlinkedInstruction>& instructions() const { return m_unlinkedInstructions; }
345
346     int m_numVars;
347     int m_numCapturedVars;
348     int m_numCalleeRegisters;
349
350     // Jump Tables
351
352     size_t numberOfSwitchJumpTables() const { return m_rareData ? m_rareData->m_switchJumpTables.size() : 0; }
353     UnlinkedSimpleJumpTable& addSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_switchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_switchJumpTables.last(); }
354     UnlinkedSimpleJumpTable& switchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_switchJumpTables[tableIndex]; }
355
356     size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }
357     UnlinkedStringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(UnlinkedStringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
358     UnlinkedStringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
359
360     unsigned addFunctionDecl(UnlinkedFunctionExecutable* n)
361     {
362         unsigned size = m_functionDecls.size();
363         m_functionDecls.append(WriteBarrier<UnlinkedFunctionExecutable>());
364         m_functionDecls.last().set(*m_vm, this, n);
365         return size;
366     }
367     UnlinkedFunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
368     size_t numberOfFunctionDecls() { return m_functionDecls.size(); }
369     unsigned addFunctionExpr(UnlinkedFunctionExecutable* n)
370     {
371         unsigned size = m_functionExprs.size();
372         m_functionExprs.append(WriteBarrier<UnlinkedFunctionExecutable>());
373         m_functionExprs.last().set(*m_vm, this, n);
374         return size;
375     }
376     UnlinkedFunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
377     size_t numberOfFunctionExprs() { return m_functionExprs.size(); }
378
379     // Exception handling support
380     size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
381     void addExceptionHandler(const UnlinkedHandlerInfo& hanler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(hanler); }
382     UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
383
384     SharedSymbolTable* symbolTable() const { return m_symbolTable.get(); }
385
386     VM* vm() const { return m_vm; }
387
388     UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; }
389     unsigned numberOfArrayProfiles() { return m_arrayProfileCount; }
390     UnlinkedArrayAllocationProfile addArrayAllocationProfile() { return m_arrayAllocationProfileCount++; }
391     unsigned numberOfArrayAllocationProfiles() { return m_arrayAllocationProfileCount; }
392     UnlinkedObjectAllocationProfile addObjectAllocationProfile() { return m_objectAllocationProfileCount++; }
393     unsigned numberOfObjectAllocationProfiles() { return m_objectAllocationProfileCount; }
394     UnlinkedValueProfile addValueProfile() { return m_valueProfileCount++; }
395     unsigned numberOfValueProfiles() { return m_valueProfileCount; }
396
397     UnlinkedLLIntCallLinkInfo addLLIntCallLinkInfo() { return m_llintCallLinkInfoCount++; }
398     unsigned numberOfLLintCallLinkInfos() { return m_llintCallLinkInfoCount; }
399
400     CodeType codeType() const { return m_codeType; }
401
402     int thisRegister() const { return m_thisRegister; }
403     int activationRegister() const { return m_activationRegister; }
404
405
406     void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
407     {
408         m_propertyAccessInstructions.append(propertyAccessInstruction);
409     }
410
411     size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); }
412     const Vector<unsigned>& propertyAccessInstructions() const { return m_propertyAccessInstructions; }
413
414     typedef Vector<JSValue> ConstantBuffer;
415
416     size_t constantBufferCount() { ASSERT(m_rareData); return m_rareData->m_constantBuffers.size(); }
417     unsigned addConstantBuffer(unsigned length)
418     {
419         createRareDataIfNecessary();
420         unsigned size = m_rareData->m_constantBuffers.size();
421         m_rareData->m_constantBuffers.append(Vector<JSValue>(length));
422         return size;
423     }
424
425     const ConstantBuffer& constantBuffer(unsigned index) const
426     {
427         ASSERT(m_rareData);
428         return m_rareData->m_constantBuffers[index];
429     }
430
431     ConstantBuffer& constantBuffer(unsigned index)
432     {
433         ASSERT(m_rareData);
434         return m_rareData->m_constantBuffers[index];
435     }
436
437     bool hasRareData() const { return m_rareData; }
438
439     int lineNumberForBytecodeOffset(unsigned bytecodeOffset);
440
441     void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,
442         int& startOffset, int& endOffset, unsigned& line, unsigned& column);
443
444     void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount)
445     {
446         m_features = features;
447         m_hasCapturedVariables = hasCapturedVariables;
448         m_firstLine = firstLine;
449         m_lineCount = lineCount;
450     }
451
452     CodeFeatures codeFeatures() const { return m_features; }
453     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
454     unsigned firstLine() const { return m_firstLine; }
455     unsigned lineCount() const { return m_lineCount; }
456
457 protected:
458     UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&);
459     ~UnlinkedCodeBlock();
460
461     void finishCreation(VM& vm)
462     {
463         Base::finishCreation(vm);
464         if (codeType() == GlobalCode)
465             return;
466         m_symbolTable.set(vm, this, SharedSymbolTable::create(vm));
467     }
468
469 private:
470
471     void createRareDataIfNecessary()
472     {
473         if (!m_rareData)
474             m_rareData = adoptPtr(new RareData);
475     }
476
477     RefCountedArray<UnlinkedInstruction> m_unlinkedInstructions;
478
479     int m_numParameters;
480     VM* m_vm;
481
482     int m_thisRegister;
483     int m_argumentsRegister;
484     int m_activationRegister;
485     int m_globalObjectRegister;
486
487     bool m_needsFullScopeChain : 1;
488     bool m_usesEval : 1;
489     bool m_isNumericCompareFunction : 1;
490     bool m_isStrictMode : 1;
491     bool m_isConstructor : 1;
492     bool m_hasCapturedVariables : 1;
493     unsigned m_firstLine;
494     unsigned m_lineCount;
495
496     CodeFeatures m_features;
497     CodeType m_codeType;
498
499     Vector<unsigned> m_jumpTargets;
500
501     // Constant Pools
502     Vector<Identifier> m_identifiers;
503     Vector<WriteBarrier<Unknown> > m_constantRegisters;
504     typedef Vector<WriteBarrier<UnlinkedFunctionExecutable> > FunctionExpressionVector;
505     FunctionExpressionVector m_functionDecls;
506     FunctionExpressionVector m_functionExprs;
507
508     WriteBarrier<SharedSymbolTable> m_symbolTable;
509
510     Vector<unsigned> m_propertyAccessInstructions;
511
512 #if ENABLE(BYTECODE_COMMENTS)
513     Vector<Comment>  m_bytecodeComments;
514     size_t m_bytecodeCommentIterator;
515 #endif
516
517     unsigned m_arrayProfileCount;
518     unsigned m_arrayAllocationProfileCount;
519     unsigned m_objectAllocationProfileCount;
520     unsigned m_valueProfileCount;
521     unsigned m_llintCallLinkInfoCount;
522
523 public:
524     struct RareData {
525         WTF_MAKE_FAST_ALLOCATED;
526     public:
527         Vector<UnlinkedHandlerInfo> m_exceptionHandlers;
528
529         // Rare Constants
530         Vector<WriteBarrier<RegExp> > m_regexps;
531
532         // Buffers used for large array literals
533         Vector<ConstantBuffer> m_constantBuffers;
534
535         // Jump Tables
536         Vector<UnlinkedSimpleJumpTable> m_switchJumpTables;
537         Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables;
538
539         Vector<ExpressionRangeInfo::FatPosition> m_expressionInfoFatPositions;
540     };
541
542 private:
543     OwnPtr<RareData> m_rareData;
544     Vector<ExpressionRangeInfo> m_expressionInfo;
545
546 protected:
547
548     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
549     static void visitChildren(JSCell*, SlotVisitor&);
550
551 public:
552     DECLARE_INFO;
553 };
554
555 class UnlinkedGlobalCodeBlock : public UnlinkedCodeBlock {
556 public:
557     typedef UnlinkedCodeBlock Base;
558
559 protected:
560     UnlinkedGlobalCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
561         : Base(vm, structure, codeType, info)
562     {
563     }
564
565     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
566
567     DECLARE_INFO;
568 };
569
570 class UnlinkedProgramCodeBlock : public UnlinkedGlobalCodeBlock {
571 private:
572     friend class CodeCache;
573     static UnlinkedProgramCodeBlock* create(VM* vm, const ExecutableInfo& info)
574     {
575         UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedProgramCodeBlock>(vm->heap)) UnlinkedProgramCodeBlock(vm, vm->unlinkedProgramCodeBlockStructure.get(), info);
576         instance->finishCreation(*vm);
577         return instance;
578     }
579
580 public:
581     typedef UnlinkedGlobalCodeBlock Base;
582     static void destroy(JSCell*);
583
584     void addFunctionDeclaration(VM& vm, const Identifier& name, UnlinkedFunctionExecutable* functionExecutable)
585     {
586         m_functionDeclarations.append(std::make_pair(name, WriteBarrier<UnlinkedFunctionExecutable>(vm, this, functionExecutable)));
587     }
588
589     void addVariableDeclaration(const Identifier& name, bool isConstant)
590     {
591         m_varDeclarations.append(std::make_pair(name, isConstant));
592     }
593
594     typedef Vector<std::pair<Identifier, bool> > VariableDeclations;
595     typedef Vector<std::pair<Identifier, WriteBarrier<UnlinkedFunctionExecutable> > > FunctionDeclations;
596
597     const VariableDeclations& variableDeclarations() const { return m_varDeclarations; }
598     const FunctionDeclations& functionDeclarations() const { return m_functionDeclarations; }
599
600     static void visitChildren(JSCell*, SlotVisitor&);
601
602 private:
603     UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
604         : Base(vm, structure, GlobalCode, info)
605     {
606     }
607
608     VariableDeclations m_varDeclarations;
609     FunctionDeclations m_functionDeclarations;
610
611 public:
612     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
613     {
614         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedProgramCodeBlockType, StructureFlags), info());
615     }
616
617     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
618
619     DECLARE_INFO;
620 };
621
622 class UnlinkedEvalCodeBlock : public UnlinkedGlobalCodeBlock {
623 private:
624     friend class CodeCache;
625
626     static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo& info)
627     {
628         UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell<UnlinkedEvalCodeBlock>(vm->heap)) UnlinkedEvalCodeBlock(vm, vm->unlinkedEvalCodeBlockStructure.get(), info);
629         instance->finishCreation(*vm);
630         return instance;
631     }
632
633 public:
634     typedef UnlinkedGlobalCodeBlock Base;
635     static void destroy(JSCell*);
636
637     const Identifier& variable(unsigned index) { return m_variables[index]; }
638     unsigned numVariables() { return m_variables.size(); }
639     void adoptVariables(Vector<Identifier, 0, UnsafeVectorOverflow>& variables)
640     {
641         ASSERT(m_variables.isEmpty());
642         m_variables.swap(variables);
643     }
644
645 private:
646     UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
647         : Base(vm, structure, EvalCode, info)
648     {
649     }
650
651     Vector<Identifier, 0, UnsafeVectorOverflow> m_variables;
652
653 public:
654     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
655     {
656         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedEvalCodeBlockType, StructureFlags), info());
657     }
658
659     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
660
661     DECLARE_INFO;
662 };
663
664 class UnlinkedFunctionCodeBlock : public UnlinkedCodeBlock {
665 public:
666     static UnlinkedFunctionCodeBlock* create(VM* vm, CodeType codeType, const ExecutableInfo& info)
667     {
668         UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell<UnlinkedFunctionCodeBlock>(vm->heap)) UnlinkedFunctionCodeBlock(vm, vm->unlinkedFunctionCodeBlockStructure.get(), codeType, info);
669         instance->finishCreation(*vm);
670         return instance;
671     }
672
673     typedef UnlinkedCodeBlock Base;
674     static void destroy(JSCell*);
675
676 private:
677     UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
678         : Base(vm, structure, codeType, info)
679     {
680     }
681     
682 public:
683     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
684     {
685         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionCodeBlockType, StructureFlags), info());
686     }
687
688     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
689
690     DECLARE_INFO;
691 };
692
693 }
694
695 #endif // UnlinkedCodeBlock_h