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/typing-asm.h" 6 7 #include <limits> 8 9 #include "src/v8.h" 10 11 #include "src/ast/ast.h" 12 #include "src/ast/scopes.h" 13 #include "src/codegen.h" 14 #include "src/type-cache.h" 15 16 namespace v8 { 17 namespace internal { 18 19 #define FAIL(node, msg) \ 20 do { \ 21 valid_ = false; \ 22 int line = node->position() == RelocInfo::kNoPosition \ 23 ? -1 \ 24 : script_->GetLineNumber(node->position()); \ 25 base::OS::SNPrintF(error_message_, sizeof(error_message_), \ 26 "asm: line %d: %s\n", line + 1, msg); \ 27 return; \ 28 } while (false) 29 30 31 #define RECURSE(call) \ 32 do { \ 33 DCHECK(!HasStackOverflow()); \ 34 call; \ 35 if (HasStackOverflow()) return; \ 36 if (!valid_) return; \ 37 } while (false) 38 39 40 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, 41 FunctionLiteral* root) 42 : zone_(zone), 43 isolate_(isolate), 44 script_(script), 45 root_(root), 46 valid_(true), 47 allow_simd_(false), 48 property_info_(NULL), 49 intish_(0), 50 stdlib_types_(zone), 51 stdlib_heap_types_(zone), 52 stdlib_math_types_(zone), 53 #define V(NAME, Name, name, lane_count, lane_type) \ 54 stdlib_simd_##name##_types_(zone), 55 SIMD128_TYPES(V) 56 #undef V 57 global_variable_type_(HashMap::PointersMatch, 58 ZoneHashMap::kDefaultHashMapCapacity, 59 ZoneAllocationPolicy(zone)), 60 local_variable_type_(HashMap::PointersMatch, 61 ZoneHashMap::kDefaultHashMapCapacity, 62 ZoneAllocationPolicy(zone)), 63 in_function_(false), 64 building_function_tables_(false), 65 cache_(TypeCache::Get()) { 66 InitializeAstVisitor(isolate); 67 InitializeStdlib(); 68 } 69 70 71 bool AsmTyper::Validate() { 72 VisitAsmModule(root_); 73 return valid_ && !HasStackOverflow(); 74 } 75 76 77 void AsmTyper::VisitAsmModule(FunctionLiteral* fun) { 78 Scope* scope = fun->scope(); 79 if (!scope->is_function_scope()) FAIL(fun, "not at function scope"); 80 81 ExpressionStatement* use_asm = fun->body()->first()->AsExpressionStatement(); 82 if (use_asm == NULL) FAIL(fun, "missing \"use asm\""); 83 Literal* use_asm_literal = use_asm->expression()->AsLiteral(); 84 if (use_asm_literal == NULL) FAIL(fun, "missing \"use asm\""); 85 if (!use_asm_literal->raw_value()->AsString()->IsOneByteEqualTo("use asm")) 86 FAIL(fun, "missing \"use asm\""); 87 88 // Module parameters. 89 for (int i = 0; i < scope->num_parameters(); ++i) { 90 Variable* param = scope->parameter(i); 91 DCHECK(GetType(param) == NULL); 92 SetType(param, Type::None(zone())); 93 } 94 95 ZoneList<Declaration*>* decls = scope->declarations(); 96 97 // Set all globals to type Any. 98 VariableDeclaration* decl = scope->function(); 99 if (decl != NULL) SetType(decl->proxy()->var(), Type::None()); 100 RECURSE(VisitDeclarations(scope->declarations())); 101 102 // Validate global variables. 103 RECURSE(VisitStatements(fun->body())); 104 105 // Validate function annotations. 106 for (int i = 0; i < decls->length(); ++i) { 107 FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration(); 108 if (decl != NULL) { 109 RECURSE(VisitFunctionAnnotation(decl->fun())); 110 Variable* var = decl->proxy()->var(); 111 if (property_info_ != NULL) { 112 SetVariableInfo(var, property_info_); 113 property_info_ = NULL; 114 } 115 SetType(var, computed_type_); 116 DCHECK(GetType(var) != NULL); 117 } 118 } 119 120 // Build function tables. 121 building_function_tables_ = true; 122 RECURSE(VisitStatements(fun->body())); 123 building_function_tables_ = false; 124 125 // Validate function bodies. 126 for (int i = 0; i < decls->length(); ++i) { 127 FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration(); 128 if (decl != NULL) { 129 RECURSE( 130 VisitWithExpectation(decl->fun(), Type::Any(zone()), "UNREACHABLE")); 131 if (!computed_type_->IsFunction()) { 132 FAIL(decl->fun(), "function literal expected to be a function"); 133 } 134 } 135 } 136 137 // Validate exports. 138 ReturnStatement* stmt = fun->body()->last()->AsReturnStatement(); 139 if (stmt == nullptr) { 140 FAIL(fun->body()->last(), "last statement in module is not a return"); 141 } 142 RECURSE(VisitWithExpectation(stmt->expression(), Type::Object(), 143 "expected object export")); 144 } 145 146 147 void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) { 148 Variable* var = decl->proxy()->var(); 149 if (var->location() != VariableLocation::PARAMETER) { 150 if (GetType(var) == NULL) { 151 SetType(var, Type::Any(zone())); 152 } else { 153 DCHECK(!GetType(var)->IsFunction()); 154 } 155 } 156 DCHECK(GetType(var) != NULL); 157 intish_ = 0; 158 } 159 160 161 void AsmTyper::VisitFunctionDeclaration(FunctionDeclaration* decl) { 162 if (in_function_) { 163 FAIL(decl, "function declared inside another"); 164 } 165 // Set function type so global references to functions have some type 166 // (so they can give a more useful error). 167 Variable* var = decl->proxy()->var(); 168 SetType(var, Type::Function(zone())); 169 } 170 171 172 void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { 173 // Extract result type. 174 ZoneList<Statement*>* body = fun->body(); 175 Type* result_type = Type::Undefined(zone()); 176 if (body->length() > 0) { 177 ReturnStatement* stmt = body->last()->AsReturnStatement(); 178 if (stmt != NULL) { 179 Literal* literal = stmt->expression()->AsLiteral(); 180 Type* old_expected = expected_type_; 181 expected_type_ = Type::Any(); 182 if (literal) { 183 RECURSE(VisitLiteral(literal, true)); 184 } else { 185 RECURSE(VisitExpressionAnnotation(stmt->expression(), NULL, true)); 186 } 187 expected_type_ = old_expected; 188 result_type = computed_type_; 189 } 190 } 191 Type::FunctionType* type = 192 Type::Function(result_type, Type::Any(), fun->parameter_count(), zone()) 193 ->AsFunction(); 194 195 // Extract parameter types. 196 bool good = true; 197 for (int i = 0; i < fun->parameter_count(); ++i) { 198 good = false; 199 if (i >= body->length()) break; 200 ExpressionStatement* stmt = body->at(i)->AsExpressionStatement(); 201 if (stmt == NULL) break; 202 Assignment* expr = stmt->expression()->AsAssignment(); 203 if (expr == NULL || expr->is_compound()) break; 204 VariableProxy* proxy = expr->target()->AsVariableProxy(); 205 if (proxy == NULL) break; 206 Variable* var = proxy->var(); 207 if (var->location() != VariableLocation::PARAMETER || var->index() != i) 208 break; 209 RECURSE(VisitExpressionAnnotation(expr->value(), var, false)); 210 if (property_info_ != NULL) { 211 SetVariableInfo(var, property_info_); 212 property_info_ = NULL; 213 } 214 SetType(var, computed_type_); 215 type->InitParameter(i, computed_type_); 216 good = true; 217 } 218 if (!good) FAIL(fun, "missing parameter type annotations"); 219 220 SetResult(fun, type); 221 } 222 223 224 void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var, 225 bool is_return) { 226 // Normal +x or x|0 annotations. 227 BinaryOperation* bin = expr->AsBinaryOperation(); 228 if (bin != NULL) { 229 if (var != NULL) { 230 VariableProxy* proxy = bin->left()->AsVariableProxy(); 231 if (proxy == NULL) { 232 FAIL(bin->left(), "expected variable for type annotation"); 233 } 234 if (proxy->var() != var) { 235 FAIL(proxy, "annotation source doesn't match destination"); 236 } 237 } 238 Literal* right = bin->right()->AsLiteral(); 239 if (right != NULL) { 240 switch (bin->op()) { 241 case Token::MUL: // We encode +x as x*1.0 242 if (right->raw_value()->ContainsDot() && 243 right->raw_value()->AsNumber() == 1.0) { 244 SetResult(expr, cache_.kAsmDouble); 245 return; 246 } 247 break; 248 case Token::BIT_OR: 249 if (!right->raw_value()->ContainsDot() && 250 right->raw_value()->AsNumber() == 0.0) { 251 if (is_return) { 252 SetResult(expr, cache_.kAsmSigned); 253 } else { 254 SetResult(expr, cache_.kAsmInt); 255 } 256 return; 257 } 258 break; 259 default: 260 break; 261 } 262 } 263 FAIL(expr, "invalid type annotation on binary op"); 264 } 265 266 // Numbers or the undefined literal (for empty returns). 267 if (expr->IsLiteral()) { 268 RECURSE(VisitWithExpectation(expr, Type::Any(), "invalid literal")); 269 return; 270 } 271 272 Call* call = expr->AsCall(); 273 if (call != NULL) { 274 VariableProxy* proxy = call->expression()->AsVariableProxy(); 275 if (proxy != NULL) { 276 VariableInfo* info = GetVariableInfo(proxy->var(), false); 277 if (!info || 278 (!info->is_check_function && !info->is_constructor_function)) { 279 if (allow_simd_) { 280 FAIL(call->expression(), 281 "only fround/SIMD.checks allowed on expression annotations"); 282 } else { 283 FAIL(call->expression(), 284 "only fround allowed on expression annotations"); 285 } 286 } 287 Type* type = info->type; 288 DCHECK(type->IsFunction()); 289 if (info->is_check_function) { 290 DCHECK(type->AsFunction()->Arity() == 1); 291 } 292 if (call->arguments()->length() != type->AsFunction()->Arity()) { 293 FAIL(call, "invalid argument count calling function"); 294 } 295 SetResult(expr, type->AsFunction()->Result()); 296 return; 297 } 298 } 299 300 FAIL(expr, "invalid type annotation"); 301 } 302 303 304 void AsmTyper::VisitStatements(ZoneList<Statement*>* stmts) { 305 for (int i = 0; i < stmts->length(); ++i) { 306 Statement* stmt = stmts->at(i); 307 RECURSE(Visit(stmt)); 308 } 309 } 310 311 312 void AsmTyper::VisitBlock(Block* stmt) { 313 RECURSE(VisitStatements(stmt->statements())); 314 } 315 316 317 void AsmTyper::VisitExpressionStatement(ExpressionStatement* stmt) { 318 RECURSE(VisitWithExpectation(stmt->expression(), Type::Any(), 319 "expression statement expected to be any")); 320 } 321 322 323 void AsmTyper::VisitEmptyStatement(EmptyStatement* stmt) {} 324 325 326 void AsmTyper::VisitSloppyBlockFunctionStatement( 327 SloppyBlockFunctionStatement* stmt) { 328 Visit(stmt->statement()); 329 } 330 331 332 void AsmTyper::VisitEmptyParentheses(EmptyParentheses* expr) { UNREACHABLE(); } 333 334 335 void AsmTyper::VisitIfStatement(IfStatement* stmt) { 336 if (!in_function_) { 337 FAIL(stmt, "if statement inside module body"); 338 } 339 RECURSE(VisitWithExpectation(stmt->condition(), cache_.kAsmSigned, 340 "if condition expected to be integer")); 341 RECURSE(Visit(stmt->then_statement())); 342 RECURSE(Visit(stmt->else_statement())); 343 } 344 345 346 void AsmTyper::VisitContinueStatement(ContinueStatement* stmt) { 347 if (!in_function_) { 348 FAIL(stmt, "continue statement inside module body"); 349 } 350 } 351 352 353 void AsmTyper::VisitBreakStatement(BreakStatement* stmt) { 354 if (!in_function_) { 355 FAIL(stmt, "continue statement inside module body"); 356 } 357 } 358 359 360 void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) { 361 // Handle module return statement in VisitAsmModule. 362 if (!in_function_) { 363 return; 364 } 365 Literal* literal = stmt->expression()->AsLiteral(); 366 if (literal) { 367 VisitLiteral(literal, true); 368 } else { 369 RECURSE( 370 VisitWithExpectation(stmt->expression(), Type::Any(), 371 "return expression expected to have return type")); 372 } 373 if (!computed_type_->Is(return_type_) || !return_type_->Is(computed_type_)) { 374 FAIL(stmt->expression(), "return type does not match function signature"); 375 } 376 } 377 378 379 void AsmTyper::VisitWithStatement(WithStatement* stmt) { 380 FAIL(stmt, "bad with statement"); 381 } 382 383 384 void AsmTyper::VisitSwitchStatement(SwitchStatement* stmt) { 385 if (!in_function_) { 386 FAIL(stmt, "switch statement inside module body"); 387 } 388 RECURSE(VisitWithExpectation(stmt->tag(), cache_.kAsmSigned, 389 "switch expression non-integer")); 390 ZoneList<CaseClause*>* clauses = stmt->cases(); 391 ZoneSet<int32_t> cases(zone()); 392 for (int i = 0; i < clauses->length(); ++i) { 393 CaseClause* clause = clauses->at(i); 394 if (clause->is_default()) { 395 if (i != clauses->length() - 1) { 396 FAIL(clause, "default case out of order"); 397 } 398 } else { 399 Expression* label = clause->label(); 400 RECURSE(VisitWithExpectation(label, cache_.kAsmSigned, 401 "case label non-integer")); 402 if (!label->IsLiteral()) FAIL(label, "non-literal case label"); 403 Handle<Object> value = label->AsLiteral()->value(); 404 int32_t value32; 405 if (!value->ToInt32(&value32)) FAIL(label, "illegal case label value"); 406 if (cases.find(value32) != cases.end()) { 407 FAIL(label, "duplicate case value"); 408 } 409 cases.insert(value32); 410 } 411 // TODO(bradnelson): Detect duplicates. 412 ZoneList<Statement*>* stmts = clause->statements(); 413 RECURSE(VisitStatements(stmts)); 414 } 415 if (cases.size() > 0) { 416 int64_t min_case = *cases.begin(); 417 int64_t max_case = *cases.rbegin(); 418 if (max_case - min_case > std::numeric_limits<int32_t>::max()) { 419 FAIL(stmt, "case range too large"); 420 } 421 } 422 } 423 424 425 void AsmTyper::VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } 426 427 428 void AsmTyper::VisitDoWhileStatement(DoWhileStatement* stmt) { 429 if (!in_function_) { 430 FAIL(stmt, "do statement inside module body"); 431 } 432 RECURSE(Visit(stmt->body())); 433 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned, 434 "do condition expected to be integer")); 435 } 436 437 438 void AsmTyper::VisitWhileStatement(WhileStatement* stmt) { 439 if (!in_function_) { 440 FAIL(stmt, "while statement inside module body"); 441 } 442 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned, 443 "while condition expected to be integer")); 444 RECURSE(Visit(stmt->body())); 445 } 446 447 448 void AsmTyper::VisitForStatement(ForStatement* stmt) { 449 if (!in_function_) { 450 FAIL(stmt, "for statement inside module body"); 451 } 452 if (stmt->init() != NULL) { 453 RECURSE(Visit(stmt->init())); 454 } 455 if (stmt->cond() != NULL) { 456 RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned, 457 "for condition expected to be integer")); 458 } 459 if (stmt->next() != NULL) { 460 RECURSE(Visit(stmt->next())); 461 } 462 RECURSE(Visit(stmt->body())); 463 } 464 465 466 void AsmTyper::VisitForInStatement(ForInStatement* stmt) { 467 FAIL(stmt, "for-in statement encountered"); 468 } 469 470 471 void AsmTyper::VisitForOfStatement(ForOfStatement* stmt) { 472 FAIL(stmt, "for-of statement encountered"); 473 } 474 475 476 void AsmTyper::VisitTryCatchStatement(TryCatchStatement* stmt) { 477 FAIL(stmt, "try statement encountered"); 478 } 479 480 481 void AsmTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 482 FAIL(stmt, "try statement encountered"); 483 } 484 485 486 void AsmTyper::VisitDebuggerStatement(DebuggerStatement* stmt) { 487 FAIL(stmt, "debugger statement encountered"); 488 } 489 490 491 void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) { 492 Scope* scope = expr->scope(); 493 DCHECK(scope->is_function_scope()); 494 if (in_function_) { 495 FAIL(expr, "invalid nested function"); 496 } 497 498 if (!expr->bounds().upper->IsFunction()) { 499 FAIL(expr, "invalid function literal"); 500 } 501 502 Type::FunctionType* type = expr->bounds().upper->AsFunction(); 503 Type* save_return_type = return_type_; 504 return_type_ = type->Result(); 505 in_function_ = true; 506 local_variable_type_.Clear(); 507 RECURSE(VisitDeclarations(scope->declarations())); 508 RECURSE(VisitStatements(expr->body())); 509 in_function_ = false; 510 return_type_ = save_return_type; 511 IntersectResult(expr, type); 512 } 513 514 515 void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { 516 FAIL(expr, "function info literal encountered"); 517 } 518 519 520 void AsmTyper::VisitDoExpression(DoExpression* expr) { 521 FAIL(expr, "do-expression encountered"); 522 } 523 524 525 void AsmTyper::VisitConditional(Conditional* expr) { 526 RECURSE(VisitWithExpectation(expr->condition(), Type::Number(), 527 "condition expected to be integer")); 528 if (!computed_type_->Is(cache_.kAsmInt)) { 529 FAIL(expr->condition(), "condition must be of type int"); 530 } 531 532 RECURSE(VisitWithExpectation( 533 expr->then_expression(), expected_type_, 534 "conditional then branch type mismatch with enclosing expression")); 535 Type* then_type = StorageType(computed_type_); 536 if (intish_ != 0 || !then_type->Is(cache_.kAsmComparable)) { 537 FAIL(expr->then_expression(), "invalid type in ? then expression"); 538 } 539 540 RECURSE(VisitWithExpectation( 541 expr->else_expression(), expected_type_, 542 "conditional else branch type mismatch with enclosing expression")); 543 Type* else_type = StorageType(computed_type_); 544 if (intish_ != 0 || !else_type->Is(cache_.kAsmComparable)) { 545 FAIL(expr->else_expression(), "invalid type in ? else expression"); 546 } 547 548 if (!then_type->Is(else_type) || !else_type->Is(then_type)) { 549 FAIL(expr, "then and else expressions in ? must have the same type"); 550 } 551 552 IntersectResult(expr, then_type); 553 } 554 555 556 void AsmTyper::VisitVariableProxy(VariableProxy* expr) { 557 Variable* var = expr->var(); 558 VariableInfo* info = GetVariableInfo(var, false); 559 if (info == NULL || info->type == NULL) { 560 if (var->mode() == TEMPORARY) { 561 SetType(var, Type::Any(zone())); 562 info = GetVariableInfo(var, false); 563 } else { 564 FAIL(expr, "unbound variable"); 565 } 566 } 567 if (property_info_ != NULL) { 568 SetVariableInfo(var, property_info_); 569 property_info_ = NULL; 570 } 571 Type* type = Type::Intersect(info->type, expected_type_, zone()); 572 if (type->Is(cache_.kAsmInt)) { 573 type = cache_.kAsmInt; 574 } 575 info->type = type; 576 intish_ = 0; 577 IntersectResult(expr, type); 578 } 579 580 581 void AsmTyper::VisitLiteral(Literal* expr, bool is_return) { 582 intish_ = 0; 583 Handle<Object> value = expr->value(); 584 if (value->IsNumber()) { 585 int32_t i; 586 uint32_t u; 587 if (expr->raw_value()->ContainsDot()) { 588 IntersectResult(expr, cache_.kAsmDouble); 589 } else if (!is_return && value->ToUint32(&u)) { 590 if (u <= 0x7fffffff) { 591 IntersectResult(expr, cache_.kAsmFixnum); 592 } else { 593 IntersectResult(expr, cache_.kAsmUnsigned); 594 } 595 } else if (value->ToInt32(&i)) { 596 IntersectResult(expr, cache_.kAsmSigned); 597 } else { 598 FAIL(expr, "illegal number"); 599 } 600 } else if (!is_return && value->IsString()) { 601 IntersectResult(expr, Type::String()); 602 } else if (value->IsUndefined()) { 603 IntersectResult(expr, Type::Undefined()); 604 } else { 605 FAIL(expr, "illegal literal"); 606 } 607 } 608 609 610 void AsmTyper::VisitLiteral(Literal* expr) { VisitLiteral(expr, false); } 611 612 613 void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) { 614 FAIL(expr, "regular expression encountered"); 615 } 616 617 618 void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) { 619 if (in_function_) { 620 FAIL(expr, "object literal in function"); 621 } 622 // Allowed for asm module's export declaration. 623 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); 624 for (int i = 0; i < props->length(); ++i) { 625 ObjectLiteralProperty* prop = props->at(i); 626 RECURSE(VisitWithExpectation(prop->value(), Type::Any(zone()), 627 "object property expected to be a function")); 628 if (!computed_type_->IsFunction()) { 629 FAIL(prop->value(), "non-function in function table"); 630 } 631 } 632 IntersectResult(expr, Type::Object(zone())); 633 } 634 635 636 void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) { 637 if (in_function_) { 638 FAIL(expr, "array literal inside a function"); 639 } 640 // Allowed for function tables. 641 ZoneList<Expression*>* values = expr->values(); 642 Type* elem_type = Type::None(zone()); 643 for (int i = 0; i < values->length(); ++i) { 644 Expression* value = values->at(i); 645 RECURSE(VisitWithExpectation(value, Type::Any(), "UNREACHABLE")); 646 if (!computed_type_->IsFunction()) { 647 FAIL(value, "array component expected to be a function"); 648 } 649 elem_type = Type::Union(elem_type, computed_type_, zone()); 650 } 651 array_size_ = values->length(); 652 IntersectResult(expr, Type::Array(elem_type, zone())); 653 } 654 655 656 void AsmTyper::VisitAssignment(Assignment* expr) { 657 // Handle function tables and everything else in different passes. 658 if (!in_function_) { 659 if (expr->value()->IsArrayLiteral()) { 660 if (!building_function_tables_) { 661 return; 662 } 663 } else { 664 if (building_function_tables_) { 665 return; 666 } 667 } 668 } 669 if (expr->is_compound()) FAIL(expr, "compound assignment encountered"); 670 Type* type = expected_type_; 671 RECURSE(VisitWithExpectation( 672 expr->value(), type, "assignment value expected to match surrounding")); 673 Type* target_type = StorageType(computed_type_); 674 if (intish_ != 0) { 675 FAIL(expr, "intish or floatish assignment"); 676 } 677 if (expr->target()->IsVariableProxy()) { 678 RECURSE(VisitWithExpectation(expr->target(), target_type, 679 "assignment target expected to match value")); 680 } else if (expr->target()->IsProperty()) { 681 Property* property = expr->target()->AsProperty(); 682 RECURSE(VisitWithExpectation(property->obj(), Type::Any(), 683 "bad propety object")); 684 if (!computed_type_->IsArray()) { 685 FAIL(property->obj(), "array expected"); 686 } 687 VisitHeapAccess(property, true, target_type); 688 } 689 IntersectResult(expr, target_type); 690 } 691 692 693 void AsmTyper::VisitYield(Yield* expr) { 694 FAIL(expr, "yield expression encountered"); 695 } 696 697 698 void AsmTyper::VisitThrow(Throw* expr) { 699 FAIL(expr, "throw statement encountered"); 700 } 701 702 703 int AsmTyper::ElementShiftSize(Type* type) { 704 if (type->Is(cache_.kAsmSize8)) return 0; 705 if (type->Is(cache_.kAsmSize16)) return 1; 706 if (type->Is(cache_.kAsmSize32)) return 2; 707 if (type->Is(cache_.kAsmSize64)) return 3; 708 return -1; 709 } 710 711 712 Type* AsmTyper::StorageType(Type* type) { 713 if (type->Is(cache_.kAsmInt)) { 714 return cache_.kAsmInt; 715 } else { 716 return type; 717 } 718 } 719 720 721 void AsmTyper::VisitHeapAccess(Property* expr, bool assigning, 722 Type* assignment_type) { 723 Type::ArrayType* array_type = computed_type_->AsArray(); 724 size_t size = array_size_; 725 Type* type = array_type->AsArray()->Element(); 726 if (type->IsFunction()) { 727 if (assigning) { 728 FAIL(expr, "assigning to function table is illegal"); 729 } 730 BinaryOperation* bin = expr->key()->AsBinaryOperation(); 731 if (bin == NULL || bin->op() != Token::BIT_AND) { 732 FAIL(expr->key(), "expected & in call"); 733 } 734 RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned, 735 "array index expected to be integer")); 736 Literal* right = bin->right()->AsLiteral(); 737 if (right == NULL || right->raw_value()->ContainsDot()) { 738 FAIL(right, "call mask must be integer"); 739 } 740 RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned, 741 "call mask expected to be integer")); 742 if (static_cast<size_t>(right->raw_value()->AsNumber()) != size - 1) { 743 FAIL(right, "call mask must match function table"); 744 } 745 bin->set_bounds(Bounds(cache_.kAsmSigned)); 746 IntersectResult(expr, type); 747 } else { 748 Literal* literal = expr->key()->AsLiteral(); 749 if (literal) { 750 RECURSE(VisitWithExpectation(literal, cache_.kAsmSigned, 751 "array index expected to be integer")); 752 } else { 753 BinaryOperation* bin = expr->key()->AsBinaryOperation(); 754 if (bin == NULL || bin->op() != Token::SAR) { 755 FAIL(expr->key(), "expected >> in heap access"); 756 } 757 RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned, 758 "array index expected to be integer")); 759 Literal* right = bin->right()->AsLiteral(); 760 if (right == NULL || right->raw_value()->ContainsDot()) { 761 FAIL(right, "heap access shift must be integer"); 762 } 763 RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned, 764 "array shift expected to be integer")); 765 int n = static_cast<int>(right->raw_value()->AsNumber()); 766 int expected_shift = ElementShiftSize(type); 767 if (expected_shift < 0 || n != expected_shift) { 768 FAIL(right, "heap access shift must match element size"); 769 } 770 bin->set_bounds(Bounds(cache_.kAsmSigned)); 771 } 772 Type* result_type; 773 if (type->Is(cache_.kAsmIntArrayElement)) { 774 result_type = cache_.kAsmIntQ; 775 intish_ = kMaxUncombinedAdditiveSteps; 776 } else if (type->Is(cache_.kAsmFloat)) { 777 if (assigning) { 778 result_type = cache_.kAsmFloatDoubleQ; 779 } else { 780 result_type = cache_.kAsmFloatQ; 781 } 782 intish_ = 0; 783 } else if (type->Is(cache_.kAsmDouble)) { 784 if (assigning) { 785 result_type = cache_.kAsmFloatDoubleQ; 786 if (intish_ != 0) { 787 FAIL(expr, "Assignment of floatish to Float64Array"); 788 } 789 } else { 790 result_type = cache_.kAsmDoubleQ; 791 } 792 intish_ = 0; 793 } else { 794 UNREACHABLE(); 795 } 796 if (assigning) { 797 if (!assignment_type->Is(result_type)) { 798 FAIL(expr, "illegal type in assignment"); 799 } 800 } else { 801 IntersectResult(expr, expected_type_); 802 IntersectResult(expr, result_type); 803 } 804 } 805 } 806 807 808 bool AsmTyper::IsStdlibObject(Expression* expr) { 809 VariableProxy* proxy = expr->AsVariableProxy(); 810 if (proxy == NULL) { 811 return false; 812 } 813 Variable* var = proxy->var(); 814 VariableInfo* info = GetVariableInfo(var, false); 815 if (info) { 816 if (info->standard_member == kStdlib) return true; 817 } 818 if (var->location() != VariableLocation::PARAMETER || var->index() != 0) { 819 return false; 820 } 821 info = GetVariableInfo(var, true); 822 info->type = Type::Object(); 823 info->standard_member = kStdlib; 824 return true; 825 } 826 827 828 Expression* AsmTyper::GetReceiverOfPropertyAccess(Expression* expr, 829 const char* name) { 830 Property* property = expr->AsProperty(); 831 if (property == NULL) { 832 return NULL; 833 } 834 Literal* key = property->key()->AsLiteral(); 835 if (key == NULL || !key->IsPropertyName() || 836 !key->AsPropertyName()->IsUtf8EqualTo(CStrVector(name))) { 837 return NULL; 838 } 839 return property->obj(); 840 } 841 842 843 bool AsmTyper::IsMathObject(Expression* expr) { 844 Expression* obj = GetReceiverOfPropertyAccess(expr, "Math"); 845 return obj && IsStdlibObject(obj); 846 } 847 848 849 bool AsmTyper::IsSIMDObject(Expression* expr) { 850 Expression* obj = GetReceiverOfPropertyAccess(expr, "SIMD"); 851 return obj && IsStdlibObject(obj); 852 } 853 854 855 bool AsmTyper::IsSIMDTypeObject(Expression* expr, const char* name) { 856 Expression* obj = GetReceiverOfPropertyAccess(expr, name); 857 return obj && IsSIMDObject(obj); 858 } 859 860 861 void AsmTyper::VisitProperty(Property* expr) { 862 if (IsMathObject(expr->obj())) { 863 VisitLibraryAccess(&stdlib_math_types_, expr); 864 return; 865 } 866 #define V(NAME, Name, name, lane_count, lane_type) \ 867 if (IsSIMDTypeObject(expr->obj(), #Name)) { \ 868 VisitLibraryAccess(&stdlib_simd_##name##_types_, expr); \ 869 return; \ 870 } \ 871 if (IsSIMDTypeObject(expr, #Name)) { \ 872 VariableInfo* info = stdlib_simd_##name##_constructor_type_; \ 873 SetResult(expr, info->type); \ 874 property_info_ = info; \ 875 return; \ 876 } 877 SIMD128_TYPES(V) 878 #undef V 879 if (IsStdlibObject(expr->obj())) { 880 VisitLibraryAccess(&stdlib_types_, expr); 881 return; 882 } 883 884 property_info_ = NULL; 885 886 // Only recurse at this point so that we avoid needing 887 // stdlib.Math to have a real type. 888 RECURSE(VisitWithExpectation(expr->obj(), Type::Any(), "bad propety object")); 889 890 // For heap view or function table access. 891 if (computed_type_->IsArray()) { 892 VisitHeapAccess(expr, false, NULL); 893 return; 894 } 895 896 // stdlib.x or foreign.x 897 VariableProxy* proxy = expr->obj()->AsVariableProxy(); 898 if (proxy != NULL) { 899 Variable* var = proxy->var(); 900 if (var->location() == VariableLocation::PARAMETER && var->index() == 1) { 901 // foreign.x is ok. 902 SetResult(expr, expected_type_); 903 return; 904 } 905 } 906 907 FAIL(expr, "invalid property access"); 908 } 909 910 911 void AsmTyper::VisitCall(Call* expr) { 912 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), 913 "callee expected to be any")); 914 StandardMember standard_member = kNone; 915 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 916 if (proxy) { 917 standard_member = VariableAsStandardMember(proxy->var()); 918 } 919 if (!in_function_ && (proxy == NULL || standard_member != kMathFround)) { 920 FAIL(expr, "calls forbidden outside function bodies"); 921 } 922 if (proxy == NULL && !expr->expression()->IsProperty()) { 923 FAIL(expr, "calls must be to bound variables or function tables"); 924 } 925 if (computed_type_->IsFunction()) { 926 Type::FunctionType* fun_type = computed_type_->AsFunction(); 927 Type* result_type = fun_type->Result(); 928 ZoneList<Expression*>* args = expr->arguments(); 929 if (fun_type->Arity() != args->length()) { 930 FAIL(expr, "call with wrong arity"); 931 } 932 for (int i = 0; i < args->length(); ++i) { 933 Expression* arg = args->at(i); 934 RECURSE(VisitWithExpectation( 935 arg, fun_type->Parameter(i), 936 "call argument expected to match callee parameter")); 937 if (standard_member != kNone && standard_member != kMathFround && 938 i == 0) { 939 result_type = computed_type_; 940 } 941 } 942 // Handle polymorphic stdlib functions specially. 943 if (standard_member == kMathCeil || standard_member == kMathFloor || 944 standard_member == kMathSqrt) { 945 if (!args->at(0)->bounds().upper->Is(cache_.kAsmFloat) && 946 !args->at(0)->bounds().upper->Is(cache_.kAsmDouble)) { 947 FAIL(expr, "illegal function argument type"); 948 } 949 } else if (standard_member == kMathAbs || standard_member == kMathMin || 950 standard_member == kMathMax) { 951 if (!args->at(0)->bounds().upper->Is(cache_.kAsmFloat) && 952 !args->at(0)->bounds().upper->Is(cache_.kAsmDouble) && 953 !args->at(0)->bounds().upper->Is(cache_.kAsmSigned)) { 954 FAIL(expr, "illegal function argument type"); 955 } 956 if (args->length() > 1) { 957 Type* other = Type::Intersect(args->at(0)->bounds().upper, 958 args->at(1)->bounds().upper, zone()); 959 if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) && 960 !other->Is(cache_.kAsmSigned)) { 961 FAIL(expr, "function arguments types don't match"); 962 } 963 } 964 } 965 intish_ = 0; 966 IntersectResult(expr, result_type); 967 } else if (computed_type_->Is(Type::Any())) { 968 // For foreign calls. 969 ZoneList<Expression*>* args = expr->arguments(); 970 for (int i = 0; i < args->length(); ++i) { 971 Expression* arg = args->at(i); 972 RECURSE(VisitWithExpectation(arg, Type::Any(), 973 "foreign call argument expected to be any")); 974 } 975 intish_ = kMaxUncombinedAdditiveSteps; 976 IntersectResult(expr, Type::Number()); 977 } else { 978 FAIL(expr, "invalid callee"); 979 } 980 } 981 982 983 void AsmTyper::VisitCallNew(CallNew* expr) { 984 if (in_function_) { 985 FAIL(expr, "new not allowed in module function"); 986 } 987 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), 988 "expected stdlib function")); 989 if (computed_type_->IsFunction()) { 990 Type::FunctionType* fun_type = computed_type_->AsFunction(); 991 ZoneList<Expression*>* args = expr->arguments(); 992 if (fun_type->Arity() != args->length()) 993 FAIL(expr, "call with wrong arity"); 994 for (int i = 0; i < args->length(); ++i) { 995 Expression* arg = args->at(i); 996 RECURSE(VisitWithExpectation( 997 arg, fun_type->Parameter(i), 998 "constructor argument expected to match callee parameter")); 999 } 1000 IntersectResult(expr, fun_type->Result()); 1001 return; 1002 } 1003 1004 FAIL(expr, "ill-typed new operator"); 1005 } 1006 1007 1008 void AsmTyper::VisitCallRuntime(CallRuntime* expr) { 1009 // Allow runtime calls for now. 1010 } 1011 1012 1013 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) { 1014 switch (expr->op()) { 1015 case Token::NOT: // Used to encode != and !== 1016 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt, 1017 "operand expected to be integer")); 1018 IntersectResult(expr, cache_.kAsmSigned); 1019 return; 1020 case Token::DELETE: 1021 FAIL(expr, "delete operator encountered"); 1022 case Token::VOID: 1023 FAIL(expr, "void operator encountered"); 1024 case Token::TYPEOF: 1025 FAIL(expr, "typeof operator encountered"); 1026 default: 1027 UNREACHABLE(); 1028 } 1029 } 1030 1031 1032 void AsmTyper::VisitCountOperation(CountOperation* expr) { 1033 FAIL(expr, "increment or decrement operator encountered"); 1034 } 1035 1036 1037 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr, 1038 Type* left_expected, 1039 Type* right_expected, 1040 Type* result_type, bool conversion) { 1041 RECURSE(VisitWithExpectation(expr->left(), Type::Number(), 1042 "left bitwise operand expected to be a number")); 1043 int left_intish = intish_; 1044 Type* left_type = computed_type_; 1045 if (!left_type->Is(left_expected)) { 1046 FAIL(expr->left(), "left bitwise operand expected to be an integer"); 1047 } 1048 if (left_intish > kMaxUncombinedAdditiveSteps) { 1049 FAIL(expr->left(), "too many consecutive additive ops"); 1050 } 1051 1052 RECURSE( 1053 VisitWithExpectation(expr->right(), Type::Number(), 1054 "right bitwise operand expected to be a number")); 1055 int right_intish = intish_; 1056 Type* right_type = computed_type_; 1057 if (!right_type->Is(right_expected)) { 1058 FAIL(expr->right(), "right bitwise operand expected to be an integer"); 1059 } 1060 if (right_intish > kMaxUncombinedAdditiveSteps) { 1061 FAIL(expr->right(), "too many consecutive additive ops"); 1062 } 1063 1064 intish_ = 0; 1065 1066 if (left_type->Is(cache_.kAsmFixnum) && right_type->Is(cache_.kAsmInt)) { 1067 left_type = right_type; 1068 } 1069 if (right_type->Is(cache_.kAsmFixnum) && left_type->Is(cache_.kAsmInt)) { 1070 right_type = left_type; 1071 } 1072 if (!conversion) { 1073 if (!left_type->Is(right_type) || !right_type->Is(left_type)) { 1074 FAIL(expr, "ill-typed bitwise operation"); 1075 } 1076 } 1077 IntersectResult(expr, result_type); 1078 } 1079 1080 1081 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { 1082 switch (expr->op()) { 1083 case Token::COMMA: { 1084 RECURSE(VisitWithExpectation(expr->left(), Type::Any(), 1085 "left comma operand expected to be any")); 1086 RECURSE(VisitWithExpectation(expr->right(), Type::Any(), 1087 "right comma operand expected to be any")); 1088 IntersectResult(expr, computed_type_); 1089 return; 1090 } 1091 case Token::OR: 1092 case Token::AND: 1093 FAIL(expr, "illegal logical operator"); 1094 case Token::BIT_OR: { 1095 // BIT_OR allows Any since it is used as a type coercion. 1096 VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmInt, 1097 cache_.kAsmSigned, true); 1098 return; 1099 } 1100 case Token::BIT_XOR: { 1101 // Handle booleans specially to handle de-sugared ! 1102 Literal* left = expr->left()->AsLiteral(); 1103 if (left && left->value()->IsBoolean()) { 1104 if (left->ToBooleanIsTrue()) { 1105 left->set_bounds(Bounds(cache_.kSingletonOne)); 1106 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmInt, 1107 "not operator expects an integer")); 1108 IntersectResult(expr, cache_.kAsmSigned); 1109 return; 1110 } else { 1111 FAIL(left, "unexpected false"); 1112 } 1113 } 1114 // BIT_XOR allows Number since it is used as a type coercion (via ~~). 1115 VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kAsmInt, 1116 cache_.kAsmSigned, true); 1117 return; 1118 } 1119 case Token::SHR: { 1120 VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, 1121 cache_.kAsmUnsigned, false); 1122 return; 1123 } 1124 case Token::SHL: 1125 case Token::SAR: 1126 case Token::BIT_AND: { 1127 VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, 1128 cache_.kAsmSigned, false); 1129 return; 1130 } 1131 case Token::ADD: 1132 case Token::SUB: 1133 case Token::MUL: 1134 case Token::DIV: 1135 case Token::MOD: { 1136 RECURSE(VisitWithExpectation( 1137 expr->left(), Type::Number(), 1138 "left arithmetic operand expected to be number")); 1139 Type* left_type = computed_type_; 1140 int left_intish = intish_; 1141 RECURSE(VisitWithExpectation( 1142 expr->right(), Type::Number(), 1143 "right arithmetic operand expected to be number")); 1144 Type* right_type = computed_type_; 1145 int right_intish = intish_; 1146 Type* type = Type::Union(left_type, right_type, zone()); 1147 if (type->Is(cache_.kAsmInt)) { 1148 if (expr->op() == Token::MUL) { 1149 Literal* right = expr->right()->AsLiteral(); 1150 if (!right) { 1151 FAIL(expr, "direct integer multiply forbidden"); 1152 } 1153 if (!right->value()->IsNumber()) { 1154 FAIL(expr, "multiply must be by an integer"); 1155 } 1156 int32_t i; 1157 if (!right->value()->ToInt32(&i)) { 1158 FAIL(expr, "multiply must be a signed integer"); 1159 } 1160 i = abs(i); 1161 if (i >= 1 << 20) { 1162 FAIL(expr, "multiply must be by value in -2^20 < n < 2^20"); 1163 } 1164 intish_ = i; 1165 IntersectResult(expr, cache_.kAsmInt); 1166 return; 1167 } else { 1168 intish_ = left_intish + right_intish + 1; 1169 if (expr->op() == Token::ADD || expr->op() == Token::SUB) { 1170 if (intish_ > kMaxUncombinedAdditiveSteps) { 1171 FAIL(expr, "too many consecutive additive ops"); 1172 } 1173 } else { 1174 if (intish_ > kMaxUncombinedMultiplicativeSteps) { 1175 FAIL(expr, "too many consecutive multiplicative ops"); 1176 } 1177 } 1178 IntersectResult(expr, cache_.kAsmInt); 1179 return; 1180 } 1181 } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() && 1182 right_type->Is(cache_.kAsmDouble)) { 1183 // For unary +, expressed as x * 1.0 1184 IntersectResult(expr, cache_.kAsmDouble); 1185 return; 1186 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) { 1187 if (left_intish != 0 || right_intish != 0) { 1188 FAIL(expr, "float operation before required fround"); 1189 } 1190 IntersectResult(expr, cache_.kAsmFloat); 1191 intish_ = 1; 1192 return; 1193 } else if (type->Is(cache_.kAsmDouble)) { 1194 IntersectResult(expr, cache_.kAsmDouble); 1195 return; 1196 } else { 1197 FAIL(expr, "ill-typed arithmetic operation"); 1198 } 1199 } 1200 default: 1201 UNREACHABLE(); 1202 } 1203 } 1204 1205 1206 void AsmTyper::VisitCompareOperation(CompareOperation* expr) { 1207 Token::Value op = expr->op(); 1208 if (op != Token::EQ && op != Token::NE && op != Token::LT && 1209 op != Token::LTE && op != Token::GT && op != Token::GTE) { 1210 FAIL(expr, "illegal comparison operator"); 1211 } 1212 1213 RECURSE( 1214 VisitWithExpectation(expr->left(), Type::Number(), 1215 "left comparison operand expected to be number")); 1216 Type* left_type = computed_type_; 1217 if (!left_type->Is(cache_.kAsmComparable)) { 1218 FAIL(expr->left(), "bad type on left side of comparison"); 1219 } 1220 1221 RECURSE( 1222 VisitWithExpectation(expr->right(), Type::Number(), 1223 "right comparison operand expected to be number")); 1224 Type* right_type = computed_type_; 1225 if (!right_type->Is(cache_.kAsmComparable)) { 1226 FAIL(expr->right(), "bad type on right side of comparison"); 1227 } 1228 1229 if (!left_type->Is(right_type) && !right_type->Is(left_type)) { 1230 FAIL(expr, "left and right side of comparison must match"); 1231 } 1232 1233 IntersectResult(expr, cache_.kAsmSigned); 1234 } 1235 1236 1237 void AsmTyper::VisitThisFunction(ThisFunction* expr) { 1238 FAIL(expr, "this function not allowed"); 1239 } 1240 1241 1242 void AsmTyper::VisitDeclarations(ZoneList<Declaration*>* decls) { 1243 for (int i = 0; i < decls->length(); ++i) { 1244 Declaration* decl = decls->at(i); 1245 RECURSE(Visit(decl)); 1246 } 1247 } 1248 1249 1250 void AsmTyper::VisitImportDeclaration(ImportDeclaration* decl) { 1251 FAIL(decl, "import declaration encountered"); 1252 } 1253 1254 1255 void AsmTyper::VisitExportDeclaration(ExportDeclaration* decl) { 1256 FAIL(decl, "export declaration encountered"); 1257 } 1258 1259 1260 void AsmTyper::VisitClassLiteral(ClassLiteral* expr) { 1261 FAIL(expr, "class literal not allowed"); 1262 } 1263 1264 1265 void AsmTyper::VisitSpread(Spread* expr) { FAIL(expr, "spread not allowed"); } 1266 1267 1268 void AsmTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) { 1269 FAIL(expr, "super property reference not allowed"); 1270 } 1271 1272 1273 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) { 1274 FAIL(expr, "call reference not allowed"); 1275 } 1276 1277 1278 void AsmTyper::InitializeStdlibSIMD() { 1279 #define V(NAME, Name, name, lane_count, lane_type) \ 1280 { \ 1281 Type* type = Type::Function(Type::Name(isolate_, zone()), Type::Any(), \ 1282 lane_count, zone()); \ 1283 for (int i = 0; i < lane_count; ++i) { \ 1284 type->AsFunction()->InitParameter(i, Type::Number()); \ 1285 } \ 1286 stdlib_simd_##name##_constructor_type_ = new (zone()) VariableInfo(type); \ 1287 stdlib_simd_##name##_constructor_type_->is_constructor_function = true; \ 1288 } 1289 SIMD128_TYPES(V) 1290 #undef V 1291 } 1292 1293 1294 void AsmTyper::InitializeStdlib() { 1295 if (allow_simd_) { 1296 InitializeStdlibSIMD(); 1297 } 1298 Type* number_type = Type::Number(zone()); 1299 Type* double_type = cache_.kAsmDouble; 1300 Type* double_fn1_type = Type::Function(double_type, double_type, zone()); 1301 Type* double_fn2_type = 1302 Type::Function(double_type, double_type, double_type, zone()); 1303 1304 Type* fround_type = Type::Function(cache_.kAsmFloat, number_type, zone()); 1305 Type* imul_type = 1306 Type::Function(cache_.kAsmSigned, cache_.kAsmInt, cache_.kAsmInt, zone()); 1307 // TODO(bradnelson): currently only approximating the proper intersection type 1308 // (which we cannot currently represent). 1309 Type* number_fn1_type = Type::Function(number_type, number_type, zone()); 1310 Type* number_fn2_type = 1311 Type::Function(number_type, number_type, number_type, zone()); 1312 1313 struct Assignment { 1314 const char* name; 1315 StandardMember standard_member; 1316 Type* type; 1317 }; 1318 1319 const Assignment math[] = {{"PI", kMathPI, double_type}, 1320 {"E", kMathE, double_type}, 1321 {"LN2", kMathLN2, double_type}, 1322 {"LN10", kMathLN10, double_type}, 1323 {"LOG2E", kMathLOG2E, double_type}, 1324 {"LOG10E", kMathLOG10E, double_type}, 1325 {"SQRT2", kMathSQRT2, double_type}, 1326 {"SQRT1_2", kMathSQRT1_2, double_type}, 1327 {"imul", kMathImul, imul_type}, 1328 {"abs", kMathAbs, number_fn1_type}, 1329 {"ceil", kMathCeil, number_fn1_type}, 1330 {"floor", kMathFloor, number_fn1_type}, 1331 {"fround", kMathFround, fround_type}, 1332 {"pow", kMathPow, double_fn2_type}, 1333 {"exp", kMathExp, double_fn1_type}, 1334 {"log", kMathLog, double_fn1_type}, 1335 {"min", kMathMin, number_fn2_type}, 1336 {"max", kMathMax, number_fn2_type}, 1337 {"sqrt", kMathSqrt, number_fn1_type}, 1338 {"cos", kMathCos, double_fn1_type}, 1339 {"sin", kMathSin, double_fn1_type}, 1340 {"tan", kMathTan, double_fn1_type}, 1341 {"acos", kMathAcos, double_fn1_type}, 1342 {"asin", kMathAsin, double_fn1_type}, 1343 {"atan", kMathAtan, double_fn1_type}, 1344 {"atan2", kMathAtan2, double_fn2_type}}; 1345 for (unsigned i = 0; i < arraysize(math); ++i) { 1346 stdlib_math_types_[math[i].name] = new (zone()) VariableInfo(math[i].type); 1347 stdlib_math_types_[math[i].name]->standard_member = math[i].standard_member; 1348 } 1349 stdlib_math_types_["fround"]->is_check_function = true; 1350 1351 stdlib_types_["Infinity"] = new (zone()) VariableInfo(double_type); 1352 stdlib_types_["Infinity"]->standard_member = kInfinity; 1353 stdlib_types_["NaN"] = new (zone()) VariableInfo(double_type); 1354 stdlib_types_["NaN"]->standard_member = kNaN; 1355 Type* buffer_type = Type::Any(zone()); 1356 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \ 1357 stdlib_types_[#TypeName "Array"] = new (zone()) VariableInfo( \ 1358 Type::Function(cache_.k##TypeName##Array, buffer_type, zone())); 1359 TYPED_ARRAYS(TYPED_ARRAY) 1360 #undef TYPED_ARRAY 1361 1362 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \ 1363 stdlib_heap_types_[#TypeName "Array"] = new (zone()) VariableInfo( \ 1364 Type::Function(cache_.k##TypeName##Array, buffer_type, zone())); 1365 TYPED_ARRAYS(TYPED_ARRAY) 1366 #undef TYPED_ARRAY 1367 } 1368 1369 1370 void AsmTyper::VisitLibraryAccess(ObjectTypeMap* map, Property* expr) { 1371 Literal* key = expr->key()->AsLiteral(); 1372 if (key == NULL || !key->IsPropertyName()) 1373 FAIL(expr, "invalid key used on stdlib member"); 1374 Handle<String> name = key->AsPropertyName(); 1375 VariableInfo* info = LibType(map, name); 1376 if (info == NULL || info->type == NULL) FAIL(expr, "unknown stdlib function"); 1377 SetResult(expr, info->type); 1378 property_info_ = info; 1379 } 1380 1381 1382 AsmTyper::VariableInfo* AsmTyper::LibType(ObjectTypeMap* map, 1383 Handle<String> name) { 1384 base::SmartArrayPointer<char> aname = name->ToCString(); 1385 ObjectTypeMap::iterator i = map->find(std::string(aname.get())); 1386 if (i == map->end()) { 1387 return NULL; 1388 } 1389 return i->second; 1390 } 1391 1392 1393 void AsmTyper::SetType(Variable* variable, Type* type) { 1394 VariableInfo* info = GetVariableInfo(variable, true); 1395 info->type = type; 1396 } 1397 1398 1399 Type* AsmTyper::GetType(Variable* variable) { 1400 VariableInfo* info = GetVariableInfo(variable, false); 1401 if (!info) return NULL; 1402 return info->type; 1403 } 1404 1405 1406 AsmTyper::VariableInfo* AsmTyper::GetVariableInfo(Variable* variable, 1407 bool setting) { 1408 ZoneHashMap::Entry* entry; 1409 ZoneHashMap* map; 1410 if (in_function_) { 1411 map = &local_variable_type_; 1412 } else { 1413 map = &global_variable_type_; 1414 } 1415 if (setting) { 1416 entry = map->LookupOrInsert(variable, ComputePointerHash(variable), 1417 ZoneAllocationPolicy(zone())); 1418 } else { 1419 entry = map->Lookup(variable, ComputePointerHash(variable)); 1420 if (!entry && in_function_) { 1421 entry = 1422 global_variable_type_.Lookup(variable, ComputePointerHash(variable)); 1423 if (entry && entry->value) { 1424 } 1425 } 1426 } 1427 if (!entry) return NULL; 1428 if (!entry->value) { 1429 if (!setting) return NULL; 1430 entry->value = new (zone()) VariableInfo; 1431 } 1432 return reinterpret_cast<VariableInfo*>(entry->value); 1433 } 1434 1435 1436 void AsmTyper::SetVariableInfo(Variable* variable, const VariableInfo* info) { 1437 VariableInfo* dest = GetVariableInfo(variable, true); 1438 dest->type = info->type; 1439 dest->is_check_function = info->is_check_function; 1440 dest->is_constructor_function = info->is_constructor_function; 1441 dest->standard_member = info->standard_member; 1442 } 1443 1444 1445 AsmTyper::StandardMember AsmTyper::VariableAsStandardMember( 1446 Variable* variable) { 1447 VariableInfo* info = GetVariableInfo(variable, false); 1448 if (!info) return kNone; 1449 return info->standard_member; 1450 } 1451 1452 1453 void AsmTyper::SetResult(Expression* expr, Type* type) { 1454 computed_type_ = type; 1455 expr->set_bounds(Bounds(computed_type_)); 1456 } 1457 1458 1459 void AsmTyper::IntersectResult(Expression* expr, Type* type) { 1460 computed_type_ = type; 1461 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); 1462 expr->set_bounds(Bounds(bounded_type)); 1463 } 1464 1465 1466 void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type, 1467 const char* msg) { 1468 Type* save = expected_type_; 1469 expected_type_ = expected_type; 1470 RECURSE(Visit(expr)); 1471 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); 1472 if (bounded_type->Is(Type::None(zone()))) { 1473 #ifdef DEBUG 1474 PrintF("Computed type: "); 1475 computed_type_->Print(); 1476 PrintF("Expected type: "); 1477 expected_type_->Print(); 1478 #endif 1479 FAIL(expr, msg); 1480 } 1481 expected_type_ = save; 1482 } 1483 1484 1485 void AsmTyper::VisitRewritableAssignmentExpression( 1486 RewritableAssignmentExpression* expr) { 1487 RECURSE(Visit(expr->expression())); 1488 } 1489 1490 1491 } // namespace internal 1492 } // namespace v8 1493