| OLD | NEW | 
|---|
| (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 } | 
| OLD | NEW | 
|---|