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