3ca27ae9a700eb946002c9b0db496ec81770af3a
[WebKit-https.git] / Source / JavaScriptCore / bytecode / UnlinkedCodeBlock.h
1 /*
2  * Copyright (C) 2012 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 "LineInfo.h"
36 #include "Nodes.h"
37 #include "RegExp.h"
38 #include "SpecialPointer.h"
39 #include "Weak.h"
40
41 #include <wtf/RefCountedArray.h>
42 #include <wtf/Vector.h>
43
44 namespace JSC {
45
46 class Debugger;
47 class FunctionBodyNode;
48 class FunctionExecutable;
49 class FunctionParameters;
50 struct ParserError;
51 class ScriptExecutable;
52 class SourceCode;
53 class SourceProvider;
54 class SharedSymbolTable;
55 class UnlinkedCodeBlock;
56 class UnlinkedFunctionCodeBlock;
57
58 typedef unsigned UnlinkedValueProfile;
59 typedef unsigned UnlinkedArrayProfile;
60 typedef unsigned UnlinkedArrayAllocationProfile;
61 typedef unsigned UnlinkedObjectAllocationProfile;
62 typedef unsigned UnlinkedLLIntCallLinkInfo;
63
64 struct ExecutableInfo {
65     ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor)
66         : m_needsActivation(needsActivation)
67         , m_usesEval(usesEval)
68         , m_isStrictMode(isStrictMode)
69         , m_isConstructor(isConstructor)
70     {
71     }
72     bool m_needsActivation;
73     bool m_usesEval;
74     bool m_isStrictMode;
75     bool m_isConstructor;
76 };
77
78 class UnlinkedFunctionExecutable : public JSCell {
79 public:
80     friend class CodeCache;
81     typedef JSCell Base;
82     static UnlinkedFunctionExecutable* create(JSGlobalData* globalData, const SourceCode& source, FunctionBodyNode* node)
83     {
84         UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(globalData->heap)) UnlinkedFunctionExecutable(globalData, globalData->unlinkedFunctionExecutableStructure.get(), source, node);
85         instance->finishCreation(*globalData);
86         return instance;
87     }
88
89     const Identifier& name() const { return m_name; }
90     const Identifier& inferredName() const { return m_inferredName; }
91     JSString* nameValue() const { return m_nameValue.get(); }
92     SharedSymbolTable* symbolTable(CodeSpecializationKind kind)
93     {
94         return (kind == CodeForCall) ? m_symbolTableForCall.get() : m_symbolTableForConstruct.get();
95     }
96     size_t parameterCount() const { return m_parameters->size(); }
97     bool isInStrictContext() const { return m_isInStrictContext; }
98     FunctionNameIsInScopeToggle functionNameIsInScopeToggle() const { return m_functionNameIsInScopeToggle; }
99
100     unsigned firstLineOffset() const { return m_firstLineOffset; }
101     unsigned lineCount() const { return m_lineCount; }
102     unsigned functionStartOffset() const { return m_functionStartOffset; }
103     unsigned startOffset() const { return m_startOffset; }
104     unsigned sourceLength() { return m_sourceLength; }
105
106     String paramString() const;
107
108     UnlinkedFunctionCodeBlock* codeBlockFor(JSGlobalData&, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&);
109
110     static UnlinkedFunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
111
112     FunctionExecutable* link(JSGlobalData&, const SourceCode&, size_t lineOffset, size_t sourceOffset);
113
114     void clearCodeForRecompilation()
115     {
116         m_symbolTableForCall.clear();
117         m_symbolTableForConstruct.clear();
118         m_codeBlockForCall.clear();
119         m_codeBlockForConstruct.clear();
120     }
121
122     FunctionParameters* parameters() { return m_parameters.get(); }
123
124     void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
125     {
126         m_features = features;
127         m_hasCapturedVariables = hasCapturedVariables;
128         m_lineCount = lastLine - firstLine;
129     }
130
131     bool forceUsesArguments() const { return m_forceUsesArguments; }
132
133     CodeFeatures features() const { return m_features; }
134     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
135
136     static const bool needsDestruction = true;
137     static const bool hasImmortalStructure = true;
138     static void destroy(JSCell*);
139
140 private:
141     UnlinkedFunctionExecutable(JSGlobalData*, Structure*, const SourceCode&, FunctionBodyNode*);
142     Weak<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
143     Weak<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;
144
145     unsigned m_numCapturedVariables : 29;
146     bool m_forceUsesArguments : 1;
147     bool m_isInStrictContext : 1;
148     bool m_hasCapturedVariables : 1;
149
150     Identifier m_name;
151     Identifier m_inferredName;
152     WriteBarrier<JSString> m_nameValue;
153     WriteBarrier<SharedSymbolTable> m_symbolTableForCall;
154     WriteBarrier<SharedSymbolTable> m_symbolTableForConstruct;
155     RefPtr<FunctionParameters> m_parameters;
156     unsigned m_firstLineOffset;
157     unsigned m_lineCount;
158     unsigned m_functionStartOffset;
159     unsigned m_startOffset;
160     unsigned m_sourceLength;
161
162     CodeFeatures m_features;
163
164     FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle;
165
166 protected:
167     void finishCreation(JSGlobalData& globalData)
168     {
169         Base::finishCreation(globalData);
170         m_nameValue.set(globalData, this, jsString(&globalData, name().string()));
171     }
172
173     static void visitChildren(JSCell*, SlotVisitor&);
174
175 public:
176     static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
177     {
178         return Structure::create(globalData, globalObject, proto, TypeInfo(UnlinkedFunctionExecutableType, StructureFlags), &s_info);
179     }
180
181     static const unsigned StructureFlags = OverridesVisitChildren | JSCell::StructureFlags;
182
183     static const ClassInfo s_info;
184 };
185
186 struct UnlinkedStringJumpTable {
187     typedef HashMap<RefPtr<StringImpl>, int32_t> StringOffsetTable;
188     StringOffsetTable offsetTable;
189
190     inline int32_t offsetForValue(StringImpl* value, int32_t defaultOffset)
191     {
192         StringOffsetTable::const_iterator end = offsetTable.end();
193         StringOffsetTable::const_iterator loc = offsetTable.find(value);
194         if (loc == end)
195             return defaultOffset;
196         return loc->value;
197     }
198
199 };
200
201 struct UnlinkedSimpleJumpTable {
202     Vector<int32_t> branchOffsets;
203     int32_t min;
204
205     int32_t offsetForValue(int32_t value, int32_t defaultOffset);
206     void add(int32_t key, int32_t offset)
207     {
208         if (!branchOffsets[key])
209             branchOffsets[key] = offset;
210     }
211 };
212
213 struct UnlinkedHandlerInfo {
214     uint32_t start;
215     uint32_t end;
216     uint32_t target;
217     uint32_t scopeDepth;
218 };
219
220 struct UnlinkedInstruction {
221     UnlinkedInstruction() { u.operand = 0; }
222     UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
223     UnlinkedInstruction(int operand) { u.operand = operand; }
224     union {
225         OpcodeID opcode;
226         int32_t operand;
227     } u;
228 };
229
230 class UnlinkedCodeBlock : public JSCell {
231 public:
232     typedef JSCell Base;
233     static const bool needsDestruction = true;
234     static const bool hasImmortalStructure = true;
235
236     enum { CallFunction, ApplyFunction };
237
238     bool isConstructor() const { return m_isConstructor; }
239     bool isStrictMode() const { return m_isStrictMode; }
240     bool usesEval() const { return m_usesEval; }
241
242     bool needsFullScopeChain() const { return m_needsFullScopeChain; }
243     void setNeedsFullScopeChain(bool needsFullScopeChain) { m_needsFullScopeChain = needsFullScopeChain; }
244
245     void addExpressionInfo(const ExpressionRangeInfo& expressionInfo)
246     {
247         m_expressionInfo.append(expressionInfo);
248     }
249
250     void addLineInfo(unsigned bytecodeOffset, int lineNo)
251     {
252         Vector<LineInfo>& lineInfo = m_lineInfo;
253         if (!lineInfo.size() || lineInfo.last().lineNumber != lineNo) {
254             LineInfo info = { bytecodeOffset, lineNo };
255             lineInfo.append(info);
256         }
257     }
258
259     bool hasExpressionInfo() { return m_expressionInfo.size(); }
260
261     // Special registers
262     void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
263     void setActivationRegister(int activationRegister) { m_activationRegister = activationRegister; }
264
265     void setArgumentsRegister(int argumentsRegister) { m_argumentsRegister = argumentsRegister; }
266     bool usesArguments() const { return m_argumentsRegister != -1; }
267     int argumentsRegister() const { return m_argumentsRegister; }
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_globalData, 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_globalData, 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_lineInfo.shrinkToFit();
327         m_propertyAccessInstructions.shrinkToFit();
328         m_expressionInfo.shrinkToFit();
329
330 #if ENABLE(BYTECODE_COMMENTS)
331         m_bytecodeComments.shrinkToFit();
332 #endif
333         if (m_rareData) {
334             m_rareData->m_exceptionHandlers.shrinkToFit();
335             m_rareData->m_regexps.shrinkToFit();
336             m_rareData->m_constantBuffers.shrinkToFit();
337             m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
338             m_rareData->m_characterSwitchJumpTables.shrinkToFit();
339             m_rareData->m_stringSwitchJumpTables.shrinkToFit();
340         }
341     }
342
343     unsigned numberOfInstructions() const { return m_unlinkedInstructions.size(); }
344     RefCountedArray<UnlinkedInstruction>& instructions() { return m_unlinkedInstructions; }
345     const RefCountedArray<UnlinkedInstruction>& instructions() const { return m_unlinkedInstructions; }
346
347     int m_numVars;
348     int m_numCapturedVars;
349     int m_numCalleeRegisters;
350
351     // Jump Tables
352
353     size_t numberOfImmediateSwitchJumpTables() const { return m_rareData ? m_rareData->m_immediateSwitchJumpTables.size() : 0; }
354     UnlinkedSimpleJumpTable& addImmediateSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_immediateSwitchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_immediateSwitchJumpTables.last(); }
355     UnlinkedSimpleJumpTable& immediateSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_immediateSwitchJumpTables[tableIndex]; }
356
357     size_t numberOfCharacterSwitchJumpTables() const { return m_rareData ? m_rareData->m_characterSwitchJumpTables.size() : 0; }
358     UnlinkedSimpleJumpTable& addCharacterSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_characterSwitchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_characterSwitchJumpTables.last(); }
359     UnlinkedSimpleJumpTable& characterSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_characterSwitchJumpTables[tableIndex]; }
360
361     size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }
362     UnlinkedStringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(UnlinkedStringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
363     UnlinkedStringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
364
365     unsigned addFunctionDecl(UnlinkedFunctionExecutable* n)
366     {
367         unsigned size = m_functionDecls.size();
368         m_functionDecls.append(WriteBarrier<UnlinkedFunctionExecutable>());
369         m_functionDecls.last().set(*m_globalData, this, n);
370         return size;
371     }
372     UnlinkedFunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
373     size_t numberOfFunctionDecls() { return m_functionDecls.size(); }
374     unsigned addFunctionExpr(UnlinkedFunctionExecutable* n)
375     {
376         unsigned size = m_functionExprs.size();
377         m_functionExprs.append(WriteBarrier<UnlinkedFunctionExecutable>());
378         m_functionExprs.last().set(*m_globalData, this, n);
379         return size;
380     }
381     UnlinkedFunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
382     size_t numberOfFunctionExprs() { return m_functionExprs.size(); }
383
384     // Exception handling support
385     size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
386     void addExceptionHandler(const UnlinkedHandlerInfo& hanler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(hanler); }
387     UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
388
389     SharedSymbolTable* symbolTable() const { return m_symbolTable.get(); }
390
391     JSGlobalData* globalData() const { return m_globalData; }
392
393     unsigned addResolve() { return m_resolveOperationCount++; }
394     unsigned numberOfResolveOperations() const { return m_resolveOperationCount; }
395     unsigned addPutToBase() { return m_putToBaseOperationCount++; }
396     unsigned numberOfPutToBaseOperations() const { return m_putToBaseOperationCount; }
397
398     UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; }
399     unsigned numberOfArrayProfiles() { return m_arrayProfileCount; }
400     UnlinkedArrayAllocationProfile addArrayAllocationProfile() { return m_arrayAllocationProfileCount++; }
401     unsigned numberOfArrayAllocationProfiles() { return m_arrayAllocationProfileCount; }
402     UnlinkedObjectAllocationProfile addObjectAllocationProfile() { return m_objectAllocationProfileCount++; }
403     unsigned numberOfObjectAllocationProfiles() { return m_objectAllocationProfileCount; }
404     UnlinkedValueProfile addValueProfile() { return m_valueProfileCount++; }
405     unsigned numberOfValueProfiles() { return m_valueProfileCount; }
406
407     UnlinkedLLIntCallLinkInfo addLLIntCallLinkInfo() { return m_llintCallLinkInfoCount++; }
408     unsigned numberOfLLintCallLinkInfos() { return m_llintCallLinkInfoCount; }
409
410     CodeType codeType() const { return m_codeType; }
411
412     int thisRegister() const { return m_thisRegister; }
413     int activationRegister() const { return m_activationRegister; }
414
415
416     void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
417     {
418         m_propertyAccessInstructions.append(propertyAccessInstruction);
419     }
420
421     size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); }
422     const Vector<unsigned>& propertyAccessInstructions() const { return m_propertyAccessInstructions; }
423
424     typedef Vector<JSValue> ConstantBuffer;
425
426     size_t constantBufferCount() { ASSERT(m_rareData); return m_rareData->m_constantBuffers.size(); }
427     unsigned addConstantBuffer(unsigned length)
428     {
429         createRareDataIfNecessary();
430         unsigned size = m_rareData->m_constantBuffers.size();
431         m_rareData->m_constantBuffers.append(Vector<JSValue>(length));
432         return size;
433     }
434
435     const ConstantBuffer& constantBuffer(unsigned index) const
436     {
437         ASSERT(m_rareData);
438         return m_rareData->m_constantBuffers[index];
439     }
440
441     ConstantBuffer& constantBuffer(unsigned index)
442     {
443         ASSERT(m_rareData);
444         return m_rareData->m_constantBuffers[index];
445     }
446
447     bool hasRareData() const { return m_rareData; }
448
449     int lineNumberForBytecodeOffset(unsigned bytecodeOffset);
450
451     void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset);
452
453     void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount)
454     {
455         m_features = features;
456         m_hasCapturedVariables = hasCapturedVariables;
457         m_firstLine = firstLine;
458         m_lineCount = lineCount;
459     }
460
461     CodeFeatures codeFeatures() const { return m_features; }
462     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
463     unsigned firstLine() const { return m_firstLine; }
464     unsigned lineCount() const { return m_lineCount; }
465
466 protected:
467     UnlinkedCodeBlock(JSGlobalData*, Structure*, CodeType, const ExecutableInfo&);
468     ~UnlinkedCodeBlock();
469
470     void finishCreation(JSGlobalData& globalData)
471     {
472         Base::finishCreation(globalData);
473         if (codeType() == GlobalCode)
474             return;
475         m_symbolTable.set(globalData, this, SharedSymbolTable::create(globalData));
476     }
477
478 private:
479
480     void createRareDataIfNecessary()
481     {
482         if (!m_rareData)
483             m_rareData = adoptPtr(new RareData);
484     }
485
486     RefCountedArray<UnlinkedInstruction> m_unlinkedInstructions;
487
488     int m_numParameters;
489     JSGlobalData* m_globalData;
490
491     int m_thisRegister;
492     int m_argumentsRegister;
493     int m_activationRegister;
494
495     bool m_needsFullScopeChain : 1;
496     bool m_usesEval : 1;
497     bool m_isNumericCompareFunction : 1;
498     bool m_isStrictMode : 1;
499     bool m_isConstructor : 1;
500     bool m_hasCapturedVariables : 1;
501     unsigned m_firstLine;
502     unsigned m_lineCount;
503
504     CodeFeatures m_features;
505     CodeType m_codeType;
506
507     Vector<unsigned> m_jumpTargets;
508
509     // Constant Pools
510     Vector<Identifier> m_identifiers;
511     Vector<WriteBarrier<Unknown> > m_constantRegisters;
512     typedef Vector<WriteBarrier<UnlinkedFunctionExecutable> > FunctionExpressionVector;
513     FunctionExpressionVector m_functionDecls;
514     FunctionExpressionVector m_functionExprs;
515
516     WriteBarrier<SharedSymbolTable> m_symbolTable;
517
518     Vector<LineInfo> m_lineInfo;
519
520     Vector<unsigned> m_propertyAccessInstructions;
521
522 #if ENABLE(BYTECODE_COMMENTS)
523     Vector<Comment>  m_bytecodeComments;
524     size_t m_bytecodeCommentIterator;
525 #endif
526
527     unsigned m_resolveOperationCount;
528     unsigned m_putToBaseOperationCount;
529     unsigned m_arrayProfileCount;
530     unsigned m_arrayAllocationProfileCount;
531     unsigned m_objectAllocationProfileCount;
532     unsigned m_valueProfileCount;
533     unsigned m_llintCallLinkInfoCount;
534
535 public:
536     struct RareData {
537         WTF_MAKE_FAST_ALLOCATED;
538     public:
539         Vector<UnlinkedHandlerInfo> m_exceptionHandlers;
540
541         // Rare Constants
542         Vector<WriteBarrier<RegExp> > m_regexps;
543
544         // Buffers used for large array literals
545         Vector<ConstantBuffer> m_constantBuffers;
546
547         // Jump Tables
548         Vector<UnlinkedSimpleJumpTable> m_immediateSwitchJumpTables;
549         Vector<UnlinkedSimpleJumpTable> m_characterSwitchJumpTables;
550         Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables;
551
552         // Expression info - present if debugging.
553     };
554
555 private:
556     OwnPtr<RareData> m_rareData;
557     Vector<ExpressionRangeInfo> m_expressionInfo;
558
559 protected:
560
561     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
562     static void visitChildren(JSCell*, SlotVisitor&);
563
564 public:
565     static const ClassInfo s_info;
566 };
567
568 class UnlinkedGlobalCodeBlock : public UnlinkedCodeBlock {
569 public:
570     typedef UnlinkedCodeBlock Base;
571
572 protected:
573     UnlinkedGlobalCodeBlock(JSGlobalData* globalData, Structure* structure, CodeType codeType, const ExecutableInfo& info)
574         : Base(globalData, structure, codeType, info)
575     {
576     }
577
578     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
579
580     static const ClassInfo s_info;
581 };
582
583 class UnlinkedProgramCodeBlock : public UnlinkedGlobalCodeBlock {
584 private:
585     friend class CodeCache;
586     static UnlinkedProgramCodeBlock* create(JSGlobalData* globalData, const ExecutableInfo& info)
587     {
588         UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedProgramCodeBlock>(globalData->heap)) UnlinkedProgramCodeBlock(globalData, globalData->unlinkedProgramCodeBlockStructure.get(), info);
589         instance->finishCreation(*globalData);
590         return instance;
591     }
592
593 public:
594     typedef UnlinkedGlobalCodeBlock Base;
595     static void destroy(JSCell*);
596
597     void addFunctionDeclaration(JSGlobalData& globalData, const Identifier& name, UnlinkedFunctionExecutable* functionExecutable)
598     {
599         m_functionDeclarations.append(std::make_pair(name, WriteBarrier<UnlinkedFunctionExecutable>(globalData, this, functionExecutable)));
600     }
601
602     void addVariableDeclaration(const Identifier& name, bool isConstant)
603     {
604         m_varDeclarations.append(std::make_pair(name, isConstant));
605     }
606
607     typedef Vector<std::pair<Identifier, bool> > VariableDeclations;
608     typedef Vector<std::pair<Identifier, WriteBarrier<UnlinkedFunctionExecutable> > > FunctionDeclations;
609
610     const VariableDeclations& variableDeclarations() const { return m_varDeclarations; }
611     const FunctionDeclations& functionDeclarations() const { return m_functionDeclarations; }
612
613     static void visitChildren(JSCell*, SlotVisitor&);
614
615 private:
616     UnlinkedProgramCodeBlock(JSGlobalData* globalData, Structure* structure, const ExecutableInfo& info)
617         : Base(globalData, structure, GlobalCode, info)
618     {
619     }
620
621     VariableDeclations m_varDeclarations;
622     FunctionDeclations m_functionDeclarations;
623
624 public:
625     static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
626     {
627         return Structure::create(globalData, globalObject, proto, TypeInfo(UnlinkedProgramCodeBlockType, StructureFlags), &s_info);
628     }
629
630     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
631
632     static const ClassInfo s_info;
633 };
634
635 class UnlinkedEvalCodeBlock : public UnlinkedGlobalCodeBlock {
636 private:
637     friend class CodeCache;
638
639     static UnlinkedEvalCodeBlock* create(JSGlobalData* globalData, const ExecutableInfo& info)
640     {
641         UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell<UnlinkedEvalCodeBlock>(globalData->heap)) UnlinkedEvalCodeBlock(globalData, globalData->unlinkedEvalCodeBlockStructure.get(), info);
642         instance->finishCreation(*globalData);
643         return instance;
644     }
645
646 public:
647     typedef UnlinkedGlobalCodeBlock Base;
648     static void destroy(JSCell*);
649
650     const Identifier& variable(unsigned index) { return m_variables[index]; }
651     unsigned numVariables() { return m_variables.size(); }
652     void adoptVariables(Vector<Identifier>& variables)
653     {
654         ASSERT(m_variables.isEmpty());
655         m_variables.swap(variables);
656     }
657
658 private:
659     UnlinkedEvalCodeBlock(JSGlobalData* globalData, Structure* structure, const ExecutableInfo& info)
660         : Base(globalData, structure, EvalCode, info)
661     {
662     }
663
664     Vector<Identifier> m_variables;
665
666 public:
667     static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
668     {
669         return Structure::create(globalData, globalObject, proto, TypeInfo(UnlinkedEvalCodeBlockType, StructureFlags), &s_info);
670     }
671
672     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
673
674     static const ClassInfo s_info;
675 };
676
677 class UnlinkedFunctionCodeBlock : public UnlinkedCodeBlock {
678 private:
679     friend class CodeCache;
680
681     static UnlinkedFunctionCodeBlock* create(JSGlobalData* globalData, CodeType codeType, const ExecutableInfo& info)
682     {
683         UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell<UnlinkedFunctionCodeBlock>(globalData->heap)) UnlinkedFunctionCodeBlock(globalData, globalData->unlinkedFunctionCodeBlockStructure.get(), codeType, info);
684         instance->finishCreation(*globalData);
685         return instance;
686     }
687
688 public:
689     typedef UnlinkedCodeBlock Base;
690     static void destroy(JSCell*);
691
692 private:
693     UnlinkedFunctionCodeBlock(JSGlobalData* globalData, Structure* structure, CodeType codeType, const ExecutableInfo& info)
694         : Base(globalData, structure, codeType, info)
695     {
696     }
697     
698 public:
699     static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
700     {
701         return Structure::create(globalData, globalObject, proto, TypeInfo(UnlinkedFunctionCodeBlockType, StructureFlags), &s_info);
702     }
703
704     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
705
706     static const ClassInfo s_info;
707 };
708
709 }
710
711 #endif // UnlinkedCodeBlock_h