/* * 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 #include 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(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 m_codeBlockForCall; WriteBarrier 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 m_nameValue; WriteBarrier m_symbolTableForCall; WriteBarrier m_symbolTableForConstruct; RefPtr 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, 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 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(*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& 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()); m_constantRegisters.last().set(*m_vm, this, v); return result; } unsigned addOrFindConstant(JSValue); const Vector >& constantRegisters() { return m_constantRegisters; } const WriteBarrier& 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& instructions() { return m_unlinkedInstructions; } const RefCountedArray& 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()); 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()); 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& propertyAccessInstructions() const { return m_propertyAccessInstructions; } typedef Vector 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(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 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 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 m_jumpTargets; // Constant Pools Vector m_identifiers; Vector > m_constantRegisters; typedef Vector > FunctionExpressionVector; FunctionExpressionVector m_functionDecls; FunctionExpressionVector m_functionExprs; WriteBarrier m_symbolTable; Vector m_propertyAccessInstructions; #if ENABLE(BYTECODE_COMMENTS) Vector 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 m_exceptionHandlers; // Rare Constants Vector > m_regexps; // Buffers used for large array literals Vector m_constantBuffers; // Jump Tables Vector m_immediateSwitchJumpTables; Vector m_characterSwitchJumpTables; Vector m_stringSwitchJumpTables; RefPtr m_evalCodeCache; Vector m_expressionInfoFatPositions; }; private: OwnPtr m_rareData; Vector 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(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(vm, this, functionExecutable))); } void addVariableDeclaration(const Identifier& name, bool isConstant) { m_varDeclarations.append(std::make_pair(name, isConstant)); } typedef Vector > VariableDeclations; typedef Vector > > 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(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& variables) { ASSERT(m_variables.isEmpty()); m_variables.swap(variables); } private: UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info) : Base(vm, structure, EvalCode, info) { } Vector 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(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