1/*
2 * Copyright (C) 2013-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#include "config.h"
27#include "TestRunnerUtils.h"
28
29#include "CodeBlock.h"
30#include "FunctionCodeBlock.h"
31#include "JSCInlines.h"
32#include "LLIntData.h"
33
34namespace JSC {
35
36FunctionExecutable* getExecutableForFunction(JSValue theFunctionValue)
37{
38 if (!theFunctionValue.isCell())
39 return nullptr;
40
41 VM& vm = theFunctionValue.asCell()->vm();
42 JSFunction* theFunction = jsDynamicCast<JSFunction*>(vm, theFunctionValue);
43 if (!theFunction)
44 return nullptr;
45
46 FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(vm,
47 theFunction->executable());
48 return executable;
49}
50
51CodeBlock* getSomeBaselineCodeBlockForFunction(JSValue theFunctionValue)
52{
53 FunctionExecutable* executable = getExecutableForFunction(theFunctionValue);
54 if (!executable)
55 return 0;
56
57 CodeBlock* baselineCodeBlock = executable->baselineCodeBlockFor(CodeForCall);
58
59 if (!baselineCodeBlock)
60 baselineCodeBlock = executable->baselineCodeBlockFor(CodeForConstruct);
61
62 return baselineCodeBlock;
63}
64
65JSValue numberOfDFGCompiles(JSValue theFunctionValue)
66{
67 bool pretendToHaveManyCompiles = false;
68#if ENABLE(DFG_JIT)
69 if (!Options::useJIT() || !Options::useDFGJIT())
70 pretendToHaveManyCompiles = true;
71#else
72 pretendToHaveManyCompiles = true;
73#endif
74
75 if (CodeBlock* baselineCodeBlock = getSomeBaselineCodeBlockForFunction(theFunctionValue)) {
76 if (pretendToHaveManyCompiles)
77 return jsNumber(1000000.0);
78 return jsNumber(baselineCodeBlock->numberOfDFGCompiles());
79 }
80
81 return jsNumber(0);
82}
83
84JSValue setNeverInline(JSValue theFunctionValue)
85{
86 if (FunctionExecutable* executable = getExecutableForFunction(theFunctionValue))
87 executable->setNeverInline(true);
88
89 return jsUndefined();
90}
91
92JSValue setNeverOptimize(JSValue theFunctionValue)
93{
94 if (FunctionExecutable* executable = getExecutableForFunction(theFunctionValue))
95 executable->setNeverOptimize(true);
96
97 return jsUndefined();
98}
99
100JSValue optimizeNextInvocation(JSValue theFunctionValue)
101{
102#if ENABLE(JIT)
103 if (CodeBlock* baselineCodeBlock = getSomeBaselineCodeBlockForFunction(theFunctionValue))
104 baselineCodeBlock->optimizeNextInvocation();
105#endif
106 UNUSED_PARAM(theFunctionValue);
107 return jsUndefined();
108}
109
110JSValue failNextNewCodeBlock(JSGlobalObject* globalObject)
111{
112 globalObject->vm().setFailNextNewCodeBlock();
113
114 return jsUndefined();
115}
116
117JSValue numberOfDFGCompiles(JSGlobalObject*, CallFrame* callFrame)
118{
119 if (callFrame->argumentCount() < 1)
120 return jsUndefined();
121 return numberOfDFGCompiles(callFrame->uncheckedArgument(0));
122}
123
124JSValue setNeverInline(JSGlobalObject*, CallFrame* callFrame)
125{
126 if (callFrame->argumentCount() < 1)
127 return jsUndefined();
128 return setNeverInline(callFrame->uncheckedArgument(0));
129}
130
131JSValue setNeverOptimize(JSGlobalObject*, CallFrame* callFrame)
132{
133 if (callFrame->argumentCount() < 1)
134 return jsUndefined();
135 return setNeverOptimize(callFrame->uncheckedArgument(0));
136}
137
138JSValue setCannotUseOSRExitFuzzing(JSGlobalObject*, CallFrame* callFrame)
139{
140 if (callFrame->argumentCount() < 1)
141 return jsUndefined();
142
143 JSValue theFunctionValue = callFrame->uncheckedArgument(0);
144 if (FunctionExecutable* executable = getExecutableForFunction(theFunctionValue))
145 executable->setCanUseOSRExitFuzzing(false);
146
147 return jsUndefined();
148}
149
150JSValue optimizeNextInvocation(JSGlobalObject*, CallFrame* callFrame)
151{
152 if (callFrame->argumentCount() < 1)
153 return jsUndefined();
154 return optimizeNextInvocation(callFrame->uncheckedArgument(0));
155}
156
157// This is a hook called at the bitter end of some of our tests.
158void finalizeStatsAtEndOfTesting()
159{
160}
161
162} // namespace JSC
163
164