diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-07 11:22:47 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-07 11:22:47 +0100 |
commit | cfd86b747d32ac22246a1aa908eaa720c63a88c1 (patch) | |
tree | 24d68c6f61c464ecba1e05670b80390ea3b0e50c /Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h | |
parent | 69d7c744c9de19d152dbe2d8e46eb7dfd4511d1a (diff) | |
download | qtwebkit-cfd86b747d32ac22246a1aa908eaa720c63a88c1.tar.gz |
Imported WebKit commit 20271caf2e2c016d5cef40184cddeefeac4f1876 (http://svn.webkit.org/repository/webkit/trunk@133733)
New snapshot that contains all previous fixes as well as build fix for latest QtMultimedia API changes.
Diffstat (limited to 'Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h')
-rw-r--r-- | Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h | 700 |
1 files changed, 700 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h new file mode 100644 index 000000000..bf3f5fdff --- /dev/null +++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h @@ -0,0 +1,700 @@ +/* + * Copyright (C) 2012 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 "CodeSpecializationKind.h" +#include "CodeType.h" +#include "ExpressionRangeInfo.h" +#include "Identifier.h" +#include "JSCell.h" +#include "LineInfo.h" +#include "Nodes.h" +#include "RegExp.h" +#include "SpecialPointer.h" + +#include <wtf/RefCountedArray.h> +#include <wtf/Vector.h> + +namespace JSC { + +class Debugger; +class FunctionBodyNode; +class FunctionExecutable; +class FunctionParameters; +struct ParserError; +class ScriptExecutable; +class SourceCode; +class SourceProvider; +class SharedSymbolTable; +class UnlinkedCodeBlock; +class UnlinkedFunctionCodeBlock; + +typedef unsigned UnlinkedValueProfile; +typedef unsigned UnlinkedArrayProfile; +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(JSGlobalData* globalData, const SourceCode& source, FunctionBodyNode* node) + { + UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(globalData->heap)) UnlinkedFunctionExecutable(globalData, globalData->unlinkedFunctionExecutableStructure.get(), source, node); + instance->finishCreation(*globalData); + 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 { return m_parameters->size(); } + 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 startOffset() const { return m_startOffset; } + unsigned sourceLength() { return m_sourceLength; } + + String paramString() const; + + UnlinkedFunctionCodeBlock* codeBlockFor(JSGlobalData&, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&); + + static UnlinkedFunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception); + + FunctionExecutable* link(JSGlobalData&, const SourceCode&, size_t lineOffset, size_t sourceOffset); + + void clearCode() + { + 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(JSGlobalData*, 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_startOffset; + unsigned m_sourceLength; + + CodeFeatures m_features; + + FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle; + +protected: + void finishCreation(JSGlobalData& globalData) + { + Base::finishCreation(globalData); + m_nameValue.set(globalData, this, jsString(&globalData, name().string())); + } + + static void visitChildren(JSCell*, SlotVisitor&); + +public: + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(globalData, 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(const ExpressionRangeInfo& expressionInfo) + { + m_expressionInfo.append(expressionInfo); + } + + void addLineInfo(unsigned bytecodeOffset, int lineNo) + { + Vector<LineInfo>& lineInfo = m_lineInfo; + if (!lineInfo.size() || lineInfo.last().lineNumber != lineNo) { + LineInfo info = { bytecodeOffset, lineNo }; + lineInfo.append(info); + } + } + + 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; } + + // 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_globalData, 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_globalData, 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_lineInfo.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(); + } + } + + 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_globalData, 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_globalData, 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(); } + + JSGlobalData* globalData() const { return m_globalData; } + + 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; } + 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); + + 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; } + +protected: + UnlinkedCodeBlock(JSGlobalData*, Structure*, CodeType, const ExecutableInfo&); + ~UnlinkedCodeBlock(); + + void finishCreation(JSGlobalData& globalData) + { + Base::finishCreation(globalData); + if (codeType() == GlobalCode) + return; + m_symbolTable.set(globalData, this, SharedSymbolTable::create(globalData)); + } + +private: + + void createRareDataIfNecessary() + { + if (!m_rareData) + m_rareData = adoptPtr(new RareData); + } + + RefCountedArray<UnlinkedInstruction> m_unlinkedInstructions; + + int m_numParameters; + JSGlobalData* m_globalData; + + int m_thisRegister; + int m_argumentsRegister; + int m_activationRegister; + + 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<LineInfo> m_lineInfo; + + 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_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; + + // Expression info - present if debugging. + }; + +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(JSGlobalData* globalData, Structure* structure, CodeType codeType, const ExecutableInfo& info) + : Base(globalData, 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(JSGlobalData* globalData, const ExecutableInfo& info) + { + UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedProgramCodeBlock>(globalData->heap)) UnlinkedProgramCodeBlock(globalData, globalData->unlinkedProgramCodeBlockStructure.get(), info); + instance->finishCreation(*globalData); + return instance; + } + +public: + typedef UnlinkedGlobalCodeBlock Base; + static void destroy(JSCell*); + + void addFunctionDeclaration(JSGlobalData& globalData, const Identifier& name, UnlinkedFunctionExecutable* functionExecutable) + { + m_functionDeclarations.append(std::make_pair(name, WriteBarrier<UnlinkedFunctionExecutable>(globalData, 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(JSGlobalData* globalData, Structure* structure, const ExecutableInfo& info) + : Base(globalData, structure, GlobalCode, info) + { + } + + VariableDeclations m_varDeclarations; + FunctionDeclations m_functionDeclarations; + +public: + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(globalData, 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(JSGlobalData* globalData, const ExecutableInfo& info) + { + UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell<UnlinkedEvalCodeBlock>(globalData->heap)) UnlinkedEvalCodeBlock(globalData, globalData->unlinkedEvalCodeBlockStructure.get(), info); + instance->finishCreation(*globalData); + 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>& variables) + { + ASSERT(m_variables.isEmpty()); + m_variables.swap(variables); + } + +private: + UnlinkedEvalCodeBlock(JSGlobalData* globalData, Structure* structure, const ExecutableInfo& info) + : Base(globalData, structure, EvalCode, info) + { + } + + Vector<Identifier> m_variables; + +public: + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(globalData, globalObject, proto, TypeInfo(UnlinkedEvalCodeBlockType, StructureFlags), &s_info); + } + + static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags; + + static const ClassInfo s_info; +}; + +class UnlinkedFunctionCodeBlock : public UnlinkedCodeBlock { +private: + friend class CodeCache; + + static UnlinkedFunctionCodeBlock* create(JSGlobalData* globalData, CodeType codeType, const ExecutableInfo& info) + { + UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell<UnlinkedFunctionCodeBlock>(globalData->heap)) UnlinkedFunctionCodeBlock(globalData, globalData->unlinkedFunctionCodeBlockStructure.get(), codeType, info); + instance->finishCreation(*globalData); + return instance; + } + +public: + typedef UnlinkedCodeBlock Base; + static void destroy(JSCell*); + +private: + UnlinkedFunctionCodeBlock(JSGlobalData* globalData, Structure* structure, CodeType codeType, const ExecutableInfo& info) + : Base(globalData, structure, codeType, info) + { + } + +public: + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(globalData, globalObject, proto, TypeInfo(UnlinkedFunctionCodeBlockType, StructureFlags), &s_info); + } + + static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags; + + static const ClassInfo s_info; +}; + +} + +#endif // UnlinkedCodeBlock_h |