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

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

Powered by Google App Engine
This is Rietveld 408576698