diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
commit | 41386e9cb918eed93b3f13648cbef387e371e451 (patch) | |
tree | a97f9d7bd1d9d091833286085f72da9d83fd0606 /Source/JavaScriptCore/runtime/Executable.h | |
parent | e15dd966d523731101f70ccf768bba12435a0208 (diff) | |
download | WebKitGtk-tarball-41386e9cb918eed93b3f13648cbef387e371e451.tar.gz |
webkitgtk-2.4.9webkitgtk-2.4.9
Diffstat (limited to 'Source/JavaScriptCore/runtime/Executable.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/Executable.h | 328 |
1 files changed, 144 insertions, 184 deletions
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h index bce2428cb..6ff27aee9 100644 --- a/Source/JavaScriptCore/runtime/Executable.h +++ b/Source/JavaScriptCore/runtime/Executable.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2010, 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2010, 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 @@ -26,23 +26,20 @@ #ifndef Executable_h #define Executable_h -#include "ArityCheckMode.h" #include "CallData.h" #include "CodeBlockHash.h" #include "CodeSpecializationKind.h" #include "CompilationResult.h" #include "DFGPlan.h" -#include "ExecutableInfo.h" #include "HandlerInfo.h" -#include "InferredValue.h" +#include "JSFunction.h" +#include "Interpreter.h" #include "JITCode.h" #include "JSGlobalObject.h" -#include "RegisterPreservationMode.h" #include "SamplingTool.h" #include "SourceCode.h" -#include "TypeSet.h" #include "UnlinkedCodeBlock.h" -#include "UnlinkedFunctionExecutable.h" +#include <wtf/PassOwnPtr.h> namespace JSC { @@ -64,7 +61,8 @@ inline bool isCall(CodeSpecializationKind kind) return false; } -class ExecutableBase : public JSCell { +class ExecutableBase : public JSCell, public DoublyLinkedListNode<ExecutableBase> { + friend class WTF::DoublyLinkedListNode<ExecutableBase>; friend class JIT; protected: @@ -85,24 +83,26 @@ protected: public: typedef JSCell Base; - static const unsigned StructureFlags = Base::StructureFlags; +#if ENABLE(JIT) static const bool needsDestruction = true; + static const bool hasImmortalStructure = true; static void destroy(JSCell*); +#endif CodeBlockHash hashFor(CodeSpecializationKind) const; bool isEvalExecutable() { - return type() == EvalExecutableType; + return structure()->typeInfo().type() == EvalExecutableType; } bool isFunctionExecutable() { - return type() == FunctionExecutableType; + return structure()->typeInfo().type() == FunctionExecutableType; } bool isProgramExecutable() { - return type() == ProgramExecutableType; + return structure()->typeInfo().type() == ProgramExecutableType; } bool isHostFunction() const @@ -111,13 +111,14 @@ public: return m_numParametersForCall == NUM_PARAMETERS_IS_HOST; } - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); } + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CompoundType, StructureFlags), info()); } void clearCode(); DECLARE_EXPORT_INFO; protected: + static const unsigned StructureFlags = 0; int m_numParametersForCall; int m_numParametersForConstruct; @@ -143,94 +144,37 @@ public: ASSERT(kind == CodeForConstruct); return generatedJITCodeForConstruct(); } - - MacroAssemblerCodePtr entrypointFor( - VM& vm, CodeSpecializationKind kind, ArityCheckMode arity, RegisterPreservationMode registers) - { - // Check if we have a cached result. We only have it for arity check because we use the - // no-arity entrypoint in non-virtual calls, which will "cache" this value directly in - // machine code. - if (arity == MustCheckArity) { - switch (kind) { - case CodeForCall: - switch (registers) { - case RegisterPreservationNotRequired: - if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheck) - return result; - break; - case MustPreserveRegisters: - if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheckAndPreserveRegs) - return result; - break; - } - break; - case CodeForConstruct: - switch (registers) { - case RegisterPreservationNotRequired: - if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheck) - return result; - break; - case MustPreserveRegisters: - if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheckAndPreserveRegs) - return result; - break; - } - break; - } - } - MacroAssemblerCodePtr result = - generatedJITCodeFor(kind)->addressForCall(vm, this, arity, registers); - if (arity == MustCheckArity) { - // Cache the result; this is necessary for the JIT's virtual call optimizations. - switch (kind) { - case CodeForCall: - switch (registers) { - case RegisterPreservationNotRequired: - m_jitCodeForCallWithArityCheck = result; - break; - case MustPreserveRegisters: - m_jitCodeForCallWithArityCheckAndPreserveRegs = result; - break; - } - break; - case CodeForConstruct: - switch (registers) { - case RegisterPreservationNotRequired: - m_jitCodeForConstructWithArityCheck = result; - break; - case MustPreserveRegisters: - m_jitCodeForConstructWithArityCheckAndPreserveRegs = result; - break; - } - break; - } - } - return result; - } - - static ptrdiff_t offsetOfJITCodeWithArityCheckFor( - CodeSpecializationKind kind, RegisterPreservationMode registers) - { - switch (kind) { - case CodeForCall: - switch (registers) { - case RegisterPreservationNotRequired: - return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck); - case MustPreserveRegisters: - return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheckAndPreserveRegs); - } - case CodeForConstruct: - switch (registers) { - case RegisterPreservationNotRequired: - return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck); - case MustPreserveRegisters: - return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheckAndPreserveRegs); - } - } - RELEASE_ASSERT_NOT_REACHED(); - return 0; + + MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck() + { + ASSERT(m_jitCodeForCall); + ASSERT(m_jitCodeForCallWithArityCheck); + return m_jitCodeForCallWithArityCheck; } - + + MacroAssemblerCodePtr generatedJITCodeForConstructWithArityCheck() + { + ASSERT(m_jitCodeForConstruct); + ASSERT(m_jitCodeForConstructWithArityCheck); + return m_jitCodeForConstructWithArityCheck; + } + + MacroAssemblerCodePtr generatedJITCodeWithArityCheckFor(CodeSpecializationKind kind) + { + if (kind == CodeForCall) + return generatedJITCodeForCallWithArityCheck(); + ASSERT(kind == CodeForConstruct); + return generatedJITCodeForConstructWithArityCheck(); + } + + static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind) + { + if (kind == CodeForCall) + return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck); + ASSERT(kind == CodeForConstruct); + return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck); + } + static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind) { if (kind == CodeForCall) @@ -266,34 +210,52 @@ public: return intrinsic(); return NoIntrinsic; } - - void dump(PrintStream&) const; + MacroAssemblerCodePtr hostCodeEntryFor(CodeSpecializationKind kind) + { + return generatedJITCodeFor(kind)->addressForCall(); + } + + MacroAssemblerCodePtr jsCodeEntryFor(CodeSpecializationKind kind) + { + return generatedJITCodeFor(kind)->addressForCall(); + } + + MacroAssemblerCodePtr jsCodeWithArityCheckEntryFor(CodeSpecializationKind kind) + { + return generatedJITCodeWithArityCheckFor(kind); + } + protected: + ExecutableBase* m_prev; + ExecutableBase* m_next; + RefPtr<JITCode> m_jitCodeForCall; RefPtr<JITCode> m_jitCodeForConstruct; MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck; MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck; - MacroAssemblerCodePtr m_jitCodeForCallWithArityCheckAndPreserveRegs; - MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheckAndPreserveRegs; }; -class NativeExecutable final : public ExecutableBase { +class NativeExecutable : public ExecutableBase { friend class JIT; friend class LLIntOffsetsExtractor; public: typedef ExecutableBase Base; - static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; - static NativeExecutable* create(VM& vm, PassRefPtr<JITCode> callThunk, NativeFunction function, PassRefPtr<JITCode> constructThunk, NativeFunction constructor, Intrinsic intrinsic) + static NativeExecutable* create(VM& vm, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic) { NativeExecutable* executable; executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor); - executable->finishCreation(vm, callThunk, constructThunk, intrinsic); + if (!callThunk) + executable->finishCreation(vm, 0, 0, intrinsic); + else + executable->finishCreation(vm, JITCode::hostFunction(callThunk), JITCode::hostFunction(constructThunk), intrinsic); return executable; } +#if ENABLE(JIT) static void destroy(JSCell*); +#endif CodeBlockHash hashFor(CodeSpecializationKind) const; @@ -316,7 +278,7 @@ public: return OBJECT_OFFSETOF(NativeExecutable, m_constructor); } - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); } + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(LeafType, StructureFlags), info()); } DECLARE_INFO; @@ -326,6 +288,8 @@ protected: void finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, Intrinsic intrinsic) { Base::finishCreation(vm); + m_jitCodeForCallWithArityCheck = callThunk ? callThunk->addressForCall() : MacroAssemblerCodePtr(); + m_jitCodeForConstructWithArityCheck = constructThunk ? constructThunk->addressForCall() : MacroAssemblerCodePtr(); m_jitCodeForCall = callThunk; m_jitCodeForConstruct = constructThunk; m_intrinsic = intrinsic; @@ -348,24 +312,40 @@ private: class ScriptExecutable : public ExecutableBase { public: typedef ExecutableBase Base; - static const unsigned StructureFlags = Base::StructureFlags; + ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext) + : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED) + , m_source(source) + , m_features(isInStrictContext ? StrictModeFeature : 0) + , m_neverInline(false) + , m_startColumn(UINT_MAX) + , m_endColumn(UINT_MAX) + { + } + + ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext) + : ExecutableBase(exec->vm(), structure, NUM_PARAMETERS_NOT_COMPILED) + , m_source(source) + , m_features(isInStrictContext ? StrictModeFeature : 0) + , m_neverInline(false) + , m_startColumn(UINT_MAX) + , m_endColumn(UINT_MAX) + { + } + +#if ENABLE(JIT) static void destroy(JSCell*); +#endif CodeBlockHash hashFor(CodeSpecializationKind) const; const SourceCode& source() const { return m_source; } intptr_t sourceID() const { return m_source.providerID(); } const String& sourceURL() const { return m_source.provider()->url(); } - int firstLine() const { return m_firstLine; } - void setOverrideLineNumber(int overrideLineNumber) { m_overrideLineNumber = overrideLineNumber; } - bool hasOverrideLineNumber() const { return m_overrideLineNumber != -1; } - int overrideLineNumber() const { return m_overrideLineNumber; } + int lineNo() const { return m_firstLine; } int lastLine() const { return m_lastLine; } unsigned startColumn() const { return m_startColumn; } unsigned endColumn() const { return m_endColumn; } - unsigned typeProfilingStartOffset() const { return m_typeProfilingStartOffset; } - unsigned typeProfilingEndOffset() const { return m_typeProfilingEndOffset; } bool usesEval() const { return m_features & EvalFeature; } bool usesArguments() const { return m_features & ArgumentsFeature; } @@ -374,12 +354,8 @@ public: ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; } void setNeverInline(bool value) { m_neverInline = value; } - void setDidTryToEnterInLoop(bool value) { m_didTryToEnterInLoop = value; } bool neverInline() const { return m_neverInline; } - bool didTryToEnterInLoop() const { return m_didTryToEnterInLoop; } bool isInliningCandidate() const { return !neverInline(); } - - bool* addressOfDidTryToEnterInLoop() { return &m_didTryToEnterInLoop; } void unlinkCalls(); @@ -400,24 +376,20 @@ public: } void installCode(CodeBlock*); - RefPtr<CodeBlock> newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception); + PassRefPtr<CodeBlock> newCodeBlockFor(CodeSpecializationKind, JSScope*, JSObject*& exception); PassRefPtr<CodeBlock> newReplacementCodeBlockFor(CodeSpecializationKind); - JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind) + JSObject* prepareForExecution(ExecState* exec, JSScope* scope, CodeSpecializationKind kind) { if (hasJITCodeFor(kind)) return 0; - return prepareForExecutionImpl(exec, function, scope, kind); + return prepareForExecutionImpl(exec, scope, kind); } - template <typename Functor> void forEachCodeBlock(Functor&&); - private: - JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind); + JSObject* prepareForExecutionImpl(ExecState*, JSScope*, CodeSpecializationKind); protected: - ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext); - void finishCreation(VM& vm) { Base::finishCreation(vm); @@ -433,21 +405,16 @@ protected: CodeFeatures m_features; bool m_hasCapturedVariables; bool m_neverInline; - bool m_didTryToEnterInLoop; - int m_overrideLineNumber; int m_firstLine; int m_lastLine; unsigned m_startColumn; unsigned m_endColumn; - unsigned m_typeProfilingStartOffset; - unsigned m_typeProfilingEndOffset; }; -class EvalExecutable final : public ScriptExecutable { +class EvalExecutable : public ScriptExecutable { friend class LLIntOffsetsExtractor; public: typedef ScriptExecutable Base; - static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; static void destroy(JSCell*); @@ -456,7 +423,7 @@ public: return m_evalCodeBlock.get(); } - static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, ThisTDZMode, const VariableEnvironment*); + static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext); PassRefPtr<JITCode> generatedJITCode() { @@ -474,13 +441,14 @@ public: void clearCode(); - ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None); } + ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); } unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); } unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); } private: friend class ScriptExecutable; + static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags; EvalExecutable(ExecState*, const SourceCode&, bool); static void visitChildren(JSCell*, SlotVisitor&); @@ -489,11 +457,10 @@ private: WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock; }; -class ProgramExecutable final : public ScriptExecutable { +class ProgramExecutable : public ScriptExecutable { friend class LLIntOffsetsExtractor; public: typedef ScriptExecutable Base; - static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; static ProgramExecutable* create(ExecState* exec, const SourceCode& source) { @@ -530,10 +497,12 @@ public: void clearCode(); - ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None); } + ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); } private: friend class ScriptExecutable; + + static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags; ProgramExecutable(ExecState*, const SourceCode&); @@ -543,24 +512,19 @@ private: RefPtr<ProgramCodeBlock> m_programCodeBlock; }; -class FunctionExecutable final : public ScriptExecutable { +class FunctionExecutable : public ScriptExecutable { friend class JIT; friend class LLIntOffsetsExtractor; public: typedef ScriptExecutable Base; - static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; - static FunctionExecutable* create( - VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, - unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn) + static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces = true) { - FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn); + FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn, bodyIncludesBraces); executable->finishCreation(vm); return executable; } - static FunctionExecutable* fromGlobalCode( - const Identifier& name, ExecState&, const SourceCode&, - JSObject*& exception, int overrideLineNumber); + static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception); static void destroy(JSCell*); @@ -621,68 +585,64 @@ public: { return baselineCodeBlockFor(kind); } - - RefPtr<TypeSet> returnStatementTypeSet() - { - if (!m_returnStatementTypeSet) - m_returnStatementTypeSet = TypeSet::create(); - - return m_returnStatementTypeSet; - } - FunctionMode functionMode() { return m_unlinkedExecutable->functionMode(); } - bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); } - ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); } - bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); } const Identifier& name() { return m_unlinkedExecutable->name(); } const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); } JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); } size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'! + String paramString() const; + SymbolTable* symbolTable(CodeSpecializationKind); - void clearUnlinkedCodeForRecompilation(); + void clearCodeIfNotCompiling(); + void clearUnlinkedCodeForRecompilationIfNotCompiling(); static void visitChildren(JSCell*, SlotVisitor&); static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), info()); } - - unsigned parametersStartOffset() const { return m_parametersStartOffset; } - - void overrideParameterAndTypeProfilingStartEndOffsets(unsigned parametersStartOffset, unsigned typeProfilingStartOffset, unsigned typeProfilingEndOffset) - { - m_parametersStartOffset = parametersStartOffset; - m_typeProfilingStartOffset = typeProfilingStartOffset; - m_typeProfilingEndOffset = typeProfilingEndOffset; - } - + DECLARE_INFO; void unlinkCalls(); void clearCode(); - - InferredValue* singletonFunction() { return m_singletonFunction.get(); } + + bool bodyIncludesBraces() const { return m_bodyIncludesBraces; } private: - FunctionExecutable( - VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, - unsigned lastLine, unsigned startColumn, unsigned endColumn); - - void finishCreation(VM&); + FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces); + + bool isCompiling() + { +#if ENABLE(JIT) + if (!m_jitCodeForCall && m_codeBlockForCall) + return true; + if (!m_jitCodeForConstruct && m_codeBlockForConstruct) + return true; +#endif + return false; + } friend class ScriptExecutable; - + + static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags; WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable; RefPtr<FunctionCodeBlock> m_codeBlockForCall; RefPtr<FunctionCodeBlock> m_codeBlockForConstruct; - RefPtr<TypeSet> m_returnStatementTypeSet; - unsigned m_parametersStartOffset; - WriteBarrier<InferredValue> m_singletonFunction; + bool m_bodyIncludesBraces; }; +inline bool isHostFunction(JSValue value, NativeFunction nativeFunction) +{ + JSFunction* function = jsCast<JSFunction*>(getJSFunction(value)); + if (!function || !function->isHostFunction()) + return false; + return function->nativeFunction() == nativeFunction; +} + inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable) { - switch (executable->type()) { + switch (executable->structure()->typeInfo().type()) { case EvalExecutableType: return jsCast<EvalExecutable*>(executable)->clearCode(); case ProgramExecutableType: @@ -696,7 +656,7 @@ inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable) inline void ScriptExecutable::unlinkCalls() { - switch (type()) { + switch (structure()->typeInfo().type()) { case EvalExecutableType: return jsCast<EvalExecutable*>(this)->unlinkCalls(); case ProgramExecutableType: |