1/*
2 * Copyright (C) 2009-2019 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
30namespace JSC {
31
32class IsoCellSet;
33
34class ScriptExecutable : public ExecutableBase {
35public:
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 JS_EXPORT_PRIVATE int lastLine() const;
49 unsigned startColumn() const { return m_source.startColumn().oneBasedInt(); }
50 JS_EXPORT_PRIVATE unsigned endColumn() const;
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, bool hasCapturedVariables, int lastLine, unsigned endColumn);
85 void installCode(CodeBlock*);
86 void installCode(VM&, CodeBlock*, CodeType, CodeSpecializationKind);
87 CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, Exception*&);
88 CodeBlock* newReplacementCodeBlockFor(CodeSpecializationKind);
89
90 void clearCode(IsoCellSet&);
91
92 Intrinsic intrinsic() const
93 {
94 return m_intrinsic;
95 }
96
97 bool hasJITCodeForCall() const
98 {
99 return m_jitCodeForCall;
100 }
101 bool hasJITCodeForConstruct() const
102 {
103 return m_jitCodeForConstruct;
104 }
105
106 // This function has an interesting GC story. Callers of this function are asking us to create a CodeBlock
107 // that is not jettisoned before this function returns. Callers are essentially asking for a strong reference
108 // to the CodeBlock. Because the Executable may be allocating the CodeBlock, we require callers to pass in
109 // their CodeBlock*& reference because it's safe for CodeBlock to be jettisoned if Executable is the only thing
110 // to point to it. This forces callers to have a CodeBlock* in a register or on the stack that will be marked
111 // by conservative GC if a GC happens after we create the CodeBlock.
112 template <typename ExecutableType>
113 Exception* prepareForExecution(VM&, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*& resultCodeBlock);
114
115private:
116 friend class ExecutableBase;
117 Exception* prepareForExecutionImpl(VM&, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*&);
118
119 bool hasClearableCode(VM&) const;
120
121protected:
122 ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isInArrowFunctionContext, EvalContextType, Intrinsic);
123
124 void finishCreation(VM& vm)
125 {
126 Base::finishCreation(vm);
127
128#if ENABLE(CODEBLOCK_SAMPLING)
129 if (SamplingTool* sampler = vm.interpreter->sampler())
130 sampler->notifyOfScope(vm, this);
131#endif
132 }
133
134 void recordParse(CodeFeatures features, bool hasCapturedVariables)
135 {
136 m_features = features;
137 m_hasCapturedVariables = hasCapturedVariables;
138 }
139
140 SourceCode m_source;
141 Intrinsic m_intrinsic { NoIntrinsic };
142 bool m_didTryToEnterInLoop { false };
143 CodeFeatures m_features;
144 bool m_hasCapturedVariables : 1;
145 bool m_neverInline : 1;
146 bool m_neverOptimize : 1;
147 bool m_neverFTLOptimize : 1;
148 bool m_isArrowFunctionContext : 1;
149 bool m_canUseOSRExitFuzzing : 1;
150 unsigned m_derivedContextType : 2; // DerivedContextType
151 unsigned m_evalContextType : 2; // EvalContextType
152};
153
154} // namespace JSC
155