1 // Copyright 2015 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.
10 #include "src/ast-expression-visitor.h"
11 #include "src/parser.h"
12 #include "src/rewriter.h"
13 #include "src/scopes.h"
14 #include "test/cctest/cctest.h"
15 #include "test/cctest/expression-type-collector.h"
16 #include "test/cctest/expression-type-collector-macros.h"
18 using namespace v8::internal;
22 static void CollectTypes(HandleAndZoneScope* handles, const char* source,
23 ZoneVector<ExpressionTypeEntry>* dst) {
24 i::Isolate* isolate = CcTest::i_isolate();
25 i::Factory* factory = isolate->factory();
27 i::Handle<i::String> source_code =
28 factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked();
30 i::Handle<i::Script> script = factory->NewScript(source_code);
32 i::ParseInfo info(handles->main_zone(), script);
33 i::Parser parser(&info);
34 parser.set_allow_harmony_arrow_functions(true);
35 parser.set_allow_harmony_sloppy(true);
38 info.set_allow_lazy_parsing(false);
39 info.set_toplevel(true);
41 CHECK(i::Compiler::ParseAndAnalyze(&info));
43 ExpressionTypeCollector(
44 isolate, handles->main_zone(),
45 info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun(), dst)
52 TEST(VisitExpressions) {
54 HandleAndZoneScope handles;
55 ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
56 const char test_function[] =
57 "function GeometricMean(stdlib, foreign, buffer) {\n"
60 " var exp = stdlib.Math.exp;\n"
61 " var log = stdlib.Math.log;\n"
62 " var values = new stdlib.Float64Array(buffer);\n"
64 " function logSum(start, end) {\n"
68 " var sum = 0.0, p = 0, q = 0;\n"
70 " // asm.js forces byte addressing of the heap by requiring shifting "
72 " for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {\n"
73 " sum = sum + +log(values[p>>3]);\n"
79 " function geometricMean(start, end) {\n"
83 " return +exp(+logSum(start, end) / +((end - start)|0));\n"
86 " return { geometricMean: geometricMean };\n"
89 CollectTypes(&handles, test_function, &types);
92 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
93 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
94 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
95 CHECK_VAR(start, Bounds::Unbounded());
96 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
97 CHECK_VAR(start, Bounds::Unbounded());
98 CHECK_EXPR(Literal, Bounds::Unbounded());
101 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
102 CHECK_VAR(end, Bounds::Unbounded());
103 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
104 CHECK_VAR(end, Bounds::Unbounded());
105 CHECK_EXPR(Literal, Bounds::Unbounded());
108 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
109 CHECK_VAR(sum, Bounds::Unbounded());
110 CHECK_EXPR(Literal, Bounds::Unbounded());
112 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
113 CHECK_VAR(p, Bounds::Unbounded());
114 CHECK_EXPR(Literal, Bounds::Unbounded());
116 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
117 CHECK_VAR(q, Bounds::Unbounded());
118 CHECK_EXPR(Literal, Bounds::Unbounded());
120 // for (p = start << 3, q = end << 3;
121 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
122 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
123 CHECK_VAR(p, Bounds::Unbounded());
124 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
125 CHECK_VAR(start, Bounds::Unbounded());
126 CHECK_EXPR(Literal, Bounds::Unbounded());
129 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
130 CHECK_VAR(q, Bounds::Unbounded());
131 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
132 CHECK_VAR(end, Bounds::Unbounded());
133 CHECK_EXPR(Literal, Bounds::Unbounded());
138 CHECK_EXPR(CompareOperation, Bounds::Unbounded()) {
139 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
140 CHECK_VAR(p, Bounds::Unbounded());
141 CHECK_EXPR(Literal, Bounds::Unbounded());
143 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
144 CHECK_VAR(q, Bounds::Unbounded());
145 CHECK_EXPR(Literal, Bounds::Unbounded());
148 // p = (p + 8)|0) {\n"
149 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
150 CHECK_VAR(p, Bounds::Unbounded());
151 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
152 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
153 CHECK_VAR(p, Bounds::Unbounded());
154 CHECK_EXPR(Literal, Bounds::Unbounded());
156 CHECK_EXPR(Literal, Bounds::Unbounded());
159 // sum = sum + +log(values[p>>3]);
160 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
161 CHECK_VAR(sum, Bounds::Unbounded());
162 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
163 CHECK_VAR(sum, Bounds::Unbounded());
164 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
165 CHECK_EXPR(Call, Bounds::Unbounded()) {
166 CHECK_VAR(log, Bounds::Unbounded());
167 CHECK_EXPR(Property, Bounds::Unbounded()) {
168 CHECK_VAR(values, Bounds::Unbounded());
169 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
170 CHECK_VAR(p, Bounds::Unbounded());
171 CHECK_EXPR(Literal, Bounds::Unbounded());
175 CHECK_EXPR(Literal, Bounds::Unbounded());
180 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
181 CHECK_VAR(sum, Bounds::Unbounded());
182 CHECK_EXPR(Literal, Bounds::Unbounded());
185 // function geometricMean
186 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
187 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
188 CHECK_VAR(start, Bounds::Unbounded());
189 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
190 CHECK_VAR(start, Bounds::Unbounded());
191 CHECK_EXPR(Literal, Bounds::Unbounded());
194 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
195 CHECK_VAR(end, Bounds::Unbounded());
196 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
197 CHECK_VAR(end, Bounds::Unbounded());
198 CHECK_EXPR(Literal, Bounds::Unbounded());
201 // return +exp(+logSum(start, end) / +((end - start)|0));
202 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
203 CHECK_EXPR(Call, Bounds::Unbounded()) {
204 CHECK_VAR(exp, Bounds::Unbounded());
205 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
206 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
207 CHECK_EXPR(Call, Bounds::Unbounded()) {
208 CHECK_VAR(logSum, Bounds::Unbounded());
209 CHECK_VAR(start, Bounds::Unbounded());
210 CHECK_VAR(end, Bounds::Unbounded());
212 CHECK_EXPR(Literal, Bounds::Unbounded());
214 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
215 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
216 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
217 CHECK_VAR(end, Bounds::Unbounded());
218 CHECK_VAR(start, Bounds::Unbounded());
220 CHECK_EXPR(Literal, Bounds::Unbounded());
222 CHECK_EXPR(Literal, Bounds::Unbounded());
226 CHECK_EXPR(Literal, Bounds::Unbounded());
230 CHECK_EXPR(Literal, Bounds::Unbounded());
231 // var exp = stdlib.Math.exp;
232 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
233 CHECK_VAR(exp, Bounds::Unbounded());
234 CHECK_EXPR(Property, Bounds::Unbounded()) {
235 CHECK_EXPR(Property, Bounds::Unbounded()) {
236 CHECK_VAR(stdlib, Bounds::Unbounded());
237 CHECK_EXPR(Literal, Bounds::Unbounded());
239 CHECK_EXPR(Literal, Bounds::Unbounded());
242 // var log = stdlib.Math.log;
243 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
244 CHECK_VAR(log, Bounds::Unbounded());
245 CHECK_EXPR(Property, Bounds::Unbounded()) {
246 CHECK_EXPR(Property, Bounds::Unbounded()) {
247 CHECK_VAR(stdlib, Bounds::Unbounded());
248 CHECK_EXPR(Literal, Bounds::Unbounded());
250 CHECK_EXPR(Literal, Bounds::Unbounded());
253 // var values = new stdlib.Float64Array(buffer);
254 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
255 CHECK_VAR(values, Bounds::Unbounded());
256 CHECK_EXPR(CallNew, Bounds::Unbounded()) {
257 CHECK_EXPR(Property, Bounds::Unbounded()) {
258 CHECK_VAR(stdlib, Bounds::Unbounded());
259 CHECK_EXPR(Literal, Bounds::Unbounded());
261 CHECK_VAR(buffer, Bounds::Unbounded());
264 // return { geometricMean: geometricMean };
265 CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) {
266 CHECK_VAR(geometricMean, Bounds::Unbounded());
274 TEST(VisitEmptyForStatment) {
275 v8::V8::Initialize();
276 HandleAndZoneScope handles;
277 ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
278 // Check that traversing an empty for statement works.
279 const char test_function[] =
283 CollectTypes(&handles, test_function, &types);
285 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {}
291 TEST(VisitSwitchStatment) {
292 v8::V8::Initialize();
293 HandleAndZoneScope handles;
294 ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
295 // Check that traversing a switch with a default works.
296 const char test_function[] =
298 " switch (0) { case 1: break; default: break; }\n"
300 CollectTypes(&handles, test_function, &types);
302 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
303 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
304 CHECK_VAR(.switch_tag, Bounds::Unbounded());
305 CHECK_EXPR(Literal, Bounds::Unbounded());
307 CHECK_EXPR(Literal, Bounds::Unbounded());
308 CHECK_VAR(.switch_tag, Bounds::Unbounded());
309 CHECK_EXPR(Literal, Bounds::Unbounded());
317 v8::V8::Initialize();
318 HandleAndZoneScope handles;
319 ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
320 // Check that traversing an empty for statement works.
321 const char test_function[] =
325 CollectTypes(&handles, test_function, &types);
327 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
328 CHECK_EXPR(Throw, Bounds::Unbounded()) {
329 CHECK_EXPR(Literal, Bounds::Unbounded());
338 v8::V8::Initialize();
339 HandleAndZoneScope handles;
340 ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
341 // Check that traversing an empty for statement works.
342 const char test_function[] =
343 "function* foo() {\n"
346 CollectTypes(&handles, test_function, &types);
348 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
349 // Generator function yields generator on entry.
350 CHECK_EXPR(Yield, Bounds::Unbounded()) {
351 CHECK_VAR(.generator_object, Bounds::Unbounded());
352 CHECK_EXPR(Assignment, Bounds::Unbounded()) {
353 CHECK_VAR(.generator_object, Bounds::Unbounded());
354 CHECK_EXPR(CallRuntime, Bounds::Unbounded());
357 // Then yields undefined.
358 CHECK_EXPR(Yield, Bounds::Unbounded()) {
359 CHECK_VAR(.generator_object, Bounds::Unbounded());
360 CHECK_EXPR(Literal, Bounds::Unbounded());
363 CHECK_EXPR(Yield, Bounds::Unbounded()) {
364 CHECK_VAR(.generator_object, Bounds::Unbounded());
365 CHECK_EXPR(Literal, Bounds::Unbounded());
373 TEST(VisitSkipping) {
374 v8::V8::Initialize();
375 HandleAndZoneScope handles;
376 ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
377 // Check that traversing an empty for statement works.
378 const char test_function[] =
379 "function foo(x) {\n"
380 " return (x + x) + 1;\n"
382 CollectTypes(&handles, test_function, &types);
384 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
385 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
388 CHECK_EXPR(Literal, Bounds::Unbounded());