Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: test/cctest/test-asm-validator.cc

Issue 1322773002: Add asm.js typer / validator. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/cctest/cctest.gyp ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "src/v8.h"
6
7 #include "src/ast.h"
8 #include "src/ast-expression-visitor.h"
9 #include "src/parser.h"
10 #include "src/rewriter.h"
11 #include "src/scopes.h"
12 #include "src/typing-asm.h"
13 #include "src/zone-type-cache.h"
14 #include "test/cctest/cctest.h"
15 #include "test/cctest/expression-type-collector.h"
16 #include "test/cctest/expression-type-collector-macros.h"
17
18 // Macros for function types.
19 #define FUNC_V_TYPE Bounds(Type::Function(Type::Undefined(), zone))
20 #define FUNC_I_TYPE Bounds(Type::Function(cache.kInt32, zone))
21 #define FUNC_F_TYPE Bounds(Type::Function(cache.kFloat32, zone))
22 #define FUNC_D_TYPE Bounds(Type::Function(cache.kFloat64, zone))
23 #define FUNC_D2D_TYPE \
24 Bounds(Type::Function(cache.kFloat64, cache.kFloat64, zone))
25 #define FUNC_N2F_TYPE \
26 Bounds(Type::Function(cache.kFloat32, Type::Number(), zone))
27 #define FUNC_I2I_TYPE Bounds(Type::Function(cache.kInt32, cache.kInt32, zone))
28 #define FUNC_II2D_TYPE \
29 Bounds(Type::Function(cache.kFloat64, cache.kInt32, cache.kInt32, zone))
30 #define FUNC_II2I_TYPE \
31 Bounds(Type::Function(cache.kInt32, cache.kInt32, cache.kInt32, zone))
32 #define FUNC_DD2D_TYPE \
33 Bounds(Type::Function(cache.kFloat64, cache.kFloat64, cache.kFloat64, zone))
34 #define FUNC_N2N_TYPE \
35 Bounds(Type::Function(Type::Number(), Type::Number(), zone))
36
37 // Macros for array types.
38 #define FLOAT64_ARRAY_TYPE Bounds(Type::Array(cache.kFloat64, zone))
39 #define FUNC_I2I_ARRAY_TYPE \
40 Bounds(Type::Array(Type::Function(cache.kInt32, cache.kInt32, zone), zone))
41
42 using namespace v8::internal;
43
44 namespace {
45
46 std::string Validate(Zone* zone, const char* source,
47 ZoneVector<ExpressionTypeEntry>* types) {
48 i::Isolate* isolate = CcTest::i_isolate();
49 i::Factory* factory = isolate->factory();
50
51 i::Handle<i::String> source_code =
52 factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked();
53
54 i::Handle<i::Script> script = factory->NewScript(source_code);
55
56 i::ParseInfo info(zone, script);
57 i::Parser parser(&info);
58 parser.set_allow_harmony_arrow_functions(true);
59 parser.set_allow_harmony_sloppy(true);
60 info.set_global();
61 info.set_lazy(false);
62 info.set_allow_lazy_parsing(false);
63 info.set_toplevel(true);
64
65 i::CompilationInfo compilation_info(&info);
66 CHECK(i::Compiler::ParseAndAnalyze(&info));
67 info.set_literal(
68 info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun());
69
70 AsmTyper typer(
71 isolate, zone, *script,
72 info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun());
73 if (typer.Validate()) {
74 ExpressionTypeCollector(&compilation_info, types).Run();
75 return "";
76 } else {
77 return typer.error_message();
78 }
79 }
80 }
81
82
83 TEST(ValidateMinimum) {
84 const char test_function[] =
85 "function GeometricMean(stdlib, foreign, buffer) {\n"
86 " \"use asm\";\n"
87 "\n"
88 " var exp = stdlib.Math.exp;\n"
89 " var log = stdlib.Math.log;\n"
90 " var values = new stdlib.Float64Array(buffer);\n"
91 "\n"
92 " function logSum(start, end) {\n"
93 " start = start|0;\n"
94 " end = end|0;\n"
95 "\n"
96 " var sum = 0.0, p = 0, q = 0;\n"
97 "\n"
98 " // asm.js forces byte addressing of the heap by requiring shifting "
99 "by 3\n"
100 " for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {\n"
101 " sum = sum + +log(values[p>>3]);\n"
102 " }\n"
103 "\n"
104 " return +sum;\n"
105 " }\n"
106 "\n"
107 " function geometricMean(start, end) {\n"
108 " start = start|0;\n"
109 " end = end|0;\n"
110 "\n"
111 " return +exp(+logSum(start, end) / +((end - start)|0));\n"
112 " }\n"
113 "\n"
114 " return { geometricMean: geometricMean };\n"
115 "}\n";
116
117 v8::V8::Initialize();
118 HandleAndZoneScope handles;
119 Zone* zone = handles.main_zone();
120 ZoneVector<ExpressionTypeEntry> types(zone);
121 CHECK_EQ("", Validate(zone, test_function, &types));
122 ZoneTypeCache cache;
123
124 CHECK_TYPES_BEGIN {
125 // Module.
126 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
127 // function logSum
128 CHECK_EXPR(FunctionLiteral, FUNC_II2D_TYPE) {
129 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
130 CHECK_VAR(start, Bounds(cache.kInt32));
131 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
132 CHECK_VAR(start, Bounds(cache.kInt32));
133 CHECK_EXPR(Literal, Bounds(cache.kInt32));
134 }
135 }
136 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
137 CHECK_VAR(end, Bounds(cache.kInt32));
138 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
139 CHECK_VAR(end, Bounds(cache.kInt32));
140 CHECK_EXPR(Literal, Bounds(cache.kInt32));
141 }
142 }
143 CHECK_EXPR(Assignment, Bounds(cache.kFloat64)) {
144 CHECK_VAR(sum, Bounds(cache.kFloat64));
145 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
146 }
147 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
148 CHECK_VAR(p, Bounds(cache.kInt32));
149 CHECK_EXPR(Literal, Bounds(cache.kInt32));
150 }
151 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
152 CHECK_VAR(q, Bounds(cache.kInt32));
153 CHECK_EXPR(Literal, Bounds(cache.kInt32));
154 }
155 // for (p = start << 3, q = end << 3;
156 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
157 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
158 CHECK_VAR(p, Bounds(cache.kInt32));
159 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
160 CHECK_VAR(start, Bounds(cache.kInt32));
161 CHECK_EXPR(Literal, Bounds(cache.kInt32));
162 }
163 }
164 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
165 CHECK_VAR(q, Bounds(cache.kInt32));
166 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
167 CHECK_VAR(end, Bounds(cache.kInt32));
168 CHECK_EXPR(Literal, Bounds(cache.kInt32));
169 }
170 }
171 }
172 // (p|0) < (q|0);
173 CHECK_EXPR(CompareOperation, Bounds(cache.kInt32)) {
174 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
175 CHECK_VAR(p, Bounds(cache.kInt32));
176 CHECK_EXPR(Literal, Bounds(cache.kInt32));
177 }
178 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
179 CHECK_VAR(q, Bounds(cache.kInt32));
180 CHECK_EXPR(Literal, Bounds(cache.kInt32));
181 }
182 }
183 // p = (p + 8)|0) {\n"
184 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
185 CHECK_VAR(p, Bounds(cache.kInt32));
186 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
187 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
188 CHECK_VAR(p, Bounds(cache.kInt32));
189 CHECK_EXPR(Literal, Bounds(cache.kInt32));
190 }
191 CHECK_EXPR(Literal, Bounds(cache.kInt32));
192 }
193 }
194 // sum = sum + +log(values[p>>3]);
195 CHECK_EXPR(Assignment, Bounds(cache.kFloat64)) {
196 CHECK_VAR(sum, Bounds(cache.kFloat64));
197 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
198 CHECK_VAR(sum, Bounds(cache.kFloat64));
199 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
200 CHECK_EXPR(Call, Bounds(cache.kFloat64)) {
201 CHECK_VAR(log, FUNC_D2D_TYPE);
202 CHECK_EXPR(Property, Bounds(cache.kFloat64)) {
203 CHECK_VAR(values, FLOAT64_ARRAY_TYPE);
204 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
205 CHECK_VAR(p, Bounds(cache.kInt32));
206 CHECK_EXPR(Literal, Bounds(cache.kInt32));
207 }
208 }
209 }
210 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
211 }
212 }
213 }
214 // return +sum;
215 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
216 CHECK_VAR(sum, Bounds(cache.kFloat64));
217 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
218 }
219 }
220 // function geometricMean
221 CHECK_EXPR(FunctionLiteral, FUNC_II2D_TYPE) {
222 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
223 CHECK_VAR(start, Bounds(cache.kInt32));
224 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
225 CHECK_VAR(start, Bounds(cache.kInt32));
226 CHECK_EXPR(Literal, Bounds(cache.kInt32));
227 }
228 }
229 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
230 CHECK_VAR(end, Bounds(cache.kInt32));
231 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
232 CHECK_VAR(end, Bounds(cache.kInt32));
233 CHECK_EXPR(Literal, Bounds(cache.kInt32));
234 }
235 }
236 // return +exp(+logSum(start, end) / +((end - start)|0));
237 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
238 CHECK_EXPR(Call, Bounds(cache.kFloat64)) {
239 CHECK_VAR(exp, FUNC_D2D_TYPE);
240 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
241 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
242 CHECK_EXPR(Call, Bounds(cache.kFloat64)) {
243 CHECK_VAR(logSum, FUNC_II2D_TYPE);
244 CHECK_VAR(start, Bounds(cache.kInt32));
245 CHECK_VAR(end, Bounds(cache.kInt32));
246 }
247 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
248 }
249 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
250 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
251 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
252 CHECK_VAR(end, Bounds(cache.kInt32));
253 CHECK_VAR(start, Bounds(cache.kInt32));
254 }
255 CHECK_EXPR(Literal, Bounds(cache.kInt32));
256 }
257 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
258 }
259 }
260 }
261 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
262 }
263 }
264 // "use asm";
265 CHECK_EXPR(Literal, Bounds(Type::String()));
266 // var exp = stdlib.Math.exp;
267 CHECK_EXPR(Assignment, FUNC_D2D_TYPE) {
268 CHECK_VAR(exp, FUNC_D2D_TYPE);
269 CHECK_EXPR(Property, FUNC_D2D_TYPE) {
270 CHECK_EXPR(Property, Bounds::Unbounded()) {
271 CHECK_VAR(stdlib, Bounds::Unbounded());
272 CHECK_EXPR(Literal, Bounds::Unbounded());
273 }
274 CHECK_EXPR(Literal, Bounds::Unbounded());
275 }
276 }
277 // var log = stdlib.Math.log;
278 CHECK_EXPR(Assignment, FUNC_D2D_TYPE) {
279 CHECK_VAR(log, FUNC_D2D_TYPE);
280 CHECK_EXPR(Property, FUNC_D2D_TYPE) {
281 CHECK_EXPR(Property, Bounds::Unbounded()) {
282 CHECK_VAR(stdlib, Bounds::Unbounded());
283 CHECK_EXPR(Literal, Bounds::Unbounded());
284 }
285 CHECK_EXPR(Literal, Bounds::Unbounded());
286 }
287 }
288 // var values = new stdlib.Float64Array(buffer);
289 CHECK_EXPR(Assignment, FLOAT64_ARRAY_TYPE) {
290 CHECK_VAR(values, FLOAT64_ARRAY_TYPE);
291 CHECK_EXPR(CallNew, FLOAT64_ARRAY_TYPE) {
292 CHECK_EXPR(Property, Bounds::Unbounded()) {
293 CHECK_VAR(stdlib, Bounds::Unbounded());
294 CHECK_EXPR(Literal, Bounds::Unbounded());
295 }
296 CHECK_VAR(buffer, Bounds::Unbounded());
297 }
298 }
299 // return { geometricMean: geometricMean };
300 CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) {
301 CHECK_VAR(geometricMean, FUNC_II2D_TYPE);
302 }
303 }
304 }
305 CHECK_TYPES_END
306 }
307
308
309 #define HARNESS_STDLIB() \
310 "var Infinity = stdlib.Infinity;\n" \
311 "var NaN = stdlib.NaN;\n" \
312 "var acos = stdlib.Math.acos;\n" \
313 "var asin = stdlib.Math.asin;\n" \
314 "var atan = stdlib.Math.atan;\n" \
315 "var cos = stdlib.Math.cos;\n" \
316 "var sin = stdlib.Math.sin;\n" \
317 "var tan = stdlib.Math.tan;\n" \
318 "var exp = stdlib.Math.exp;\n" \
319 "var log = stdlib.Math.log;\n" \
320 "var ceil = stdlib.Math.ceil;\n" \
321 "var floor = stdlib.Math.floor;\n" \
322 "var sqrt = stdlib.Math.sqrt;\n" \
323 "var min = stdlib.Math.min;\n" \
324 "var max = stdlib.Math.max;\n" \
325 "var atan2 = stdlib.Math.atan2;\n" \
326 "var pow = stdlib.Math.pow;\n" \
327 "var abs = stdlib.Math.abs;\n" \
328 "var imul = stdlib.Math.imul;\n" \
329 "var fround = stdlib.Math.fround;\n" \
330 "var E = stdlib.Math.E;\n" \
331 "var LN10 = stdlib.Math.LN10;\n" \
332 "var LN2 = stdlib.Math.LN2;\n" \
333 "var LOG2E = stdlib.Math.LOG2E;\n" \
334 "var LOG10E = stdlib.Math.LOG10E;\n" \
335 "var PI = stdlib.Math.PI;\n" \
336 "var SQRT1_2 = stdlib.Math.SQRT1_2;\n" \
337 "var SQRT2 = stdlib.Math.SQRT2;\n"
338
339
340 #define HARNESS_HEAP() \
341 "var u8 = new stdlib.Uint8Array(buffer);\n" \
342 "var i8 = new stdlib.Int8Array(buffer);\n" \
343 "var u16 = new stdlib.Uint16Array(buffer);\n" \
344 "var i16 = new stdlib.Int16Array(buffer);\n" \
345 "var u32 = new stdlib.Uint32Array(buffer);\n" \
346 "var i32 = new stdlib.Int32Array(buffer);\n" \
347 "var f32 = new stdlib.Float32Array(buffer);\n" \
348 "var f64 = new stdlib.Float64Array(buffer);\n"
349
350
351 #define HARNESS_PREAMBLE() \
352 const char test_function[] = \
353 "function Module(stdlib, foreign, buffer) {\n" \
354 "\"use asm\";\n" HARNESS_STDLIB() HARNESS_HEAP()
355
356
357 #define HARNESS_POSTAMBLE() \
358 "return { foo: foo };\n" \
359 "}\n";
360
361
362 #define CHECK_VAR_MATH_SHORTCUT(name, type) \
363 CHECK_EXPR(Assignment, type) { \
364 CHECK_VAR(name, type); \
365 CHECK_EXPR(Property, type) { \
366 CHECK_EXPR(Property, Bounds::Unbounded()) { \
367 CHECK_VAR(stdlib, Bounds::Unbounded()); \
368 CHECK_EXPR(Literal, Bounds::Unbounded()); \
369 } \
370 CHECK_EXPR(Literal, Bounds::Unbounded()); \
371 } \
372 }
373
374
375 #define CHECK_VAR_SHORTCUT(name, type) \
376 CHECK_EXPR(Assignment, type) { \
377 CHECK_VAR(name, type); \
378 CHECK_EXPR(Property, type) { \
379 CHECK_VAR(stdlib, Bounds::Unbounded()); \
380 CHECK_EXPR(Literal, Bounds::Unbounded()); \
381 } \
382 }
383
384
385 #define CHECK_VAR_NEW_SHORTCUT(name, type) \
386 CHECK_EXPR(Assignment, type) { \
387 CHECK_VAR(name, type); \
388 CHECK_EXPR(CallNew, type) { \
389 CHECK_EXPR(Property, Bounds::Unbounded()) { \
390 CHECK_VAR(stdlib, Bounds::Unbounded()); \
391 CHECK_EXPR(Literal, Bounds::Unbounded()); \
392 } \
393 CHECK_VAR(buffer, Bounds::Unbounded()); \
394 } \
395 }
396
397
398 namespace {
399
400 void CheckStdlibShortcuts(Zone* zone, ZoneVector<ExpressionTypeEntry>& types,
401 size_t& index, int& depth, ZoneTypeCache& cache) {
402 // var exp = stdlib.*; (D * 12)
403 CHECK_VAR_SHORTCUT(Infinity, Bounds(cache.kFloat64));
404 CHECK_VAR_SHORTCUT(NaN, Bounds(cache.kFloat64));
405 // var x = stdlib.Math.x; D2D
406 CHECK_VAR_MATH_SHORTCUT(acos, FUNC_D2D_TYPE);
407 CHECK_VAR_MATH_SHORTCUT(asin, FUNC_D2D_TYPE);
408 CHECK_VAR_MATH_SHORTCUT(atan, FUNC_D2D_TYPE);
409 CHECK_VAR_MATH_SHORTCUT(cos, FUNC_D2D_TYPE);
410 CHECK_VAR_MATH_SHORTCUT(sin, FUNC_D2D_TYPE);
411 CHECK_VAR_MATH_SHORTCUT(tan, FUNC_D2D_TYPE);
412 CHECK_VAR_MATH_SHORTCUT(exp, FUNC_D2D_TYPE);
413 CHECK_VAR_MATH_SHORTCUT(log, FUNC_D2D_TYPE);
414 CHECK_VAR_MATH_SHORTCUT(ceil, FUNC_D2D_TYPE);
415 CHECK_VAR_MATH_SHORTCUT(floor, FUNC_D2D_TYPE);
416 CHECK_VAR_MATH_SHORTCUT(sqrt, FUNC_D2D_TYPE);
417 // var exp = stdlib.Math.*; (DD2D * 12)
418 CHECK_VAR_MATH_SHORTCUT(min, FUNC_DD2D_TYPE);
419 CHECK_VAR_MATH_SHORTCUT(max, FUNC_DD2D_TYPE);
420 CHECK_VAR_MATH_SHORTCUT(atan2, FUNC_DD2D_TYPE);
421 CHECK_VAR_MATH_SHORTCUT(pow, FUNC_DD2D_TYPE);
422 // Special ones.
423 CHECK_VAR_MATH_SHORTCUT(abs, FUNC_N2N_TYPE);
424 CHECK_VAR_MATH_SHORTCUT(imul, FUNC_II2I_TYPE);
425 CHECK_VAR_MATH_SHORTCUT(fround, FUNC_N2F_TYPE);
426 // var exp = stdlib.Math.*; (D * 12)
427 CHECK_VAR_MATH_SHORTCUT(E, Bounds(cache.kFloat64));
428 CHECK_VAR_MATH_SHORTCUT(LN10, Bounds(cache.kFloat64));
429 CHECK_VAR_MATH_SHORTCUT(LN2, Bounds(cache.kFloat64));
430 CHECK_VAR_MATH_SHORTCUT(LOG2E, Bounds(cache.kFloat64));
431 CHECK_VAR_MATH_SHORTCUT(LOG10E, Bounds(cache.kFloat64));
432 CHECK_VAR_MATH_SHORTCUT(PI, Bounds(cache.kFloat64));
433 CHECK_VAR_MATH_SHORTCUT(SQRT1_2, Bounds(cache.kFloat64));
434 CHECK_VAR_MATH_SHORTCUT(SQRT2, Bounds(cache.kFloat64));
435 // var values = new stdlib.*Array(buffer);
436 CHECK_VAR_NEW_SHORTCUT(u8, Bounds(cache.kUint8Array));
437 CHECK_VAR_NEW_SHORTCUT(i8, Bounds(cache.kInt8Array));
438 CHECK_VAR_NEW_SHORTCUT(u16, Bounds(cache.kUint16Array));
439 CHECK_VAR_NEW_SHORTCUT(i16, Bounds(cache.kInt16Array));
440 CHECK_VAR_NEW_SHORTCUT(u32, Bounds(cache.kUint32Array));
441 CHECK_VAR_NEW_SHORTCUT(i32, Bounds(cache.kInt32Array));
442 CHECK_VAR_NEW_SHORTCUT(f32, Bounds(cache.kFloat32Array));
443 CHECK_VAR_NEW_SHORTCUT(f64, Bounds(cache.kFloat64Array));
444 }
445 }
446
447
448 #define CHECK_FUNC_TYPES_BEGIN(func) \
449 HARNESS_PREAMBLE() \
450 func "\n" HARNESS_POSTAMBLE(); \
451 \
452 v8::V8::Initialize(); \
453 HandleAndZoneScope handles; \
454 Zone* zone = handles.main_zone(); \
455 ZoneVector<ExpressionTypeEntry> types(zone); \
456 CHECK_EQ("", Validate(zone, test_function, &types)); \
457 ZoneTypeCache cache; \
458 \
459 CHECK_TYPES_BEGIN { \
460 /* Module. */ \
461 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
462 #define CHECK_FUNC_TYPES_END_1() \
463 /* "use asm"; */ \
464 CHECK_EXPR(Literal, Bounds(Type::String())); \
465 /* stdlib shortcuts. */ \
466 CheckStdlibShortcuts(zone, types, index, depth, cache);
467
468
469 #define CHECK_FUNC_TYPES_END_2() \
470 /* return { foo: foo }; */ \
471 CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) { \
472 CHECK_VAR(foo, FUNC_V_TYPE); \
473 } \
474 } \
475 } \
476 CHECK_TYPES_END
477
478
479 #define CHECK_FUNC_TYPES_END \
480 CHECK_FUNC_TYPES_END_1(); \
481 CHECK_FUNC_TYPES_END_2();
482
483
484 #define CHECK_FUNC_ERROR(func, message) \
485 HARNESS_PREAMBLE() \
486 func "\n" HARNESS_POSTAMBLE(); \
487 \
488 v8::V8::Initialize(); \
489 HandleAndZoneScope handles; \
490 Zone* zone = handles.main_zone(); \
491 ZoneVector<ExpressionTypeEntry> types(zone); \
492 CHECK_EQ(message, Validate(zone, test_function, &types));
493
494
495 TEST(BareHarness) {
496 CHECK_FUNC_TYPES_BEGIN("function foo() {}") {
497 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {}
498 }
499 CHECK_FUNC_TYPES_END
500 }
501
502
503 TEST(ReturnVoid) {
504 CHECK_FUNC_TYPES_BEGIN(
505 "function bar() { return; }\n"
506 "function foo() { bar(); }") {
507 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
508 // return undefined;
509 CHECK_EXPR(Literal, Bounds(Type::Undefined()));
510 }
511 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
512 CHECK_EXPR(Call, Bounds(Type::Undefined())) {
513 CHECK_VAR(bar, FUNC_V_TYPE);
514 }
515 }
516 }
517 CHECK_FUNC_TYPES_END
518 }
519
520
521 TEST(ReturnInt32Literal) {
522 CHECK_FUNC_TYPES_BEGIN(
523 "function bar() { return 1; }\n"
524 "function foo() { bar(); }") {
525 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
526 // return 1;
527 CHECK_EXPR(Literal, Bounds(cache.kInt32));
528 }
529 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
530 CHECK_EXPR(Call, Bounds(cache.kInt32)) { CHECK_VAR(bar, FUNC_I_TYPE); }
531 }
532 }
533 CHECK_FUNC_TYPES_END
534 }
535
536
537 TEST(ReturnFloat64Literal) {
538 CHECK_FUNC_TYPES_BEGIN(
539 "function bar() { return 1.0; }\n"
540 "function foo() { bar(); }") {
541 CHECK_EXPR(FunctionLiteral, FUNC_D_TYPE) {
542 // return 1.0;
543 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
544 }
545 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
546 CHECK_EXPR(Call, Bounds(cache.kFloat64)) { CHECK_VAR(bar, FUNC_D_TYPE); }
547 }
548 }
549 CHECK_FUNC_TYPES_END
550 }
551
552
553 TEST(ReturnFloat32Literal) {
554 CHECK_FUNC_TYPES_BEGIN(
555 "function bar() { return fround(1.0); }\n"
556 "function foo() { bar(); }") {
557 CHECK_EXPR(FunctionLiteral, FUNC_F_TYPE) {
558 // return fround(1.0);
559 CHECK_EXPR(Call, Bounds(cache.kFloat32)) {
560 CHECK_VAR(fround, FUNC_N2F_TYPE);
561 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
562 }
563 }
564 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
565 CHECK_EXPR(Call, Bounds(cache.kFloat32)) { CHECK_VAR(bar, FUNC_F_TYPE); }
566 }
567 }
568 CHECK_FUNC_TYPES_END
569 }
570
571
572 TEST(ReturnFloat64Var) {
573 CHECK_FUNC_TYPES_BEGIN(
574 "function bar() { var x = 1.0; return +x; }\n"
575 "function foo() { bar(); }") {
576 CHECK_EXPR(FunctionLiteral, FUNC_D_TYPE) {
577 // return 1.0;
578 CHECK_EXPR(Assignment, Bounds(cache.kFloat64)) {
579 CHECK_VAR(x, Bounds(cache.kFloat64));
580 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
581 }
582 // return 1.0;
583 CHECK_EXPR(BinaryOperation, Bounds(cache.kFloat64)) {
584 CHECK_VAR(x, Bounds(cache.kFloat64));
585 CHECK_EXPR(Literal, Bounds(cache.kFloat64));
586 }
587 }
588 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
589 CHECK_EXPR(Call, Bounds(cache.kFloat64)) { CHECK_VAR(bar, FUNC_D_TYPE); }
590 }
591 }
592 CHECK_FUNC_TYPES_END
593 }
594
595
596 TEST(Addition2) {
597 CHECK_FUNC_TYPES_BEGIN(
598 "function bar() { var x = 1; var y = 2; return (x+y)|0; }\n"
599 "function foo() { bar(); }") {
600 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
601 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
602 CHECK_VAR(x, Bounds(cache.kInt32));
603 CHECK_EXPR(Literal, Bounds(cache.kInt32));
604 }
605 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
606 CHECK_VAR(y, Bounds(cache.kInt32));
607 CHECK_EXPR(Literal, Bounds(cache.kInt32));
608 }
609 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
610 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
611 CHECK_VAR(x, Bounds(cache.kInt32));
612 CHECK_VAR(y, Bounds(cache.kInt32));
613 }
614 CHECK_EXPR(Literal, Bounds(cache.kInt32));
615 }
616 }
617 CHECK_SKIP();
618 }
619 CHECK_FUNC_TYPES_END
620 }
621
622
623 TEST(Addition4) {
624 CHECK_FUNC_TYPES_BEGIN(
625 "function bar() { var x = 1; var y = 2; return (x+y+x+y)|0; }\n"
626 "function foo() { bar(); }") {
627 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
628 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
629 CHECK_VAR(x, Bounds(cache.kInt32));
630 CHECK_EXPR(Literal, Bounds(cache.kInt32));
631 }
632 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
633 CHECK_VAR(y, Bounds(cache.kInt32));
634 CHECK_EXPR(Literal, Bounds(cache.kInt32));
635 }
636 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
637 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
638 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
639 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
640 CHECK_VAR(x, Bounds(cache.kInt32));
641 CHECK_VAR(y, Bounds(cache.kInt32));
642 }
643 CHECK_VAR(x, Bounds(cache.kInt32));
644 }
645 CHECK_VAR(y, Bounds(cache.kInt32));
646 }
647 CHECK_EXPR(Literal, Bounds(cache.kInt32));
648 }
649 }
650 CHECK_SKIP();
651 }
652 CHECK_FUNC_TYPES_END
653 }
654
655
656 TEST(Multiplication2) {
657 CHECK_FUNC_ERROR(
658 "function bar() { var x = 1; var y = 2; return (x*y)|0; }\n"
659 "function foo() { bar(); }",
660 "asm: line 39: direct integer multiply forbidden\n");
661 }
662
663
664 TEST(Division4) {
665 CHECK_FUNC_ERROR(
666 "function bar() { var x = 1; var y = 2; return (x/y/x/y)|0; }\n"
667 "function foo() { bar(); }",
668 "asm: line 39: too many consecutive multiplicative ops\n");
669 }
670
671
672 TEST(Load1) {
673 CHECK_FUNC_TYPES_BEGIN(
674 "function bar() { var x = 1; var y = i8[x>>0]|0; }\n"
675 "function foo() { bar(); }") {
676 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
677 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
678 CHECK_VAR(x, Bounds(cache.kInt32));
679 CHECK_EXPR(Literal, Bounds(cache.kInt32));
680 }
681 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
682 CHECK_VAR(y, Bounds(cache.kInt32));
683 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
684 CHECK_EXPR(Property, Bounds(cache.kInt8)) {
685 CHECK_VAR(i8, Bounds(cache.kInt8Array));
686 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
687 CHECK_VAR(x, Bounds(cache.kInt32));
688 CHECK_EXPR(Literal, Bounds(cache.kInt32));
689 }
690 }
691 CHECK_EXPR(Literal, Bounds(cache.kInt32));
692 }
693 }
694 }
695 CHECK_SKIP();
696 }
697 CHECK_FUNC_TYPES_END
698 }
699
700
701 TEST(FunctionTables) {
702 CHECK_FUNC_TYPES_BEGIN(
703 "function func1(x) { x = x | 0; return (x * 5) | 0; }\n"
704 "function func2(x) { x = x | 0; return (x * 25) | 0; }\n"
705 "var table1 = [func1, func2];\n"
706 "function bar(x, y) { x = x | 0; y = y | 0;\n"
707 " return table1[x & 1](y)|0; }\n"
708 "function foo() { bar(1, 2); }") {
709 CHECK_EXPR(FunctionLiteral, FUNC_I2I_TYPE) {
710 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
711 CHECK_VAR(x, Bounds(cache.kInt32));
712 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
713 CHECK_VAR(x, Bounds(cache.kInt32));
714 CHECK_EXPR(Literal, Bounds(cache.kInt32));
715 }
716 }
717 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
718 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
719 CHECK_VAR(x, Bounds(cache.kInt32));
720 CHECK_EXPR(Literal, Bounds(cache.kInt32));
721 }
722 CHECK_EXPR(Literal, Bounds(cache.kInt32));
723 }
724 }
725 CHECK_EXPR(FunctionLiteral, FUNC_I2I_TYPE) {
726 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
727 CHECK_VAR(x, Bounds(cache.kInt32));
728 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
729 CHECK_VAR(x, Bounds(cache.kInt32));
730 CHECK_EXPR(Literal, Bounds(cache.kInt32));
731 }
732 }
733 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
734 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
735 CHECK_VAR(x, Bounds(cache.kInt32));
736 CHECK_EXPR(Literal, Bounds(cache.kInt32));
737 }
738 CHECK_EXPR(Literal, Bounds(cache.kInt32));
739 }
740 }
741 CHECK_EXPR(FunctionLiteral, FUNC_II2I_TYPE) {
742 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
743 CHECK_VAR(x, Bounds(cache.kInt32));
744 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
745 CHECK_VAR(x, Bounds(cache.kInt32));
746 CHECK_EXPR(Literal, Bounds(cache.kInt32));
747 }
748 }
749 CHECK_EXPR(Assignment, Bounds(cache.kInt32)) {
750 CHECK_VAR(y, Bounds(cache.kInt32));
751 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
752 CHECK_VAR(y, Bounds(cache.kInt32));
753 CHECK_EXPR(Literal, Bounds(cache.kInt32));
754 }
755 }
756 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
757 CHECK_EXPR(Call, Bounds(cache.kInt32)) {
758 CHECK_EXPR(Property, FUNC_I2I_TYPE) {
759 CHECK_VAR(table1, FUNC_I2I_ARRAY_TYPE);
760 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
761 CHECK_VAR(x, Bounds(cache.kInt32));
762 CHECK_EXPR(Literal, Bounds(cache.kInt32));
763 }
764 }
765 CHECK_VAR(y, Bounds(cache.kInt32));
766 }
767 CHECK_EXPR(Literal, Bounds(cache.kInt32));
768 }
769 }
770 CHECK_SKIP();
771 }
772 CHECK_FUNC_TYPES_END_1();
773 CHECK_EXPR(Assignment, FUNC_I2I_ARRAY_TYPE) {
774 CHECK_VAR(table1, FUNC_I2I_ARRAY_TYPE);
775 CHECK_EXPR(ArrayLiteral, FUNC_I2I_ARRAY_TYPE) {
776 CHECK_VAR(func1, FUNC_I2I_TYPE);
777 CHECK_VAR(func2, FUNC_I2I_TYPE);
778 }
779 }
780 CHECK_FUNC_TYPES_END_2();
781 }
782
783
784 TEST(BadFunctionTable) {
785 CHECK_FUNC_ERROR(
786 "function func1(x) { x = x | 0; return (x * 5) | 0; }\n"
787 "var table1 = [func1, 1];\n"
788 "function bar(x, y) { x = x | 0; y = y | 0;\n"
789 " return table1[x & 1](y)|0; }\n"
790 "function foo() { bar(1, 2); }",
791 "asm: line 40: array component expected to be a function\n");
792 }
793
794
795 TEST(MissingParameterTypes) {
796 CHECK_FUNC_ERROR(
797 "function bar(x) { var y = 1; }\n"
798 "function foo() { bar(2); }",
799 "asm: line 39: missing parameter type annotations\n");
800 }
801
802
803 TEST(InvalidTypeAnnotationBinaryOpDiv) {
804 CHECK_FUNC_ERROR(
805 "function bar(x) { x = x / 4; }\n"
806 "function foo() { bar(2); }",
807 "asm: line 39: invalid type annotation on binary op\n");
808 }
809
810
811 TEST(InvalidTypeAnnotationBinaryOpMul) {
812 CHECK_FUNC_ERROR(
813 "function bar(x) { x = x * 4.0; }\n"
814 "function foo() { bar(2); }",
815 "asm: line 39: invalid type annotation on binary op\n");
816 }
817
818
819 TEST(InvalidArgumentCount) {
820 CHECK_FUNC_ERROR(
821 "function bar(x) { return fround(4, 5); }\n"
822 "function foo() { bar(); }",
823 "asm: line 39: invalid argument count calling fround\n");
824 }
825
826
827 TEST(InvalidTypeAnnotationArity) {
828 CHECK_FUNC_ERROR(
829 "function bar(x) { x = max(x); }\n"
830 "function foo() { bar(3); }",
831 "asm: line 39: only fround allowed on expression annotations\n");
832 }
833
834
835 TEST(InvalidTypeAnnotationOnlyFround) {
836 CHECK_FUNC_ERROR(
837 "function bar(x) { x = sin(x); }\n"
838 "function foo() { bar(3); }",
839 "asm: line 39: only fround allowed on expression annotations\n");
840 }
841
842
843 TEST(InvalidTypeAnnotation) {
844 CHECK_FUNC_ERROR(
845 "function bar(x) { x = (x+x)(x); }\n"
846 "function foo() { bar(3); }",
847 "asm: line 39: invalid type annotation\n");
848 }
849
850
851 TEST(WithStatement) {
852 CHECK_FUNC_ERROR(
853 "function bar() { var x = 0; with (x) { x = x + 1; } }\n"
854 "function foo() { bar(); }",
855 "asm: line 39: bad with statement\n");
856 }
857
858
859 TEST(NestedFunction) {
860 CHECK_FUNC_ERROR(
861 "function bar() { function x() { return 1; } }\n"
862 "function foo() { bar(); }",
863 "asm: line 39: function declared inside another\n");
864 }
865
866
867 TEST(UnboundVariable) {
868 CHECK_FUNC_ERROR(
869 "function bar() { var x = y; }\n"
870 "function foo() { bar(); }",
871 "asm: line 39: unbound variable\n");
872 }
873
874
875 TEST(ForeignFunction) {
876 CHECK_FUNC_TYPES_BEGIN(
877 "var baz = foreign.baz;\n"
878 "function bar() { return baz(1, 2)|0; }\n"
879 "function foo() { bar(); }") {
880 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
881 CHECK_EXPR(BinaryOperation, Bounds(cache.kInt32)) {
882 CHECK_EXPR(Call, Bounds(Type::Number(zone))) {
883 CHECK_VAR(baz, Bounds(Type::Any()));
884 CHECK_EXPR(Literal, Bounds(cache.kInt32));
885 CHECK_EXPR(Literal, Bounds(cache.kInt32));
886 }
887 CHECK_EXPR(Literal, Bounds(cache.kInt32));
888 }
889 }
890 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
891 CHECK_EXPR(Call, Bounds(cache.kInt32)) { CHECK_VAR(bar, FUNC_I_TYPE); }
892 }
893 }
894 CHECK_FUNC_TYPES_END_1()
895 CHECK_EXPR(Assignment, Bounds(Type::Any())) {
896 CHECK_VAR(baz, Bounds(Type::Any()));
897 CHECK_EXPR(Property, Bounds(Type::Any())) {
898 CHECK_VAR(foreign, Bounds::Unbounded());
899 CHECK_EXPR(Literal, Bounds::Unbounded());
900 }
901 }
902 CHECK_FUNC_TYPES_END_2()
903 }
904
905
906 TEST(BadExports) {
907 HARNESS_PREAMBLE()
908 "function foo() {};\n"
909 "return {foo: foo, bar: 1};"
910 "}\n";
911
912 v8::V8::Initialize();
913 HandleAndZoneScope handles;
914 Zone* zone = handles.main_zone();
915 ZoneVector<ExpressionTypeEntry> types(zone);
916 CHECK_EQ("asm: line 40: non-function in function table\n",
917 Validate(zone, test_function, &types));
918 }
OLDNEW
« no previous file with comments | « test/cctest/cctest.gyp ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698