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