blob: 7b6b1fd07c080d60dc5d50cffa3ac9966f32984f [file] [log] [blame]
/*
* 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 "Weak.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 UnlinkedArrayAllocationProfile;
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 functionStartOffset() const { return m_functionStartOffset; }
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 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(JSGlobalData*, Structure*, const SourceCode&, FunctionBodyNode*);
Weak<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
Weak<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_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;
DECLARE_CLASSINFO();
};
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; }
UnlinkedArrayAllocationProfile addArrayAllocationProfile() { return m_arrayAllocationProfileCount++; }
unsigned numberOfArrayAllocationProfiles() { return m_arrayAllocationProfileCount; }
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_arrayAllocationProfileCount;
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:
DECLARE_CLASSINFO();
};
class UnlinkedGlobalCodeBlock : public UnlinkedCodeBlock {
public:
typedef UnlinkedCodeBlock Base;
DECLARE_CLASSINFO();
protected:
UnlinkedGlobalCodeBlock(JSGlobalData* globalData, Structure* structure, CodeType codeType, const ExecutableInfo& info)
: Base(globalData, structure, codeType, info)
{
}
static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
};
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;
DECLARE_CLASSINFO();
};
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;
DECLARE_CLASSINFO();
};
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;
DECLARE_CLASSINFO();
};
}
#endif // UnlinkedCodeBlock_h