115f88397b7ce64534985edf8746c3f611f36285
[WebKit-https.git] / Source / JavaScriptCore / runtime / ScriptExecutable.h
1 /*
2  * Copyright (C) 2009-2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #pragma once
27
28 #include "ExecutableBase.h"
29
30 namespace JSC {
31
32 class IsoCellSet;
33
34 class ScriptExecutable : public ExecutableBase {
35 public:
36     typedef ExecutableBase Base;
37     static const unsigned StructureFlags = Base::StructureFlags;
38
39     static void destroy(JSCell*);
40         
41     CodeBlockHash hashFor(CodeSpecializationKind) const;
42
43     const SourceCode& source() const { return m_source; }
44     intptr_t sourceID() const { return m_source.providerID(); }
45     const SourceOrigin& sourceOrigin() const { return m_source.provider()->sourceOrigin(); }
46     const String& sourceURL() const { return m_source.provider()->url(); }
47     int firstLine() const { return m_source.firstLine().oneBasedInt(); }
48     int lastLine() const { return m_lastLine; }
49     unsigned startColumn() const { return m_source.startColumn().oneBasedInt(); }
50     unsigned endColumn() const { return m_endColumn; }
51
52     Optional<int> overrideLineNumber(VM&) const;
53     unsigned typeProfilingStartOffset(VM&) const;
54     unsigned typeProfilingEndOffset(VM&) const;
55
56     bool usesEval() const { return m_features & EvalFeature; }
57     bool usesArguments() const { return m_features & ArgumentsFeature; }
58     bool isArrowFunctionContext() const { return m_isArrowFunctionContext; }
59     bool isStrictMode() const { return m_features & StrictModeFeature; }
60     DerivedContextType derivedContextType() const { return static_cast<DerivedContextType>(m_derivedContextType); }
61     EvalContextType evalContextType() const { return static_cast<EvalContextType>(m_evalContextType); }
62
63     ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; }
64         
65     void setNeverInline(bool value) { m_neverInline = value; }
66     void setNeverOptimize(bool value) { m_neverOptimize = value; }
67     void setNeverFTLOptimize(bool value) { m_neverFTLOptimize = value; }
68     void setDidTryToEnterInLoop(bool value) { m_didTryToEnterInLoop = value; }
69     void setCanUseOSRExitFuzzing(bool value) { m_canUseOSRExitFuzzing = value; }
70     bool neverInline() const { return m_neverInline; }
71     bool neverOptimize() const { return m_neverOptimize; }
72     bool neverFTLOptimize() const { return m_neverFTLOptimize; }
73     bool didTryToEnterInLoop() const { return m_didTryToEnterInLoop; }
74     bool isInliningCandidate() const { return !neverInline(); }
75     bool isOkToOptimize() const { return !neverOptimize(); }
76     bool canUseOSRExitFuzzing() const { return m_canUseOSRExitFuzzing; }
77     
78     bool* addressOfDidTryToEnterInLoop() { return &m_didTryToEnterInLoop; }
79
80     CodeFeatures features() const { return m_features; }
81         
82     DECLARE_EXPORT_INFO;
83
84     void recordParse(CodeFeatures features, bool hasCapturedVariables, int lastLine, unsigned endColumn)
85     {
86         m_features = features;
87         m_hasCapturedVariables = hasCapturedVariables;
88         m_lastLine = lastLine;
89         ASSERT(endColumn != UINT_MAX);
90         m_endColumn = endColumn;
91     }
92
93     void installCode(CodeBlock*);
94     void installCode(VM&, CodeBlock*, CodeType, CodeSpecializationKind);
95     CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception);
96     CodeBlock* newReplacementCodeBlockFor(CodeSpecializationKind);
97
98     void clearCode(IsoCellSet&);
99
100     Intrinsic intrinsic() const
101     {
102         return m_intrinsic;
103     }
104
105     static constexpr int NUM_PARAMETERS_NOT_COMPILED = -1;
106
107     bool hasJITCodeForCall() const
108     {
109         return m_numParametersForCall >= 0;
110     }
111     bool hasJITCodeForConstruct() const
112     {
113         return m_numParametersForConstruct >= 0;
114     }
115
116     // This function has an interesting GC story. Callers of this function are asking us to create a CodeBlock
117     // that is not jettisoned before this function returns. Callers are essentially asking for a strong reference
118     // to the CodeBlock. Because the Executable may be allocating the CodeBlock, we require callers to pass in
119     // their CodeBlock*& reference because it's safe for CodeBlock to be jettisoned if Executable is the only thing
120     // to point to it. This forces callers to have a CodeBlock* in a register or on the stack that will be marked
121     // by conservative GC if a GC happens after we create the CodeBlock.
122     template <typename ExecutableType>
123     JSObject* prepareForExecution(VM&, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*& resultCodeBlock);
124
125 private:
126     friend class ExecutableBase;
127     JSObject* prepareForExecutionImpl(VM&, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*&);
128
129     bool hasClearableCode(VM&) const;
130
131 protected:
132     ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isInArrowFunctionContext, EvalContextType, Intrinsic);
133
134     void finishCreation(VM& vm)
135     {
136         Base::finishCreation(vm);
137
138 #if ENABLE(CODEBLOCK_SAMPLING)
139         if (SamplingTool* sampler = vm.interpreter->sampler())
140             sampler->notifyOfScope(vm, this);
141 #endif
142     }
143
144     SourceCode m_source;
145
146     int m_numParametersForCall { NUM_PARAMETERS_NOT_COMPILED };
147     int m_numParametersForConstruct { NUM_PARAMETERS_NOT_COMPILED };
148
149     int m_lastLine { -1 };
150     unsigned m_endColumn { UINT_MAX };
151
152     Intrinsic m_intrinsic { NoIntrinsic };
153     bool m_didTryToEnterInLoop { false };
154     CodeFeatures m_features;
155     bool m_hasCapturedVariables : 1;
156     bool m_neverInline : 1;
157     bool m_neverOptimize : 1;
158     bool m_neverFTLOptimize : 1;
159     bool m_isArrowFunctionContext : 1;
160     bool m_canUseOSRExitFuzzing : 1;
161     unsigned m_derivedContextType : 2; // DerivedContextType
162     unsigned m_evalContextType : 2; // EvalContextType
163 };
164
165 } // namespace JSC