]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - bytecode/UnlinkedCodeBlock.h
JavaScriptCore-1218.tar.gz
[apple/javascriptcore.git] / bytecode / UnlinkedCodeBlock.h
diff --git a/bytecode/UnlinkedCodeBlock.h b/bytecode/UnlinkedCodeBlock.h
new file mode 100644 (file)
index 0000000..6349683
--- /dev/null
@@ -0,0 +1,718 @@
+/*
+ * Copyright (C) 2012, 2013 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef UnlinkedCodeBlock_h
+#define UnlinkedCodeBlock_h
+
+#include "BytecodeConventions.h"
+#include "CodeCache.h"
+#include "CodeSpecializationKind.h"
+#include "CodeType.h"
+#include "ExpressionRangeInfo.h"
+#include "Identifier.h"
+#include "JSCell.h"
+#include "JSString.h"
+#include "LineInfo.h"
+#include "ParserModes.h"
+#include "RegExp.h"
+#include "SpecialPointer.h"
+#include "SymbolTable.h"
+
+#include <wtf/RefCountedArray.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class Debugger;
+class FunctionBodyNode;
+class FunctionExecutable;
+class FunctionParameters;
+class JSScope;
+struct ParserError;
+class ScriptExecutable;
+class SourceCode;
+class SourceProvider;
+class SharedSymbolTable;
+class UnlinkedCodeBlock;
+class UnlinkedFunctionCodeBlock;
+
+typedef unsigned UnlinkedValueProfile;
+typedef unsigned UnlinkedArrayProfile;
+typedef unsigned UnlinkedArrayAllocationProfile;
+typedef unsigned UnlinkedObjectAllocationProfile;
+typedef unsigned UnlinkedLLIntCallLinkInfo;
+
+struct ExecutableInfo {
+    ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor)
+        : m_needsActivation(needsActivation)
+        , m_usesEval(usesEval)
+        , m_isStrictMode(isStrictMode)
+        , m_isConstructor(isConstructor)
+    {
+    }
+    bool m_needsActivation;
+    bool m_usesEval;
+    bool m_isStrictMode;
+    bool m_isConstructor;
+};
+
+class UnlinkedFunctionExecutable : public JSCell {
+public:
+    friend class CodeCache;
+    typedef JSCell Base;
+    static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionBodyNode* node)
+    {
+        UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap)) UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node);
+        instance->finishCreation(*vm);
+        return instance;
+    }
+
+    const Identifier& name() const { return m_name; }
+    const Identifier& inferredName() const { return m_inferredName; }
+    JSString* nameValue() const { return m_nameValue.get(); }
+    SharedSymbolTable* symbolTable(CodeSpecializationKind kind)
+    {
+        return (kind == CodeForCall) ? m_symbolTableForCall.get() : m_symbolTableForConstruct.get();
+    }
+    size_t parameterCount() const;
+    bool isInStrictContext() const { return m_isInStrictContext; }
+    FunctionNameIsInScopeToggle functionNameIsInScopeToggle() const { return m_functionNameIsInScopeToggle; }
+
+    unsigned firstLineOffset() const { return m_firstLineOffset; }
+    unsigned lineCount() const { return m_lineCount; }
+    unsigned functionStartOffset() const { return m_functionStartOffset; }
+    unsigned functionStartColumn() const { return m_functionStartColumn; }
+    unsigned startOffset() const { return m_startOffset; }
+    unsigned sourceLength() { return m_sourceLength; }
+
+    String paramString() const;
+
+    UnlinkedFunctionCodeBlock* codeBlockFor(VM&, JSScope*, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&);
+
+    static UnlinkedFunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
+
+    FunctionExecutable* link(VM&, const SourceCode&, size_t lineOffset, size_t sourceOffset);
+
+    void clearCodeForRecompilation()
+    {
+        m_symbolTableForCall.clear();
+        m_symbolTableForConstruct.clear();
+        m_codeBlockForCall.clear();
+        m_codeBlockForConstruct.clear();
+    }
+
+    FunctionParameters* parameters() { return m_parameters.get(); }
+
+    void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
+    {
+        m_features = features;
+        m_hasCapturedVariables = hasCapturedVariables;
+        m_lineCount = lastLine - firstLine;
+    }
+
+    bool forceUsesArguments() const { return m_forceUsesArguments; }
+
+    CodeFeatures features() const { return m_features; }
+    bool hasCapturedVariables() const { return m_hasCapturedVariables; }
+
+    static const bool needsDestruction = true;
+    static const bool hasImmortalStructure = true;
+    static void destroy(JSCell*);
+
+private:
+    UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionBodyNode*);
+    WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
+    WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;
+
+    unsigned m_numCapturedVariables : 29;
+    bool m_forceUsesArguments : 1;
+    bool m_isInStrictContext : 1;
+    bool m_hasCapturedVariables : 1;
+
+    Identifier m_name;
+    Identifier m_inferredName;
+    WriteBarrier<JSString> m_nameValue;
+    WriteBarrier<SharedSymbolTable> m_symbolTableForCall;
+    WriteBarrier<SharedSymbolTable> m_symbolTableForConstruct;
+    RefPtr<FunctionParameters> m_parameters;
+    unsigned m_firstLineOffset;
+    unsigned m_lineCount;
+    unsigned m_functionStartOffset;
+    unsigned m_functionStartColumn;
+    unsigned m_startOffset;
+    unsigned m_sourceLength;
+
+    CodeFeatures m_features;
+
+    FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle;
+
+protected:
+    void finishCreation(VM& vm)
+    {
+        Base::finishCreation(vm);
+        m_nameValue.set(vm, this, jsString(&vm, name().string()));
+    }
+
+    static void visitChildren(JSCell*, SlotVisitor&);
+
+public:
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
+    {
+        return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionExecutableType, StructureFlags), &s_info);
+    }
+
+    static const unsigned StructureFlags = OverridesVisitChildren | JSCell::StructureFlags;
+
+    static const ClassInfo s_info;
+};
+
+struct UnlinkedStringJumpTable {
+    typedef HashMap<RefPtr<StringImpl>, int32_t> StringOffsetTable;
+    StringOffsetTable offsetTable;
+
+    inline int32_t offsetForValue(StringImpl* value, int32_t defaultOffset)
+    {
+        StringOffsetTable::const_iterator end = offsetTable.end();
+        StringOffsetTable::const_iterator loc = offsetTable.find(value);
+        if (loc == end)
+            return defaultOffset;
+        return loc->value;
+    }
+
+};
+
+struct UnlinkedSimpleJumpTable {
+    Vector<int32_t> branchOffsets;
+    int32_t min;
+
+    int32_t offsetForValue(int32_t value, int32_t defaultOffset);
+    void add(int32_t key, int32_t offset)
+    {
+        if (!branchOffsets[key])
+            branchOffsets[key] = offset;
+    }
+};
+
+struct UnlinkedHandlerInfo {
+    uint32_t start;
+    uint32_t end;
+    uint32_t target;
+    uint32_t scopeDepth;
+};
+
+struct UnlinkedInstruction {
+    UnlinkedInstruction() { u.operand = 0; }
+    UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
+    UnlinkedInstruction(int operand) { u.operand = operand; }
+    union {
+        OpcodeID opcode;
+        int32_t operand;
+    } u;
+};
+
+class UnlinkedCodeBlock : public JSCell {
+public:
+    typedef JSCell Base;
+    static const bool needsDestruction = true;
+    static const bool hasImmortalStructure = true;
+
+    enum { CallFunction, ApplyFunction };
+
+    bool isConstructor() const { return m_isConstructor; }
+    bool isStrictMode() const { return m_isStrictMode; }
+    bool usesEval() const { return m_usesEval; }
+
+    bool needsFullScopeChain() const { return m_needsFullScopeChain; }
+    void setNeedsFullScopeChain(bool needsFullScopeChain) { m_needsFullScopeChain = needsFullScopeChain; }
+
+    void addExpressionInfo(unsigned instructionOffset, int divot,
+        int startOffset, int endOffset, unsigned line, unsigned column);
+
+    bool hasExpressionInfo() { return m_expressionInfo.size(); }
+
+    // Special registers
+    void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
+    void setActivationRegister(int activationRegister) { m_activationRegister = activationRegister; }
+
+    void setArgumentsRegister(int argumentsRegister) { m_argumentsRegister = argumentsRegister; }
+    bool usesArguments() const { return m_argumentsRegister != -1; }
+    int argumentsRegister() const { return m_argumentsRegister; }
+
+
+    bool usesGlobalObject() const { return m_globalObjectRegister != -1; }
+    void setGlobalObjectRegister(int globalObjectRegister) { m_globalObjectRegister = globalObjectRegister; }
+    int globalObjectRegister() const { return m_globalObjectRegister; }
+
+    // Parameter information
+    void setNumParameters(int newValue) { m_numParameters = newValue; }
+    void addParameter() { m_numParameters++; }
+    unsigned numParameters() const { return m_numParameters; }
+
+    unsigned addRegExp(RegExp* r)
+    {
+        createRareDataIfNecessary();
+        unsigned size = m_rareData->m_regexps.size();
+        m_rareData->m_regexps.append(WriteBarrier<RegExp>(*m_vm, this, r));
+        return size;
+    }
+    unsigned numberOfRegExps() const
+    {
+        if (!m_rareData)
+            return 0;
+        return m_rareData->m_regexps.size();
+    }
+    RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
+
+    // Constant Pools
+
+    size_t numberOfIdentifiers() const { return m_identifiers.size(); }
+    void addIdentifier(const Identifier& i) { return m_identifiers.append(i); }
+    const Identifier& identifier(int index) const { return m_identifiers[index]; }
+    const Vector<Identifier>& identifiers() const { return m_identifiers; }
+
+    size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
+    unsigned addConstant(JSValue v)
+    {
+        unsigned result = m_constantRegisters.size();
+        m_constantRegisters.append(WriteBarrier<Unknown>());
+        m_constantRegisters.last().set(*m_vm, this, v);
+        return result;
+    }
+    unsigned addOrFindConstant(JSValue);
+    const Vector<WriteBarrier<Unknown> >& constantRegisters() { return m_constantRegisters; }
+    const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
+    ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
+    ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
+
+    // Jumps
+    size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
+    void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
+    unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
+    unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
+
+    void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
+    bool isNumericCompareFunction() const { return m_isNumericCompareFunction; }
+
+    void shrinkToFit()
+    {
+        m_jumpTargets.shrinkToFit();
+        m_identifiers.shrinkToFit();
+        m_constantRegisters.shrinkToFit();
+        m_functionDecls.shrinkToFit();
+        m_functionExprs.shrinkToFit();
+        m_propertyAccessInstructions.shrinkToFit();
+        m_expressionInfo.shrinkToFit();
+
+#if ENABLE(BYTECODE_COMMENTS)
+        m_bytecodeComments.shrinkToFit();
+#endif
+        if (m_rareData) {
+            m_rareData->m_exceptionHandlers.shrinkToFit();
+            m_rareData->m_regexps.shrinkToFit();
+            m_rareData->m_constantBuffers.shrinkToFit();
+            m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
+            m_rareData->m_characterSwitchJumpTables.shrinkToFit();
+            m_rareData->m_stringSwitchJumpTables.shrinkToFit();
+            m_rareData->m_expressionInfoFatPositions.shrinkToFit();
+        }
+    }
+
+    unsigned numberOfInstructions() const { return m_unlinkedInstructions.size(); }
+    RefCountedArray<UnlinkedInstruction>& instructions() { return m_unlinkedInstructions; }
+    const RefCountedArray<UnlinkedInstruction>& instructions() const { return m_unlinkedInstructions; }
+
+    int m_numVars;
+    int m_numCapturedVars;
+    int m_numCalleeRegisters;
+
+    // Jump Tables
+
+    size_t numberOfImmediateSwitchJumpTables() const { return m_rareData ? m_rareData->m_immediateSwitchJumpTables.size() : 0; }
+    UnlinkedSimpleJumpTable& addImmediateSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_immediateSwitchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_immediateSwitchJumpTables.last(); }
+    UnlinkedSimpleJumpTable& immediateSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_immediateSwitchJumpTables[tableIndex]; }
+
+    size_t numberOfCharacterSwitchJumpTables() const { return m_rareData ? m_rareData->m_characterSwitchJumpTables.size() : 0; }
+    UnlinkedSimpleJumpTable& addCharacterSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_characterSwitchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_characterSwitchJumpTables.last(); }
+    UnlinkedSimpleJumpTable& characterSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_characterSwitchJumpTables[tableIndex]; }
+
+    size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }
+    UnlinkedStringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(UnlinkedStringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
+    UnlinkedStringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
+
+    unsigned addFunctionDecl(UnlinkedFunctionExecutable* n)
+    {
+        unsigned size = m_functionDecls.size();
+        m_functionDecls.append(WriteBarrier<UnlinkedFunctionExecutable>());
+        m_functionDecls.last().set(*m_vm, this, n);
+        return size;
+    }
+    UnlinkedFunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
+    size_t numberOfFunctionDecls() { return m_functionDecls.size(); }
+    unsigned addFunctionExpr(UnlinkedFunctionExecutable* n)
+    {
+        unsigned size = m_functionExprs.size();
+        m_functionExprs.append(WriteBarrier<UnlinkedFunctionExecutable>());
+        m_functionExprs.last().set(*m_vm, this, n);
+        return size;
+    }
+    UnlinkedFunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
+    size_t numberOfFunctionExprs() { return m_functionExprs.size(); }
+
+    // Exception handling support
+    size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
+    void addExceptionHandler(const UnlinkedHandlerInfo& hanler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(hanler); }
+    UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
+
+    SharedSymbolTable* symbolTable() const { return m_symbolTable.get(); }
+
+    VM* vm() const { return m_vm; }
+
+    unsigned addResolve() { return m_resolveOperationCount++; }
+    unsigned numberOfResolveOperations() const { return m_resolveOperationCount; }
+    unsigned addPutToBase() { return m_putToBaseOperationCount++; }
+    unsigned numberOfPutToBaseOperations() const { return m_putToBaseOperationCount; }
+
+    UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; }
+    unsigned numberOfArrayProfiles() { return m_arrayProfileCount; }
+    UnlinkedArrayAllocationProfile addArrayAllocationProfile() { return m_arrayAllocationProfileCount++; }
+    unsigned numberOfArrayAllocationProfiles() { return m_arrayAllocationProfileCount; }
+    UnlinkedObjectAllocationProfile addObjectAllocationProfile() { return m_objectAllocationProfileCount++; }
+    unsigned numberOfObjectAllocationProfiles() { return m_objectAllocationProfileCount; }
+    UnlinkedValueProfile addValueProfile() { return m_valueProfileCount++; }
+    unsigned numberOfValueProfiles() { return m_valueProfileCount; }
+
+    UnlinkedLLIntCallLinkInfo addLLIntCallLinkInfo() { return m_llintCallLinkInfoCount++; }
+    unsigned numberOfLLintCallLinkInfos() { return m_llintCallLinkInfoCount; }
+
+    CodeType codeType() const { return m_codeType; }
+
+    int thisRegister() const { return m_thisRegister; }
+    int activationRegister() const { return m_activationRegister; }
+
+
+    void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
+    {
+        m_propertyAccessInstructions.append(propertyAccessInstruction);
+    }
+
+    size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); }
+    const Vector<unsigned>& propertyAccessInstructions() const { return m_propertyAccessInstructions; }
+
+    typedef Vector<JSValue> ConstantBuffer;
+
+    size_t constantBufferCount() { ASSERT(m_rareData); return m_rareData->m_constantBuffers.size(); }
+    unsigned addConstantBuffer(unsigned length)
+    {
+        createRareDataIfNecessary();
+        unsigned size = m_rareData->m_constantBuffers.size();
+        m_rareData->m_constantBuffers.append(Vector<JSValue>(length));
+        return size;
+    }
+
+    const ConstantBuffer& constantBuffer(unsigned index) const
+    {
+        ASSERT(m_rareData);
+        return m_rareData->m_constantBuffers[index];
+    }
+
+    ConstantBuffer& constantBuffer(unsigned index)
+    {
+        ASSERT(m_rareData);
+        return m_rareData->m_constantBuffers[index];
+    }
+
+    bool hasRareData() const { return m_rareData; }
+
+    int lineNumberForBytecodeOffset(unsigned bytecodeOffset);
+
+    void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,
+        int& startOffset, int& endOffset, unsigned& line, unsigned& column);
+
+    void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount)
+    {
+        m_features = features;
+        m_hasCapturedVariables = hasCapturedVariables;
+        m_firstLine = firstLine;
+        m_lineCount = lineCount;
+    }
+
+    CodeFeatures codeFeatures() const { return m_features; }
+    bool hasCapturedVariables() const { return m_hasCapturedVariables; }
+    unsigned firstLine() const { return m_firstLine; }
+    unsigned lineCount() const { return m_lineCount; }
+
+    PassRefPtr<CodeCache> codeCacheForEval()
+    {
+        if (m_codeType == GlobalCode)
+            return m_vm->codeCache();
+        createRareDataIfNecessary();
+        if (!m_rareData->m_evalCodeCache)
+            m_rareData->m_evalCodeCache = CodeCache::create(CodeCache::NonGlobalCodeCache);
+        return m_rareData->m_evalCodeCache.get();
+    }
+
+protected:
+    UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&);
+    ~UnlinkedCodeBlock();
+
+    void finishCreation(VM& vm)
+    {
+        Base::finishCreation(vm);
+        if (codeType() == GlobalCode)
+            return;
+        m_symbolTable.set(vm, this, SharedSymbolTable::create(vm));
+    }
+
+private:
+
+    void createRareDataIfNecessary()
+    {
+        if (!m_rareData)
+            m_rareData = adoptPtr(new RareData);
+    }
+
+    RefCountedArray<UnlinkedInstruction> m_unlinkedInstructions;
+
+    int m_numParameters;
+    VM* m_vm;
+
+    int m_thisRegister;
+    int m_argumentsRegister;
+    int m_activationRegister;
+    int m_globalObjectRegister;
+
+    bool m_needsFullScopeChain : 1;
+    bool m_usesEval : 1;
+    bool m_isNumericCompareFunction : 1;
+    bool m_isStrictMode : 1;
+    bool m_isConstructor : 1;
+    bool m_hasCapturedVariables : 1;
+    unsigned m_firstLine;
+    unsigned m_lineCount;
+
+    CodeFeatures m_features;
+    CodeType m_codeType;
+
+    Vector<unsigned> m_jumpTargets;
+
+    // Constant Pools
+    Vector<Identifier> m_identifiers;
+    Vector<WriteBarrier<Unknown> > m_constantRegisters;
+    typedef Vector<WriteBarrier<UnlinkedFunctionExecutable> > FunctionExpressionVector;
+    FunctionExpressionVector m_functionDecls;
+    FunctionExpressionVector m_functionExprs;
+
+    WriteBarrier<SharedSymbolTable> m_symbolTable;
+
+    Vector<unsigned> m_propertyAccessInstructions;
+
+#if ENABLE(BYTECODE_COMMENTS)
+    Vector<Comment>  m_bytecodeComments;
+    size_t m_bytecodeCommentIterator;
+#endif
+
+    unsigned m_resolveOperationCount;
+    unsigned m_putToBaseOperationCount;
+    unsigned m_arrayProfileCount;
+    unsigned m_arrayAllocationProfileCount;
+    unsigned m_objectAllocationProfileCount;
+    unsigned m_valueProfileCount;
+    unsigned m_llintCallLinkInfoCount;
+
+public:
+    struct RareData {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        Vector<UnlinkedHandlerInfo> m_exceptionHandlers;
+
+        // Rare Constants
+        Vector<WriteBarrier<RegExp> > m_regexps;
+
+        // Buffers used for large array literals
+        Vector<ConstantBuffer> m_constantBuffers;
+
+        // Jump Tables
+        Vector<UnlinkedSimpleJumpTable> m_immediateSwitchJumpTables;
+        Vector<UnlinkedSimpleJumpTable> m_characterSwitchJumpTables;
+        Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables;
+        RefPtr<CodeCache> m_evalCodeCache;
+
+        Vector<ExpressionRangeInfo::FatPosition> m_expressionInfoFatPositions;
+    };
+
+private:
+    OwnPtr<RareData> m_rareData;
+    Vector<ExpressionRangeInfo> m_expressionInfo;
+
+protected:
+
+    static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
+    static void visitChildren(JSCell*, SlotVisitor&);
+
+public:
+    static const ClassInfo s_info;
+};
+
+class UnlinkedGlobalCodeBlock : public UnlinkedCodeBlock {
+public:
+    typedef UnlinkedCodeBlock Base;
+
+protected:
+    UnlinkedGlobalCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
+        : Base(vm, structure, codeType, info)
+    {
+    }
+
+    static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
+
+    static const ClassInfo s_info;
+};
+
+class UnlinkedProgramCodeBlock : public UnlinkedGlobalCodeBlock {
+private:
+    friend class CodeCache;
+    static UnlinkedProgramCodeBlock* create(VM* vm, const ExecutableInfo& info)
+    {
+        UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedProgramCodeBlock>(vm->heap)) UnlinkedProgramCodeBlock(vm, vm->unlinkedProgramCodeBlockStructure.get(), info);
+        instance->finishCreation(*vm);
+        return instance;
+    }
+
+public:
+    typedef UnlinkedGlobalCodeBlock Base;
+    static void destroy(JSCell*);
+
+    void addFunctionDeclaration(VM& vm, const Identifier& name, UnlinkedFunctionExecutable* functionExecutable)
+    {
+        m_functionDeclarations.append(std::make_pair(name, WriteBarrier<UnlinkedFunctionExecutable>(vm, this, functionExecutable)));
+    }
+
+    void addVariableDeclaration(const Identifier& name, bool isConstant)
+    {
+        m_varDeclarations.append(std::make_pair(name, isConstant));
+    }
+
+    typedef Vector<std::pair<Identifier, bool> > VariableDeclations;
+    typedef Vector<std::pair<Identifier, WriteBarrier<UnlinkedFunctionExecutable> > > FunctionDeclations;
+
+    const VariableDeclations& variableDeclarations() const { return m_varDeclarations; }
+    const FunctionDeclations& functionDeclarations() const { return m_functionDeclarations; }
+
+    static void visitChildren(JSCell*, SlotVisitor&);
+
+private:
+    UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
+        : Base(vm, structure, GlobalCode, info)
+    {
+    }
+
+    VariableDeclations m_varDeclarations;
+    FunctionDeclations m_functionDeclarations;
+
+public:
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
+    {
+        return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedProgramCodeBlockType, StructureFlags), &s_info);
+    }
+
+    static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
+
+    static const ClassInfo s_info;
+};
+
+class UnlinkedEvalCodeBlock : public UnlinkedGlobalCodeBlock {
+private:
+    friend class CodeCache;
+
+    static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo& info)
+    {
+        UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell<UnlinkedEvalCodeBlock>(vm->heap)) UnlinkedEvalCodeBlock(vm, vm->unlinkedEvalCodeBlockStructure.get(), info);
+        instance->finishCreation(*vm);
+        return instance;
+    }
+
+public:
+    typedef UnlinkedGlobalCodeBlock Base;
+    static void destroy(JSCell*);
+
+    const Identifier& variable(unsigned index) { return m_variables[index]; }
+    unsigned numVariables() { return m_variables.size(); }
+    void adoptVariables(Vector<Identifier, 0, UnsafeVectorOverflow>& variables)
+    {
+        ASSERT(m_variables.isEmpty());
+        m_variables.swap(variables);
+    }
+
+private:
+    UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
+        : Base(vm, structure, EvalCode, info)
+    {
+    }
+
+    Vector<Identifier, 0, UnsafeVectorOverflow> m_variables;
+
+public:
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
+    {
+        return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedEvalCodeBlockType, StructureFlags), &s_info);
+    }
+
+    static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
+
+    static const ClassInfo s_info;
+};
+
+class UnlinkedFunctionCodeBlock : public UnlinkedCodeBlock {
+public:
+    static UnlinkedFunctionCodeBlock* create(VM* vm, CodeType codeType, const ExecutableInfo& info)
+    {
+        UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell<UnlinkedFunctionCodeBlock>(vm->heap)) UnlinkedFunctionCodeBlock(vm, vm->unlinkedFunctionCodeBlockStructure.get(), codeType, info);
+        instance->finishCreation(*vm);
+        return instance;
+    }
+
+    typedef UnlinkedCodeBlock Base;
+    static void destroy(JSCell*);
+
+private:
+    UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
+        : Base(vm, structure, codeType, info)
+    {
+    }
+    
+public:
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
+    {
+        return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionCodeBlockType, StructureFlags), &s_info);
+    }
+
+    static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
+
+    static const ClassInfo s_info;
+};
+
+}
+
+#endif // UnlinkedCodeBlock_h