• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 "src/ast/scopes.h"
6 #include "src/compiler/ast-loop-assignment-analyzer.h"
7 #include "src/parsing/parser.h"
8 #include "src/parsing/rewriter.h"
9 #include "test/cctest/cctest.h"
10 
11 namespace v8 {
12 namespace internal {
13 namespace compiler {
14 
15 namespace {
16 const int kBufferSize = 1024;
17 
18 struct TestHelper : public HandleAndZoneScope {
19   Handle<JSFunction> function;
20   LoopAssignmentAnalysis* result;
21 
TestHelperv8::internal::compiler::__anon0a84a26f0111::TestHelper22   explicit TestHelper(const char* body)
23       : function(Handle<JSFunction>::null()), result(NULL) {
24     ScopedVector<char> program(kBufferSize);
25     SNPrintF(program, "function f(a,b,c) { %s; } f;", body);
26     v8::Local<v8::Value> v = CompileRun(program.start());
27     Handle<Object> obj = v8::Utils::OpenHandle(*v);
28     function = Handle<JSFunction>::cast(obj);
29   }
30 
CheckLoopAssignedCountv8::internal::compiler::__anon0a84a26f0111::TestHelper31   void CheckLoopAssignedCount(int expected, const char* var_name) {
32     // TODO(titzer): don't scope analyze every single time.
33     ParseInfo parse_info(main_zone(), function);
34     CompilationInfo info(&parse_info, function);
35 
36     CHECK(Parser::ParseStatic(&parse_info));
37     CHECK(Rewriter::Rewrite(&parse_info));
38     CHECK(Scope::Analyze(&parse_info));
39 
40     Scope* scope = info.literal()->scope();
41     AstValueFactory* factory = parse_info.ast_value_factory();
42     CHECK(scope);
43 
44     if (result == NULL) {
45       AstLoopAssignmentAnalyzer analyzer(main_zone(), &info);
46       result = analyzer.Analyze();
47       CHECK(result);
48     }
49 
50     const i::AstRawString* name = factory->GetOneByteString(var_name);
51 
52     i::Variable* var = scope->Lookup(name);
53     CHECK(var);
54 
55     if (var->location() == VariableLocation::UNALLOCATED) {
56       CHECK_EQ(0, expected);
57     } else {
58       CHECK(var->IsStackAllocated());
59       CHECK_EQ(expected, result->GetAssignmentCountForTesting(scope, var));
60     }
61   }
62 };
63 }  // namespace
64 
65 
TEST(SimpleLoop1)66 TEST(SimpleLoop1) {
67   TestHelper f("var x = 0; while (x) ;");
68 
69   f.CheckLoopAssignedCount(0, "x");
70 }
71 
72 
TEST(SimpleLoop2)73 TEST(SimpleLoop2) {
74   const char* loops[] = {
75       "while (x) { var x = 0; }",            "for(;;) { var x = 0; }",
76       "for(;x;) { var x = 0; }",             "for(;x;x) { var x = 0; }",
77       "for(var i = x; x; x) { var x = 0; }", "for(y in 0) { var x = 0; }",
78       "for(y of 0) { var x = 0; }",          "for(var x = 0; x; x++) { }",
79       "for(var x = 0; x++;) { }",            "var x; for(;x;x++) { }",
80       "var x; do { x = 1; } while (0);",     "do { var x = 1; } while (0);"};
81 
82   for (size_t i = 0; i < arraysize(loops); i++) {
83     TestHelper f(loops[i]);
84     f.CheckLoopAssignedCount(1, "x");
85   }
86 }
87 
88 
TEST(ForInOf1)89 TEST(ForInOf1) {
90   const char* loops[] = {
91       "for(x in 0) { }", "for(x of 0) { }",
92   };
93 
94   for (size_t i = 0; i < arraysize(loops); i++) {
95     TestHelper f(loops[i]);
96     f.CheckLoopAssignedCount(0, "x");
97   }
98 }
99 
100 
TEST(Param1)101 TEST(Param1) {
102   TestHelper f("while (1) a = 0;");
103 
104   f.CheckLoopAssignedCount(1, "a");
105   f.CheckLoopAssignedCount(0, "b");
106   f.CheckLoopAssignedCount(0, "c");
107 }
108 
109 
TEST(Param2)110 TEST(Param2) {
111   TestHelper f("for (;;) b = 0;");
112 
113   f.CheckLoopAssignedCount(0, "a");
114   f.CheckLoopAssignedCount(1, "b");
115   f.CheckLoopAssignedCount(0, "c");
116 }
117 
118 
TEST(Param2b)119 TEST(Param2b) {
120   TestHelper f("a; b; c; for (;;) b = 0;");
121 
122   f.CheckLoopAssignedCount(0, "a");
123   f.CheckLoopAssignedCount(1, "b");
124   f.CheckLoopAssignedCount(0, "c");
125 }
126 
127 
TEST(Param3)128 TEST(Param3) {
129   TestHelper f("for(x in 0) c = 0;");
130 
131   f.CheckLoopAssignedCount(0, "a");
132   f.CheckLoopAssignedCount(0, "b");
133   f.CheckLoopAssignedCount(1, "c");
134 }
135 
136 
TEST(Param3b)137 TEST(Param3b) {
138   TestHelper f("a; b; c; for(x in 0) c = 0;");
139 
140   f.CheckLoopAssignedCount(0, "a");
141   f.CheckLoopAssignedCount(0, "b");
142   f.CheckLoopAssignedCount(1, "c");
143 }
144 
145 
TEST(NestedLoop1)146 TEST(NestedLoop1) {
147   TestHelper f("while (x) { while (x) { var x = 0; } }");
148 
149   f.CheckLoopAssignedCount(2, "x");
150 }
151 
152 
TEST(NestedLoop2)153 TEST(NestedLoop2) {
154   TestHelper f("while (0) { while (0) { var x = 0; } }");
155 
156   f.CheckLoopAssignedCount(2, "x");
157 }
158 
159 
TEST(NestedLoop3)160 TEST(NestedLoop3) {
161   TestHelper f("while (0) { var y = 1; while (0) { var x = 0; } }");
162 
163   f.CheckLoopAssignedCount(2, "x");
164   f.CheckLoopAssignedCount(1, "y");
165 }
166 
167 
TEST(NestedInc1)168 TEST(NestedInc1) {
169   const char* loops[] = {
170       "while (1) a(b++);",
171       "while (1) a(0, b++);",
172       "while (1) a(0, 0, b++);",
173       "while (1) a(b++, 1, 1);",
174       "while (1) a(++b);",
175       "while (1) a + (b++);",
176       "while (1) (b++) + a;",
177       "while (1) a + c(b++);",
178       "while (1) throw b++;",
179       "while (1) switch (b++) {} ;",
180       "while (1) switch (a) {case (b++): 0; } ;",
181       "while (1) switch (a) {case b: b++; } ;",
182       "while (1) a == (b++);",
183       "while (1) a === (b++);",
184       "while (1) +(b++);",
185       "while (1) ~(b++);",
186       "while (1) new a(b++);",
187       "while (1) (b++).f;",
188       "while (1) a[b++];",
189       "while (1) (b++)();",
190       "while (1) [b++];",
191       "while (1) [0,b++];",
192       "while (1) var y = [11,b++,12];",
193       "while (1) var y = {f:11,g:(b++),h:12};",
194       "while (1) try {b++;} finally {};",
195       "while (1) try {} finally {b++};",
196       "while (1) try {b++;} catch (e) {};",
197       "while (1) try {} catch (e) {b++};",
198       "while (1) return b++;",
199       "while (1) (b++) ? b : b;",
200       "while (1) b ? (b++) : b;",
201       "while (1) b ? b : (b++);",
202   };
203 
204   for (size_t i = 0; i < arraysize(loops); i++) {
205     TestHelper f(loops[i]);
206     f.CheckLoopAssignedCount(1, "b");
207   }
208 }
209 
210 
TEST(NestedAssign1)211 TEST(NestedAssign1) {
212   const char* loops[] = {
213       "while (1) a(b=1);",
214       "while (1) a(0, b=1);",
215       "while (1) a(0, 0, b=1);",
216       "while (1) a(b=1, 1, 1);",
217       "while (1) a + (b=1);",
218       "while (1) (b=1) + a;",
219       "while (1) a + c(b=1);",
220       "while (1) throw b=1;",
221       "while (1) switch (b=1) {} ;",
222       "while (1) switch (a) {case b=1: 0; } ;",
223       "while (1) switch (a) {case b: b=1; } ;",
224       "while (1) a == (b=1);",
225       "while (1) a === (b=1);",
226       "while (1) +(b=1);",
227       "while (1) ~(b=1);",
228       "while (1) new a(b=1);",
229       "while (1) (b=1).f;",
230       "while (1) a[b=1];",
231       "while (1) (b=1)();",
232       "while (1) [b=1];",
233       "while (1) [0,b=1];",
234       "while (1) var z = [11,b=1,12];",
235       "while (1) var y = {f:11,g:(b=1),h:12};",
236       "while (1) try {b=1;} finally {};",
237       "while (1) try {} finally {b=1};",
238       "while (1) try {b=1;} catch (e) {};",
239       "while (1) try {} catch (e) {b=1};",
240       "while (1) return b=1;",
241       "while (1) (b=1) ? b : b;",
242       "while (1) b ? (b=1) : b;",
243       "while (1) b ? b : (b=1);",
244   };
245 
246   for (size_t i = 0; i < arraysize(loops); i++) {
247     TestHelper f(loops[i]);
248     f.CheckLoopAssignedCount(1, "b");
249   }
250 }
251 
252 
TEST(NestedLoops3)253 TEST(NestedLoops3) {
254   TestHelper f("var x, y, z, w; while (x++) while (y++) while (z++) ; w;");
255 
256   f.CheckLoopAssignedCount(1, "x");
257   f.CheckLoopAssignedCount(2, "y");
258   f.CheckLoopAssignedCount(3, "z");
259   f.CheckLoopAssignedCount(0, "w");
260 }
261 
262 
TEST(NestedLoops3b)263 TEST(NestedLoops3b) {
264   TestHelper f(
265       "var x, y, z, w;"
266       "while (1) { x=1; while (1) { y=1; while (1) z=1; } }"
267       "w;");
268 
269   f.CheckLoopAssignedCount(1, "x");
270   f.CheckLoopAssignedCount(2, "y");
271   f.CheckLoopAssignedCount(3, "z");
272   f.CheckLoopAssignedCount(0, "w");
273 }
274 
275 
TEST(NestedLoops3c)276 TEST(NestedLoops3c) {
277   TestHelper f(
278       "var x, y, z, w;"
279       "while (1) {"
280       "  x++;"
281       "  while (1) {"
282       "    y++;"
283       "    while (1) z++;"
284       "  }"
285       "  while (1) {"
286       "    y++;"
287       "    while (1) z++;"
288       "  }"
289       "}"
290       "w;");
291 
292   f.CheckLoopAssignedCount(1, "x");
293   f.CheckLoopAssignedCount(3, "y");
294   f.CheckLoopAssignedCount(5, "z");
295   f.CheckLoopAssignedCount(0, "w");
296 }
297 
298 }  // namespace compiler
299 }  // namespace internal
300 }  // namespace v8
301