1/*
2 * Copyright (C) 2011-2015 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 "CodeBlock.h"
29#include "DFGCommon.h"
30#include "Options.h"
31
32namespace JSC { namespace DFG {
33
34#if ENABLE(DFG_JIT)
35// Fast check functions; if they return true it is still necessary to
36// check opcodes.
37bool isSupported();
38bool isSupportedForInlining(CodeBlock*);
39bool mightCompileEval(CodeBlock*);
40bool mightCompileProgram(CodeBlock*);
41bool mightCompileFunctionForCall(CodeBlock*);
42bool mightCompileFunctionForConstruct(CodeBlock*);
43bool mightInlineFunctionForCall(CodeBlock*);
44bool mightInlineFunctionForClosureCall(CodeBlock*);
45bool mightInlineFunctionForConstruct(CodeBlock*);
46bool canUseOSRExitFuzzing(CodeBlock*);
47
48inline CapabilityLevel capabilityLevel(OpcodeID, CodeBlock*, const Instruction* pc);
49
50CapabilityLevel capabilityLevel(CodeBlock*);
51#else // ENABLE(DFG_JIT)
52inline bool mightCompileEval(CodeBlock*) { return false; }
53inline bool mightCompileProgram(CodeBlock*) { return false; }
54inline bool mightCompileFunctionForCall(CodeBlock*) { return false; }
55inline bool mightCompileFunctionForConstruct(CodeBlock*) { return false; }
56inline bool mightInlineFunctionForCall(CodeBlock*) { return false; }
57inline bool mightInlineFunctionForClosureCall(CodeBlock*) { return false; }
58inline bool mightInlineFunctionForConstruct(CodeBlock*) { return false; }
59inline bool canUseOSRExitFuzzing(CodeBlock*) { return false; }
60
61inline CapabilityLevel capabilityLevel(OpcodeID, CodeBlock*, const Instruction*) { return CannotCompile; }
62inline CapabilityLevel capabilityLevel(CodeBlock*) { return CannotCompile; }
63#endif // ENABLE(DFG_JIT)
64
65inline CapabilityLevel evalCapabilityLevel(CodeBlock* codeBlock)
66{
67 if (!mightCompileEval(codeBlock))
68 return CannotCompile;
69
70 return capabilityLevel(codeBlock);
71}
72
73inline CapabilityLevel programCapabilityLevel(CodeBlock* codeBlock)
74{
75 if (!mightCompileProgram(codeBlock))
76 return CannotCompile;
77
78 return capabilityLevel(codeBlock);
79}
80
81inline CapabilityLevel functionCapabilityLevel(bool mightCompile, bool mightInline, CapabilityLevel computedCapabilityLevel)
82{
83 if (mightCompile && mightInline)
84 return leastUpperBound(CanCompileAndInline, computedCapabilityLevel);
85 if (mightCompile && !mightInline)
86 return leastUpperBound(CanCompile, computedCapabilityLevel);
87 if (!mightCompile)
88 return CannotCompile;
89 RELEASE_ASSERT_NOT_REACHED();
90 return CannotCompile;
91}
92
93inline CapabilityLevel functionForCallCapabilityLevel(CodeBlock* codeBlock)
94{
95 return functionCapabilityLevel(
96 mightCompileFunctionForCall(codeBlock),
97 mightInlineFunctionForCall(codeBlock),
98 capabilityLevel(codeBlock));
99}
100
101inline CapabilityLevel functionForConstructCapabilityLevel(CodeBlock* codeBlock)
102{
103 return functionCapabilityLevel(
104 mightCompileFunctionForConstruct(codeBlock),
105 mightInlineFunctionForConstruct(codeBlock),
106 capabilityLevel(codeBlock));
107}
108
109inline CapabilityLevel inlineFunctionForCallCapabilityLevel(CodeBlock* codeBlock)
110{
111 if (!mightInlineFunctionForCall(codeBlock))
112 return CannotCompile;
113
114 return capabilityLevel(codeBlock);
115}
116
117inline CapabilityLevel inlineFunctionForClosureCallCapabilityLevel(CodeBlock* codeBlock)
118{
119 if (!mightInlineFunctionForClosureCall(codeBlock))
120 return CannotCompile;
121
122 return capabilityLevel(codeBlock);
123}
124
125inline CapabilityLevel inlineFunctionForConstructCapabilityLevel(CodeBlock* codeBlock)
126{
127 if (!mightInlineFunctionForConstruct(codeBlock))
128 return CannotCompile;
129
130 return capabilityLevel(codeBlock);
131}
132
133inline bool mightInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
134{
135 if (kind == CodeForCall)
136 return mightInlineFunctionForCall(codeBlock);
137 ASSERT(kind == CodeForConstruct);
138 return mightInlineFunctionForConstruct(codeBlock);
139}
140
141inline bool mightCompileFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
142{
143 if (kind == CodeForCall)
144 return mightCompileFunctionForCall(codeBlock);
145 ASSERT(kind == CodeForConstruct);
146 return mightCompileFunctionForConstruct(codeBlock);
147}
148
149inline bool mightInlineFunction(CodeBlock* codeBlock)
150{
151 return mightInlineFunctionFor(codeBlock, codeBlock->specializationKind());
152}
153
154inline CapabilityLevel inlineFunctionForCapabilityLevel(CodeBlock* codeBlock, CodeSpecializationKind kind, bool isClosureCall)
155{
156 if (isClosureCall) {
157 if (kind != CodeForCall)
158 return CannotCompile;
159 return inlineFunctionForClosureCallCapabilityLevel(codeBlock);
160 }
161 if (kind == CodeForCall)
162 return inlineFunctionForCallCapabilityLevel(codeBlock);
163 ASSERT(kind == CodeForConstruct);
164 return inlineFunctionForConstructCapabilityLevel(codeBlock);
165}
166
167inline bool isSmallEnoughToInlineCodeInto(CodeBlock* codeBlock)
168{
169 return codeBlock->bytecodeCost() <= Options::maximumInliningCallerBytecodeCost();
170}
171
172} } // namespace JSC::DFG
173