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 59 : SerializerTester::SerializerTester(const char* source)
22 118 : : canonical_(main_isolate()) {
23 : // The tests only make sense in the context of concurrent compilation.
24 59 : FLAG_concurrent_inlining = true;
25 : // The tests don't make sense when optimizations are turned off.
26 59 : FLAG_opt = true;
27 : // We need the IC to feed it to the serializer.
28 59 : FLAG_use_ic = true;
29 : // We need manual control over when a given function is optimized.
30 59 : FLAG_always_opt = false;
31 : // We need allocation of executable memory for the compilation.
32 59 : FLAG_jitless = false;
33 :
34 59 : 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 118 : Optimize(function, main_zone(), main_isolate(), flags, &broker_);
48 118 : function_ = JSFunctionRef(broker_, function);
49 59 : }
50 :
51 26068 : 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 54 : void CheckForSerializedInlinee(const char* source, int argc = 0,
60 : Handle<Object> argv[] = {}) {
61 54 : SerializerTester tester(source);
62 54 : JSFunctionRef f = tester.function();
63 54 : CHECK(f.IsSerializedForCompilation());
64 :
65 : MaybeHandle<Object> g_obj = Execution::Call(
66 108 : tester.isolate(), tester.function().object(),
67 162 : tester.isolate()->factory()->undefined_value(), argc, argv);
68 : Handle<Object> g;
69 54 : 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 108 : handle(g_func->feedback_vector(), tester.isolate()));
76 54 : CHECK(g_sfi.IsSerializedForCompilation(g_fv));
77 54 : }
78 :
79 26067 : TEST(SerializeInlinedClosure) {
80 : CheckForSerializedInlinee(
81 : "function f() {"
82 : " return (function g(){ return g; })();"
83 4 : "}; f(); return f;");
84 4 : }
85 :
86 26067 : TEST(SerializeInlinedFunction) {
87 : CheckForSerializedInlinee(
88 : "function g() {};"
89 : "function f() {"
90 : " g(); return g;"
91 4 : "}; f(); return f;");
92 4 : }
93 :
94 26067 : 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 26067 : 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 26067 : 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 26067 : 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 26067 : 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 26067 : 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 26067 : 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 26067 : TEST(SerializeConstruct) {
169 : CheckForSerializedInlinee(
170 : "function g() {};"
171 : "function f() {"
172 : " new g(); return g;"
173 4 : "}; f(); return f;");
174 4 : }
175 :
176 26067 : 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 26068 : TEST(SerializeConditionalJump) {
186 : CheckForSerializedInlinee(
187 : "function g(callee) { callee(); };"
188 : "function h() {};"
189 : "function i() {};"
190 : "let a = true;"
191 : "g(h); g(i);"
192 : "function f() {"
193 : " function q() {};"
194 : " if (a) g(q);"
195 : " return q;"
196 5 : "}; f(); return f;");
197 5 : }
198 :
199 26068 : TEST(SerializeUnconditionalJump) {
200 : CheckForSerializedInlinee(
201 : "function g(callee) { callee(); };"
202 : "function h() {};"
203 : "function i() {};"
204 : "let a = false;"
205 : "g(h); g(i);"
206 : "function f() {"
207 : " function p() {};"
208 : " function q() {};"
209 : " if (a) g(q);"
210 : " else g(p);"
211 : " return p;"
212 5 : "}; f(); return f;");
213 5 : }
214 :
215 : } // namespace compiler
216 : } // namespace internal
217 78189 : } // namespace v8
218 :
219 : #endif // V8_LITE_MODE
|