• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include <stdlib.h>
6 
7 #include "src/v8.h"
8 
9 #include "src/ast/ast.h"
10 #include "src/ast/ast-expression-visitor.h"
11 #include "src/ast/scopes.h"
12 #include "src/parsing/parser.h"
13 #include "src/parsing/rewriter.h"
14 #include "src/typing-reset.h"
15 #include "test/cctest/cctest.h"
16 #include "test/cctest/compiler/function-tester.h"
17 #include "test/cctest/expression-type-collector.h"
18 #include "test/cctest/expression-type-collector-macros.h"
19 
20 #define INT32_TYPE Bounds(Type::Signed32(), Type::Signed32())
21 
22 using namespace v8::internal;
23 
24 namespace {
25 
26 class TypeSetter : public AstExpressionVisitor {
27  public:
TypeSetter(Isolate * isolate,FunctionLiteral * root)28   TypeSetter(Isolate* isolate, FunctionLiteral* root)
29       : AstExpressionVisitor(isolate, root) {}
30 
31  protected:
VisitExpression(Expression * expression)32   void VisitExpression(Expression* expression) {
33     expression->set_bounds(INT32_TYPE);
34   }
35 };
36 
37 
CheckAllSame(ZoneVector<ExpressionTypeEntry> & types,Bounds expected_type)38 void CheckAllSame(ZoneVector<ExpressionTypeEntry>& types,
39                   Bounds expected_type) {
40   CHECK_TYPES_BEGIN {
41     // function logSum
42     CHECK_EXPR(FunctionLiteral, expected_type) {
43       CHECK_EXPR(FunctionLiteral, expected_type) {
44         CHECK_EXPR(Assignment, expected_type) {
45           CHECK_VAR(start, expected_type);
46           CHECK_EXPR(BinaryOperation, expected_type) {
47             CHECK_VAR(start, expected_type);
48             CHECK_EXPR(Literal, expected_type);
49           }
50         }
51         CHECK_EXPR(Assignment, expected_type) {
52           CHECK_VAR(end, expected_type);
53           CHECK_EXPR(BinaryOperation, expected_type) {
54             CHECK_VAR(end, expected_type);
55             CHECK_EXPR(Literal, expected_type);
56           }
57         }
58         CHECK_EXPR(Assignment, expected_type) {
59           CHECK_VAR(sum, expected_type);
60           CHECK_EXPR(Literal, expected_type);
61         }
62         CHECK_EXPR(Assignment, expected_type) {
63           CHECK_VAR(p, expected_type);
64           CHECK_EXPR(Literal, expected_type);
65         }
66         CHECK_EXPR(Assignment, expected_type) {
67           CHECK_VAR(q, expected_type);
68           CHECK_EXPR(Literal, expected_type);
69         }
70         // for (p = start << 3, q = end << 3;
71         CHECK_EXPR(BinaryOperation, expected_type) {
72           CHECK_EXPR(Assignment, expected_type) {
73             CHECK_VAR(p, expected_type);
74             CHECK_EXPR(BinaryOperation, expected_type) {
75               CHECK_VAR(start, expected_type);
76               CHECK_EXPR(Literal, expected_type);
77             }
78           }
79           CHECK_EXPR(Assignment, expected_type) {
80             CHECK_VAR(q, expected_type);
81             CHECK_EXPR(BinaryOperation, expected_type) {
82               CHECK_VAR(end, expected_type);
83               CHECK_EXPR(Literal, expected_type);
84             }
85           }
86         }
87         // (p|0) < (q|0);
88         CHECK_EXPR(CompareOperation, expected_type) {
89           CHECK_EXPR(BinaryOperation, expected_type) {
90             CHECK_VAR(p, expected_type);
91             CHECK_EXPR(Literal, expected_type);
92           }
93           CHECK_EXPR(BinaryOperation, expected_type) {
94             CHECK_VAR(q, expected_type);
95             CHECK_EXPR(Literal, expected_type);
96           }
97         }
98         // p = (p + 8)|0) {\n"
99         CHECK_EXPR(Assignment, expected_type) {
100           CHECK_VAR(p, expected_type);
101           CHECK_EXPR(BinaryOperation, expected_type) {
102             CHECK_EXPR(BinaryOperation, expected_type) {
103               CHECK_VAR(p, expected_type);
104               CHECK_EXPR(Literal, expected_type);
105             }
106             CHECK_EXPR(Literal, expected_type);
107           }
108         }
109         // sum = sum + +log(values[p>>3]);
110         CHECK_EXPR(Assignment, expected_type) {
111           CHECK_VAR(sum, expected_type);
112           CHECK_EXPR(BinaryOperation, expected_type) {
113             CHECK_VAR(sum, expected_type);
114             CHECK_EXPR(BinaryOperation, expected_type) {
115               CHECK_EXPR(Call, expected_type) {
116                 CHECK_VAR(log, expected_type);
117                 CHECK_EXPR(Property, expected_type) {
118                   CHECK_VAR(values, expected_type);
119                   CHECK_EXPR(BinaryOperation, expected_type) {
120                     CHECK_VAR(p, expected_type);
121                     CHECK_EXPR(Literal, expected_type);
122                   }
123                 }
124               }
125               CHECK_EXPR(Literal, expected_type);
126             }
127           }
128         }
129         // return +sum;
130         CHECK_EXPR(BinaryOperation, expected_type) {
131           CHECK_VAR(sum, expected_type);
132           CHECK_EXPR(Literal, expected_type);
133         }
134       }
135       // function geometricMean
136       CHECK_EXPR(FunctionLiteral, expected_type) {
137         CHECK_EXPR(Assignment, expected_type) {
138           CHECK_VAR(start, expected_type);
139           CHECK_EXPR(BinaryOperation, expected_type) {
140             CHECK_VAR(start, expected_type);
141             CHECK_EXPR(Literal, expected_type);
142           }
143         }
144         CHECK_EXPR(Assignment, expected_type) {
145           CHECK_VAR(end, expected_type);
146           CHECK_EXPR(BinaryOperation, expected_type) {
147             CHECK_VAR(end, expected_type);
148             CHECK_EXPR(Literal, expected_type);
149           }
150         }
151         // return +exp(+logSum(start, end) / +((end - start)|0));
152         CHECK_EXPR(BinaryOperation, expected_type) {
153           CHECK_EXPR(Call, expected_type) {
154             CHECK_VAR(exp, expected_type);
155             CHECK_EXPR(BinaryOperation, expected_type) {
156               CHECK_EXPR(BinaryOperation, expected_type) {
157                 CHECK_EXPR(Call, expected_type) {
158                   CHECK_VAR(logSum, expected_type);
159                   CHECK_VAR(start, expected_type);
160                   CHECK_VAR(end, expected_type);
161                 }
162                 CHECK_EXPR(Literal, expected_type);
163               }
164               CHECK_EXPR(BinaryOperation, expected_type) {
165                 CHECK_EXPR(BinaryOperation, expected_type) {
166                   CHECK_EXPR(BinaryOperation, expected_type) {
167                     CHECK_VAR(end, expected_type);
168                     CHECK_VAR(start, expected_type);
169                   }
170                   CHECK_EXPR(Literal, expected_type);
171                 }
172                 CHECK_EXPR(Literal, expected_type);
173               }
174             }
175           }
176           CHECK_EXPR(Literal, expected_type);
177         }
178       }
179       // "use asm";
180       CHECK_EXPR(Literal, expected_type);
181       // var exp = stdlib.Math.exp;
182       CHECK_EXPR(Assignment, expected_type) {
183         CHECK_VAR(exp, expected_type);
184         CHECK_EXPR(Property, expected_type) {
185           CHECK_EXPR(Property, expected_type) {
186             CHECK_VAR(stdlib, expected_type);
187             CHECK_EXPR(Literal, expected_type);
188           }
189           CHECK_EXPR(Literal, expected_type);
190         }
191       }
192       // var log = stdlib.Math.log;
193       CHECK_EXPR(Assignment, expected_type) {
194         CHECK_VAR(log, expected_type);
195         CHECK_EXPR(Property, expected_type) {
196           CHECK_EXPR(Property, expected_type) {
197             CHECK_VAR(stdlib, expected_type);
198             CHECK_EXPR(Literal, expected_type);
199           }
200           CHECK_EXPR(Literal, expected_type);
201         }
202       }
203       // var values = new stdlib.Float64Array(buffer);
204       CHECK_EXPR(Assignment, expected_type) {
205         CHECK_VAR(values, expected_type);
206         CHECK_EXPR(CallNew, expected_type) {
207           CHECK_EXPR(Property, expected_type) {
208             CHECK_VAR(stdlib, expected_type);
209             CHECK_EXPR(Literal, expected_type);
210           }
211           CHECK_VAR(buffer, expected_type);
212         }
213       }
214       // return { geometricMean: geometricMean };
215       CHECK_EXPR(ObjectLiteral, expected_type) {
216         CHECK_VAR(geometricMean, expected_type);
217       }
218     }
219   }
220   CHECK_TYPES_END
221 }
222 
223 }  // namespace
224 
225 
TEST(ResetTypingInfo)226 TEST(ResetTypingInfo) {
227   const char test_function[] =
228       "function GeometricMean(stdlib, foreign, buffer) {\n"
229       "  \"use asm\";\n"
230       "\n"
231       "  var exp = stdlib.Math.exp;\n"
232       "  var log = stdlib.Math.log;\n"
233       "  var values = new stdlib.Float64Array(buffer);\n"
234       "\n"
235       "  function logSum(start, end) {\n"
236       "    start = start|0;\n"
237       "    end = end|0;\n"
238       "\n"
239       "    var sum = 0.0, p = 0, q = 0;\n"
240       "\n"
241       "    // asm.js forces byte addressing of the heap by requiring shifting "
242       "by 3\n"
243       "    for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {\n"
244       "      sum = sum + +log(values[p>>3]);\n"
245       "    }\n"
246       "\n"
247       "    return +sum;\n"
248       "  }\n"
249       "\n"
250       " function geometricMean(start, end) {\n"
251       "    start = start|0;\n"
252       "    end = end|0;\n"
253       "\n"
254       "    return +exp(+logSum(start, end) / +((end - start)|0));\n"
255       "  }\n"
256       "\n"
257       "  return { geometricMean: geometricMean };\n"
258       "}\n";
259 
260   v8::V8::Initialize();
261   HandleAndZoneScope handles;
262 
263   i::Isolate* isolate = CcTest::i_isolate();
264   i::Factory* factory = isolate->factory();
265 
266   i::Handle<i::String> source_code =
267       factory->NewStringFromUtf8(i::CStrVector(test_function))
268           .ToHandleChecked();
269 
270   i::Handle<i::Script> script = factory->NewScript(source_code);
271 
272   i::ParseInfo info(handles.main_zone(), script);
273   i::Parser parser(&info);
274   parser.set_allow_harmony_sloppy(true);
275   info.set_global();
276   info.set_lazy(false);
277   info.set_allow_lazy_parsing(false);
278   info.set_toplevel(true);
279 
280   CHECK(i::Compiler::ParseAndAnalyze(&info));
281   FunctionLiteral* root =
282       info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun();
283 
284   // Core of the test.
285   ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
286   ExpressionTypeCollector(isolate, root, &types).Run();
287   CheckAllSame(types, Bounds::Unbounded());
288 
289   TypeSetter(isolate, root).Run();
290 
291   ExpressionTypeCollector(isolate, root, &types).Run();
292   CheckAllSame(types, INT32_TYPE);
293 
294   TypingReseter(isolate, root).Run();
295 
296   ExpressionTypeCollector(isolate, root, &types).Run();
297   CheckAllSame(types, Bounds::Unbounded());
298 }
299