Line data Source code
1 : // Copyright 2019 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : // Serializer tests don't make sense in lite mode, as it doesn't gather
6 : // IC feedback.
7 : #ifndef V8_LITE_MODE
8 :
9 : #include "test/cctest/compiler/serializer-tester.h"
10 :
11 : #include "src/api-inl.h"
12 : #include "src/compiler/serializer-for-background-compilation.h"
13 : #include "src/compiler/zone-stats.h"
14 : #include "src/optimized-compilation-info.h"
15 : #include "src/zone/zone.h"
16 :
17 : namespace v8 {
18 : namespace internal {
19 : namespace compiler {
20 :
21 64 : SerializerTester::SerializerTester(const char* source)
22 128 : : canonical_(main_isolate()) {
23 : // The tests only make sense in the context of concurrent compilation.
24 64 : FLAG_concurrent_inlining = true;
25 : // The tests don't make sense when optimizations are turned off.
26 64 : FLAG_opt = true;
27 : // We need the IC to feed it to the serializer.
28 64 : FLAG_use_ic = true;
29 : // We need manual control over when a given function is optimized.
30 64 : FLAG_always_opt = false;
31 : // We need allocation of executable memory for the compilation.
32 64 : FLAG_jitless = false;
33 :
34 64 : std::string function_string = "(function() { ";
35 : function_string += source;
36 : function_string += " })();";
37 : Handle<JSFunction> function = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
38 : *v8::Local<v8::Function>::Cast(CompileRun(function_string.c_str()))));
39 : uint32_t flags = i::OptimizedCompilationInfo::kInliningEnabled |
40 : i::OptimizedCompilationInfo::kFunctionContextSpecializing |
41 : i::OptimizedCompilationInfo::kAccessorInliningEnabled |
42 : i::OptimizedCompilationInfo::kLoopPeelingEnabled |
43 : i::OptimizedCompilationInfo::kBailoutOnUninitialized |
44 : i::OptimizedCompilationInfo::kAllocationFoldingEnabled |
45 : i::OptimizedCompilationInfo::kSplittingEnabled |
46 : i::OptimizedCompilationInfo::kAnalyzeEnvironmentLiveness;
47 128 : Optimize(function, main_zone(), main_isolate(), flags, &broker_);
48 128 : function_ = JSFunctionRef(broker_, function);
49 64 : }
50 :
51 26644 : TEST(SerializeEmptyFunction) {
52 5 : SerializerTester tester("function f() {}; return f;");
53 5 : CHECK(tester.function().IsSerializedForCompilation());
54 5 : }
55 :
56 : // This helper function allows for testing weather an inlinee candidate
57 : // was properly serialized. It expects that the top-level function (that is
58 : // run through the SerializerTester) will return its inlinee candidate.
59 59 : void CheckForSerializedInlinee(const char* source, int argc = 0,
60 : Handle<Object> argv[] = {}) {
61 59 : SerializerTester tester(source);
62 59 : JSFunctionRef f = tester.function();
63 59 : CHECK(f.IsSerializedForCompilation());
64 :
65 : MaybeHandle<Object> g_obj = Execution::Call(
66 118 : tester.isolate(), tester.function().object(),
67 177 : tester.isolate()->factory()->undefined_value(), argc, argv);
68 : Handle<Object> g;
69 59 : CHECK(g_obj.ToHandle(&g));
70 :
71 : Handle<JSFunction> g_func = Handle<JSFunction>::cast(g);
72 : SharedFunctionInfoRef g_sfi(tester.broker(),
73 : handle(g_func->shared(), tester.isolate()));
74 : FeedbackVectorRef g_fv(tester.broker(),
75 : handle(g_func->feedback_vector(), tester.isolate()));
76 59 : CHECK(g_sfi.IsSerializedForCompilation(g_fv));
77 59 : }
78 :
79 26643 : TEST(SerializeInlinedClosure) {
80 : CheckForSerializedInlinee(
81 : "function f() {"
82 : " return (function g(){ return g; })();"
83 4 : "}; f(); return f;");
84 4 : }
85 :
86 26643 : TEST(SerializeInlinedFunction) {
87 : CheckForSerializedInlinee(
88 : "function g() {};"
89 : "function f() {"
90 : " g(); return g;"
91 4 : "}; f(); return f;");
92 4 : }
93 :
94 26643 : TEST(SerializeCallUndefinedReceiver) {
95 : CheckForSerializedInlinee(
96 : "function g(a,b,c) {};"
97 : "function f() {"
98 : " g(1,2,3); return g;"
99 4 : "}; f(); return f;");
100 4 : }
101 :
102 26643 : TEST(SerializeCallUndefinedReceiver2) {
103 : CheckForSerializedInlinee(
104 : "function g(a,b) {};"
105 : "function f() {"
106 : " g(1,2); return g;"
107 4 : "}; f(); return f;");
108 4 : }
109 :
110 26643 : TEST(SerializeCallProperty) {
111 : CheckForSerializedInlinee(
112 : "let obj = {"
113 : " g: function g(a,b,c) {}"
114 : "};"
115 : "function f() {"
116 : " obj.g(1,2,3); return obj.g;"
117 4 : "}; f(); return f;");
118 4 : }
119 :
120 26643 : TEST(SerializeCallProperty2) {
121 : CheckForSerializedInlinee(
122 : "let obj = {"
123 : " g: function g(a,b) {}"
124 : "};"
125 : "function f() {"
126 : " obj.g(1,2); return obj.g;"
127 4 : "}; f(); return f;");
128 4 : }
129 :
130 26643 : TEST(SerializeCallAnyReceiver) {
131 : CheckForSerializedInlinee(
132 : "let obj = {"
133 : " g: function g() {}"
134 : "};"
135 : "function f() {"
136 : " with(obj) {"
137 : " g(); return g;"
138 : " };"
139 : "};"
140 4 : "f(); return f;");
141 4 : }
142 :
143 26643 : TEST(SerializeCallWithSpread) {
144 : CheckForSerializedInlinee(
145 : "function g(args) {};"
146 : "const arr = [1,2,3];"
147 : "function f() {"
148 : " g(...arr); return g;"
149 4 : "}; f(); return f;");
150 4 : }
151 :
152 : // The following test causes the CallIC of `g` to turn megamorphic,
153 : // thus allowing us to test if we forward arguments hints (`callee` in this
154 : // example) and correctly serialize the inlining candidate `j`.
155 26643 : TEST(SerializeCallArguments) {
156 : CheckForSerializedInlinee(
157 : "function g(callee) { callee(); };"
158 : "function h() {};"
159 : "function i() {};"
160 : "g(h); g(i);"
161 : "function f() {"
162 : " function j() {};"
163 : " g(j);"
164 : " return j;"
165 4 : "}; f(); return f;");
166 4 : }
167 :
168 26643 : TEST(SerializeConstruct) {
169 : CheckForSerializedInlinee(
170 : "function g() {};"
171 : "function f() {"
172 : " new g(); return g;"
173 4 : "}; f(); return f;");
174 4 : }
175 :
176 26643 : TEST(SerializeConstructWithSpread) {
177 : CheckForSerializedInlinee(
178 : "function g(a, b, c) {};"
179 : "const arr = [1, 2];"
180 : "function f() {"
181 : " new g(0, ...arr); return g;"
182 4 : "}; f(); return f;");
183 4 : }
184 :
185 26644 : TEST(SerializeConstructSuper) {
186 : CheckForSerializedInlinee(
187 : "class A {};"
188 : "class B extends A { constructor() { super(); } };"
189 : "function f() {"
190 : " new B(); return A;"
191 5 : "}; f(); return f;");
192 5 : }
193 :
194 26644 : TEST(SerializeConditionalJump) {
195 : CheckForSerializedInlinee(
196 : "function g(callee) { callee(); };"
197 : "function h() {};"
198 : "function i() {};"
199 : "let a = true;"
200 : "g(h); g(i);"
201 : "function f() {"
202 : " function q() {};"
203 : " if (a) g(q);"
204 : " return q;"
205 5 : "}; f(); return f;");
206 5 : }
207 :
208 26644 : TEST(SerializeUnconditionalJump) {
209 : CheckForSerializedInlinee(
210 : "function g(callee) { callee(); };"
211 : "function h() {};"
212 : "function i() {};"
213 : "let a = false;"
214 : "g(h); g(i);"
215 : "function f() {"
216 : " function p() {};"
217 : " function q() {};"
218 : " if (a) g(q);"
219 : " else g(p);"
220 : " return p;"
221 5 : "}; f(); return f;");
222 5 : }
223 :
224 : } // namespace compiler
225 : } // namespace internal
226 79917 : } // namespace v8
227 :
228 : #endif // V8_LITE_MODE
|