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