diff options
Diffstat (limited to 'Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h')
-rw-r--r-- | Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h | 282 |
1 files changed, 200 insertions, 82 deletions
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h index 552ed84a2..b9dae2d5c 100644 --- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h +++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Apple Inc. All Rights Reserved. + * 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 @@ -29,9 +29,7 @@ #include "BytecodeConventions.h" #include "CodeSpecializationKind.h" #include "CodeType.h" -#include "ConstructAbility.h" #include "ExpressionRangeInfo.h" -#include "HandlerInfo.h" #include "Identifier.h" #include "JSCell.h" #include "JSString.h" @@ -39,28 +37,27 @@ #include "RegExp.h" #include "SpecialPointer.h" #include "SymbolTable.h" -#include "UnlinkedFunctionExecutable.h" -#include "VariableEnvironment.h" #include "VirtualRegister.h" + +#include <wtf/Compression.h> #include <wtf/RefCountedArray.h> #include <wtf/Vector.h> namespace JSC { class Debugger; -class FunctionMetadataNode; +class FunctionBodyNode; class FunctionExecutable; +class FunctionParameters; class JSScope; -class ParserError; +struct ParserError; class ScriptExecutable; class SourceCode; class SourceProvider; class SymbolTable; class UnlinkedCodeBlock; class UnlinkedFunctionCodeBlock; -class UnlinkedFunctionExecutable; class UnlinkedInstructionStream; -struct ExecutableInfo; typedef unsigned UnlinkedValueProfile; typedef unsigned UnlinkedArrayProfile; @@ -68,6 +65,132 @@ 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, bool isFromGlobalCode = false) + { + UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap)) UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node, isFromGlobalCode); + 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(); } + SymbolTable* 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 unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; } + unsigned unlinkedBodyStartColumn() const { return m_unlinkedBodyStartColumn; } + unsigned unlinkedBodyEndColumn() const { return m_unlinkedBodyEndColumn; } + unsigned startOffset() const { return m_startOffset; } + unsigned sourceLength() { return m_sourceLength; } + + String paramString() const; + + UnlinkedFunctionCodeBlock* codeBlockFor(VM&, 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) + { + m_features = features; + m_hasCapturedVariables = hasCapturedVariables; + } + + 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*, bool isFromGlobalCode); + WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall; + WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct; + + unsigned m_numCapturedVariables : 29; + bool m_forceUsesArguments : 1; + bool m_isInStrictContext : 1; + bool m_hasCapturedVariables : 1; + bool m_isFromGlobalCode : 1; + + Identifier m_name; + Identifier m_inferredName; + WriteBarrier<JSString> m_nameValue; + WriteBarrier<SymbolTable> m_symbolTableForCall; + WriteBarrier<SymbolTable> m_symbolTableForConstruct; + RefPtr<FunctionParameters> m_parameters; + unsigned m_firstLineOffset; + unsigned m_lineCount; + unsigned m_unlinkedFunctionNameStart; + unsigned m_unlinkedBodyStartColumn; + unsigned m_unlinkedBodyEndColumn; + 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), info()); + } + + static const unsigned StructureFlags = OverridesVisitChildren | JSCell::StructureFlags; + + DECLARE_EXPORT_INFO; +}; + struct UnlinkedStringJumpTable { typedef HashMap<RefPtr<StringImpl>, int32_t> StringOffsetTable; StringOffsetTable offsetTable; @@ -95,6 +218,13 @@ struct UnlinkedSimpleJumpTable { } }; +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; } @@ -109,9 +239,8 @@ struct UnlinkedInstruction { class UnlinkedCodeBlock : public JSCell { public: typedef JSCell Base; - static const unsigned StructureFlags = Base::StructureFlags; - static const bool needsDestruction = true; + static const bool hasImmortalStructure = true; enum { CallFunction, ApplyFunction }; @@ -120,18 +249,21 @@ public: 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); - void addTypeProfilerExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot); - bool hasExpressionInfo() { return m_expressionInfo.size(); } // Special registers void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; } - void setScopeRegister(VirtualRegister scopeRegister) { m_scopeRegister = scopeRegister; } - void setActivationRegister(VirtualRegister activationRegister) { m_lexicalEnvironmentRegister = activationRegister; } + void setActivationRegister(VirtualRegister activationRegister) { m_activationRegister = activationRegister; } + + void setArgumentsRegister(VirtualRegister argumentsRegister) { m_argumentsRegister = argumentsRegister; } + bool usesArguments() const { return m_argumentsRegister.isValid(); } + VirtualRegister argumentsRegister() const { return m_argumentsRegister; } + bool usesGlobalObject() const { return m_globalObjectRegister.isValid(); } void setGlobalObjectRegister(VirtualRegister globalObjectRegister) { m_globalObjectRegister = globalObjectRegister; } @@ -164,35 +296,19 @@ public: const Identifier& identifier(int index) const { return m_identifiers[index]; } const Vector<Identifier>& identifiers() const { return m_identifiers; } - unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other) + 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); - m_constantsSourceCodeRepresentation.append(sourceCodeRepresentation); - return result; - } - unsigned addConstant(LinkTimeConstant type) - { - unsigned result = m_constantRegisters.size(); - ASSERT(result); - unsigned index = static_cast<unsigned>(type); - ASSERT(index < LinkTimeConstantCount); - m_linkTimeConstants[index] = result; - m_constantRegisters.append(WriteBarrier<Unknown>()); - m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other); return result; } - unsigned registerIndexForLinkTimeConstant(LinkTimeConstant type) - { - unsigned index = static_cast<unsigned>(type); - ASSERT(index < LinkTimeConstantCount); - return m_linkTimeConstants[index]; - } + 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; } - const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation() { return m_constantsSourceCodeRepresentation; } + ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); } // Jumps size_t numberOfJumpTargets() const { return m_jumpTargets.size(); } @@ -200,16 +316,14 @@ public: unsigned jumpTarget(int index) const { return m_jumpTargets[index]; } unsigned lastJumpTarget() const { return m_jumpTargets.last(); } - bool isBuiltinFunction() const { return m_isBuiltinFunction; } - - ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); } + 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_constantsSourceCodeRepresentation.shrinkToFit(); m_functionDecls.shrinkToFit(); m_functionExprs.shrinkToFit(); m_propertyAccessInstructions.shrinkToFit(); @@ -266,9 +380,11 @@ public: // Exception handling support size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; } - void addExceptionHandler(const UnlinkedHandlerInfo& handler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(handler); } + 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]; } + SymbolTable* symbolTable() const { return m_symbolTable.get(); } + VM* vm() const { return m_vm; } UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; } @@ -286,9 +402,8 @@ public: CodeType codeType() const { return m_codeType; } VirtualRegister thisRegister() const { return m_thisRegister; } - VirtualRegister scopeRegister() const { return m_scopeRegister; } - VirtualRegister activationRegister() const { return m_lexicalEnvironmentRegister; } - bool hasActivationRegister() const { return m_lexicalEnvironmentRegister.isValid(); } + VirtualRegister activationRegister() const { return m_activationRegister; } + void addPropertyAccessInstruction(unsigned propertyAccessInstruction) { @@ -321,15 +436,13 @@ public: return m_rareData->m_constantBuffers[index]; } - bool hasRareData() const { return m_rareData.get(); } + bool hasRareData() const { return m_rareData; } int lineNumberForBytecodeOffset(unsigned bytecodeOffset); void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column); - bool typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot); - void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount, unsigned endColumn) { m_features = features; @@ -347,9 +460,6 @@ public: ALWAYS_INLINE unsigned startColumn() const { return 0; } unsigned endColumn() const { return m_endColumn; } - void addOpProfileControlFlowBytecodeOffset(size_t offset) { m_opProfileControlFlowBytecodeOffsets.append(offset); } - const Vector<size_t>& opProfileControlFlowBytecodeOffsets() const { return m_opProfileControlFlowBytecodeOffsets; } - void dumpExpressionRangeInfo(); // For debugging purpose only. protected: @@ -369,7 +479,7 @@ private: void createRareDataIfNecessary() { if (!m_rareData) - m_rareData = std::make_unique<RareData>(); + m_rareData = adoptPtr(new RareData); } void getLineAndColumn(ExpressionRangeInfo&, unsigned& line, unsigned& column); @@ -380,18 +490,16 @@ private: VM* m_vm; VirtualRegister m_thisRegister; - VirtualRegister m_scopeRegister; - VirtualRegister m_lexicalEnvironmentRegister; + VirtualRegister m_argumentsRegister; + VirtualRegister m_activationRegister; VirtualRegister m_globalObjectRegister; - unsigned m_needsFullScopeChain : 1; - unsigned m_usesEval : 1; - unsigned m_isStrictMode : 1; - unsigned m_isConstructor : 1; - unsigned m_hasCapturedVariables : 1; - unsigned m_isBuiltinFunction : 1; - unsigned m_constructorKind : 2; - + 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; unsigned m_endColumn; @@ -404,8 +512,6 @@ private: // Constant Pools Vector<Identifier> m_identifiers; Vector<WriteBarrier<Unknown>> m_constantRegisters; - Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation; - std::array<unsigned, LinkTimeConstantCount> m_linkTimeConstants; typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector; FunctionExpressionVector m_functionDecls; FunctionExpressionVector m_functionExprs; @@ -445,16 +551,12 @@ public: }; private: - std::unique_ptr<RareData> m_rareData; + OwnPtr<RareData> m_rareData; Vector<ExpressionRangeInfo> m_expressionInfo; - struct TypeProfilerExpressionRange { - unsigned m_startDivot; - unsigned m_endDivot; - }; - HashMap<unsigned, TypeProfilerExpressionRange> m_typeProfilerInfoMap; - Vector<size_t> m_opProfileControlFlowBytecodeOffsets; protected: + + static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags; static void visitChildren(JSCell*, SlotVisitor&); public: @@ -471,10 +573,12 @@ protected: { } + static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags; + DECLARE_INFO; }; -class UnlinkedProgramCodeBlock final : public UnlinkedGlobalCodeBlock { +class UnlinkedProgramCodeBlock : public UnlinkedGlobalCodeBlock { private: friend class CodeCache; static UnlinkedProgramCodeBlock* create(VM* vm, const ExecutableInfo& info) @@ -486,12 +590,23 @@ private: public: typedef UnlinkedGlobalCodeBlock Base; - static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; - static void destroy(JSCell*); - void setVariableDeclarations(const VariableEnvironment& environment) { m_varDeclarations = environment; } - const VariableEnvironment& variableDeclarations() const { return m_varDeclarations; } + 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&); @@ -501,7 +616,8 @@ private: { } - VariableEnvironment m_varDeclarations; + VariableDeclations m_varDeclarations; + FunctionDeclations m_functionDeclarations; public: static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) @@ -509,10 +625,12 @@ public: return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedProgramCodeBlockType, StructureFlags), info()); } + static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags; + DECLARE_INFO; }; -class UnlinkedEvalCodeBlock final : public UnlinkedGlobalCodeBlock { +class UnlinkedEvalCodeBlock : public UnlinkedGlobalCodeBlock { private: friend class CodeCache; @@ -525,8 +643,6 @@ private: public: typedef UnlinkedGlobalCodeBlock Base; - static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; - static void destroy(JSCell*); const Identifier& variable(unsigned index) { return m_variables[index]; } @@ -551,14 +667,13 @@ public: return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedEvalCodeBlockType, StructureFlags), info()); } + static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags; + DECLARE_INFO; }; -class UnlinkedFunctionCodeBlock final : public UnlinkedCodeBlock { +class UnlinkedFunctionCodeBlock : public UnlinkedCodeBlock { public: - typedef UnlinkedCodeBlock Base; - static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; - 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); @@ -566,6 +681,7 @@ public: return instance; } + typedef UnlinkedCodeBlock Base; static void destroy(JSCell*); private: @@ -580,6 +696,8 @@ public: return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionCodeBlockType, StructureFlags), info()); } + static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags; + DECLARE_INFO; }; |