| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/typing-asm.h" | 5 #include "src/typing-asm.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "src/v8.h" | 9 #include "src/v8.h" |
| 10 | 10 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 | 29 |
| 30 | 30 |
| 31 #define RECURSE(call) \ | 31 #define RECURSE(call) \ |
| 32 do { \ | 32 do { \ |
| 33 DCHECK(!HasStackOverflow()); \ | 33 DCHECK(!HasStackOverflow()); \ |
| 34 call; \ | 34 call; \ |
| 35 if (HasStackOverflow()) return; \ | 35 if (HasStackOverflow()) return; \ |
| 36 if (!valid_) return; \ | 36 if (!valid_) return; \ |
| 37 } while (false) | 37 } while (false) |
| 38 | 38 |
| 39 | |
| 40 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, | 39 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, |
| 41 FunctionLiteral* root) | 40 FunctionLiteral* root) |
| 42 : zone_(zone), | 41 : zone_(zone), |
| 43 isolate_(isolate), | 42 isolate_(isolate), |
| 44 script_(script), | 43 script_(script), |
| 45 root_(root), | 44 root_(root), |
| 46 valid_(true), | 45 valid_(true), |
| 47 allow_simd_(false), | 46 allow_simd_(false), |
| 48 property_info_(NULL), | 47 property_info_(NULL), |
| 49 intish_(0), | 48 intish_(0), |
| 50 stdlib_types_(zone), | 49 stdlib_types_(zone), |
| 51 stdlib_heap_types_(zone), | 50 stdlib_heap_types_(zone), |
| 52 stdlib_math_types_(zone), | 51 stdlib_math_types_(zone), |
| 53 #define V(NAME, Name, name, lane_count, lane_type) \ | 52 #define V(NAME, Name, name, lane_count, lane_type) \ |
| 54 stdlib_simd_##name##_types_(zone), | 53 stdlib_simd_##name##_types_(zone), |
| 55 SIMD128_TYPES(V) | 54 SIMD128_TYPES(V) |
| 56 #undef V | 55 #undef V |
| 57 global_variable_type_(HashMap::PointersMatch, | 56 global_variable_type_(HashMap::PointersMatch, |
| 58 ZoneHashMap::kDefaultHashMapCapacity, | 57 ZoneHashMap::kDefaultHashMapCapacity, |
| 59 ZoneAllocationPolicy(zone)), | 58 ZoneAllocationPolicy(zone)), |
| 60 local_variable_type_(HashMap::PointersMatch, | 59 local_variable_type_(HashMap::PointersMatch, |
| 61 ZoneHashMap::kDefaultHashMapCapacity, | 60 ZoneHashMap::kDefaultHashMapCapacity, |
| 62 ZoneAllocationPolicy(zone)), | 61 ZoneAllocationPolicy(zone)), |
| 63 in_function_(false), | 62 in_function_(false), |
| 64 building_function_tables_(false), | 63 building_function_tables_(false), |
| 64 visiting_exports_(false), |
| 65 cache_(TypeCache::Get()) { | 65 cache_(TypeCache::Get()) { |
| 66 InitializeAstVisitor(isolate); | 66 InitializeAstVisitor(isolate); |
| 67 InitializeStdlib(); | 67 InitializeStdlib(); |
| 68 } | 68 } |
| 69 | 69 |
| 70 | 70 |
| 71 bool AsmTyper::Validate() { | 71 bool AsmTyper::Validate() { |
| 72 VisitAsmModule(root_); | 72 VisitAsmModule(root_); |
| 73 return valid_ && !HasStackOverflow(); | 73 return valid_ && !HasStackOverflow(); |
| 74 } | 74 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 if (decl != NULL) { | 128 if (decl != NULL) { |
| 129 RECURSE( | 129 RECURSE( |
| 130 VisitWithExpectation(decl->fun(), Type::Any(zone()), "UNREACHABLE")); | 130 VisitWithExpectation(decl->fun(), Type::Any(zone()), "UNREACHABLE")); |
| 131 if (!computed_type_->IsFunction()) { | 131 if (!computed_type_->IsFunction()) { |
| 132 FAIL(decl->fun(), "function literal expected to be a function"); | 132 FAIL(decl->fun(), "function literal expected to be a function"); |
| 133 } | 133 } |
| 134 } | 134 } |
| 135 } | 135 } |
| 136 | 136 |
| 137 // Validate exports. | 137 // Validate exports. |
| 138 visiting_exports_ = true; |
| 138 ReturnStatement* stmt = fun->body()->last()->AsReturnStatement(); | 139 ReturnStatement* stmt = fun->body()->last()->AsReturnStatement(); |
| 139 if (stmt == nullptr) { | 140 if (stmt == nullptr) { |
| 140 FAIL(fun->body()->last(), "last statement in module is not a return"); | 141 FAIL(fun->body()->last(), "last statement in module is not a return"); |
| 141 } | 142 } |
| 142 RECURSE(VisitWithExpectation(stmt->expression(), Type::Object(), | 143 RECURSE(VisitWithExpectation(stmt->expression(), Type::Object(), |
| 143 "expected object export")); | 144 "expected object export")); |
| 144 } | 145 } |
| 145 | 146 |
| 146 | 147 |
| 147 void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) { | 148 void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 171 | 172 |
| 172 void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { | 173 void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
| 173 // Extract result type. | 174 // Extract result type. |
| 174 ZoneList<Statement*>* body = fun->body(); | 175 ZoneList<Statement*>* body = fun->body(); |
| 175 Type* result_type = Type::Undefined(zone()); | 176 Type* result_type = Type::Undefined(zone()); |
| 176 if (body->length() > 0) { | 177 if (body->length() > 0) { |
| 177 ReturnStatement* stmt = body->last()->AsReturnStatement(); | 178 ReturnStatement* stmt = body->last()->AsReturnStatement(); |
| 178 if (stmt != NULL) { | 179 if (stmt != NULL) { |
| 179 Literal* literal = stmt->expression()->AsLiteral(); | 180 Literal* literal = stmt->expression()->AsLiteral(); |
| 180 Type* old_expected = expected_type_; | 181 Type* old_expected = expected_type_; |
| 181 expected_type_ = Type::Any(); | 182 expected_type_ = Type::Any(zone()); |
| 182 if (literal) { | 183 if (literal) { |
| 183 RECURSE(VisitLiteral(literal, true)); | 184 RECURSE(VisitLiteral(literal, true)); |
| 184 } else { | 185 } else { |
| 185 RECURSE(VisitExpressionAnnotation(stmt->expression(), NULL, true)); | 186 RECURSE(VisitExpressionAnnotation(stmt->expression(), NULL, true)); |
| 186 } | 187 } |
| 187 expected_type_ = old_expected; | 188 expected_type_ = old_expected; |
| 188 result_type = computed_type_; | 189 result_type = computed_type_; |
| 189 } | 190 } |
| 190 } | 191 } |
| 191 Type::FunctionType* type = | 192 Type::FunctionType* type = Type::Function(result_type, Type::Any(zone()), |
| 192 Type::Function(result_type, Type::Any(), fun->parameter_count(), zone()) | 193 fun->parameter_count(), zone()) |
| 193 ->AsFunction(); | 194 ->AsFunction(); |
| 194 | 195 |
| 195 // Extract parameter types. | 196 // Extract parameter types. |
| 196 bool good = true; | 197 bool good = true; |
| 197 for (int i = 0; i < fun->parameter_count(); ++i) { | 198 for (int i = 0; i < fun->parameter_count(); ++i) { |
| 198 good = false; | 199 good = false; |
| 199 if (i >= body->length()) break; | 200 if (i >= body->length()) break; |
| 200 ExpressionStatement* stmt = body->at(i)->AsExpressionStatement(); | 201 ExpressionStatement* stmt = body->at(i)->AsExpressionStatement(); |
| 201 if (stmt == NULL) break; | 202 if (stmt == NULL) break; |
| 202 Assignment* expr = stmt->expression()->AsAssignment(); | 203 Assignment* expr = stmt->expression()->AsAssignment(); |
| 203 if (expr == NULL || expr->is_compound()) break; | 204 if (expr == NULL || expr->is_compound()) break; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 break; | 259 break; |
| 259 default: | 260 default: |
| 260 break; | 261 break; |
| 261 } | 262 } |
| 262 } | 263 } |
| 263 FAIL(expr, "invalid type annotation on binary op"); | 264 FAIL(expr, "invalid type annotation on binary op"); |
| 264 } | 265 } |
| 265 | 266 |
| 266 // Numbers or the undefined literal (for empty returns). | 267 // Numbers or the undefined literal (for empty returns). |
| 267 if (expr->IsLiteral()) { | 268 if (expr->IsLiteral()) { |
| 268 RECURSE(VisitWithExpectation(expr, Type::Any(), "invalid literal")); | 269 RECURSE(VisitWithExpectation(expr, Type::Any(zone()), "invalid literal")); |
| 269 return; | 270 return; |
| 270 } | 271 } |
| 271 | 272 |
| 272 Call* call = expr->AsCall(); | 273 Call* call = expr->AsCall(); |
| 273 if (call != NULL) { | 274 if (call != NULL) { |
| 274 VariableProxy* proxy = call->expression()->AsVariableProxy(); | 275 VariableProxy* proxy = call->expression()->AsVariableProxy(); |
| 275 if (proxy != NULL) { | 276 if (proxy != NULL) { |
| 276 VariableInfo* info = GetVariableInfo(proxy->var(), false); | 277 VariableInfo* info = GetVariableInfo(proxy->var(), false); |
| 277 if (!info || | 278 if (!info || |
| 278 (!info->is_check_function && !info->is_constructor_function)) { | 279 (!info->is_check_function && !info->is_constructor_function)) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 308 } | 309 } |
| 309 } | 310 } |
| 310 | 311 |
| 311 | 312 |
| 312 void AsmTyper::VisitBlock(Block* stmt) { | 313 void AsmTyper::VisitBlock(Block* stmt) { |
| 313 RECURSE(VisitStatements(stmt->statements())); | 314 RECURSE(VisitStatements(stmt->statements())); |
| 314 } | 315 } |
| 315 | 316 |
| 316 | 317 |
| 317 void AsmTyper::VisitExpressionStatement(ExpressionStatement* stmt) { | 318 void AsmTyper::VisitExpressionStatement(ExpressionStatement* stmt) { |
| 318 RECURSE(VisitWithExpectation(stmt->expression(), Type::Any(), | 319 RECURSE(VisitWithExpectation(stmt->expression(), Type::Any(zone()), |
| 319 "expression statement expected to be any")); | 320 "expression statement expected to be any")); |
| 320 } | 321 } |
| 321 | 322 |
| 322 | 323 |
| 323 void AsmTyper::VisitEmptyStatement(EmptyStatement* stmt) {} | 324 void AsmTyper::VisitEmptyStatement(EmptyStatement* stmt) {} |
| 324 | 325 |
| 325 | 326 |
| 326 void AsmTyper::VisitSloppyBlockFunctionStatement( | 327 void AsmTyper::VisitSloppyBlockFunctionStatement( |
| 327 SloppyBlockFunctionStatement* stmt) { | 328 SloppyBlockFunctionStatement* stmt) { |
| 328 Visit(stmt->statement()); | 329 Visit(stmt->statement()); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) { | 361 void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) { |
| 361 // Handle module return statement in VisitAsmModule. | 362 // Handle module return statement in VisitAsmModule. |
| 362 if (!in_function_) { | 363 if (!in_function_) { |
| 363 return; | 364 return; |
| 364 } | 365 } |
| 365 Literal* literal = stmt->expression()->AsLiteral(); | 366 Literal* literal = stmt->expression()->AsLiteral(); |
| 366 if (literal) { | 367 if (literal) { |
| 367 VisitLiteral(literal, true); | 368 VisitLiteral(literal, true); |
| 368 } else { | 369 } else { |
| 369 RECURSE( | 370 RECURSE( |
| 370 VisitWithExpectation(stmt->expression(), Type::Any(), | 371 VisitWithExpectation(stmt->expression(), Type::Any(zone()), |
| 371 "return expression expected to have return type")); | 372 "return expression expected to have return type")); |
| 372 } | 373 } |
| 373 if (!computed_type_->Is(return_type_) || !return_type_->Is(computed_type_)) { | 374 if (!computed_type_->Is(return_type_) || !return_type_->Is(computed_type_)) { |
| 374 FAIL(stmt->expression(), "return type does not match function signature"); | 375 FAIL(stmt->expression(), "return type does not match function signature"); |
| 375 } | 376 } |
| 376 } | 377 } |
| 377 | 378 |
| 378 | 379 |
| 379 void AsmTyper::VisitWithStatement(WithStatement* stmt) { | 380 void AsmTyper::VisitWithStatement(WithStatement* stmt) { |
| 380 FAIL(stmt, "bad with statement"); | 381 FAIL(stmt, "bad with statement"); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 FAIL(stmt, "try statement encountered"); | 483 FAIL(stmt, "try statement encountered"); |
| 483 } | 484 } |
| 484 | 485 |
| 485 | 486 |
| 486 void AsmTyper::VisitDebuggerStatement(DebuggerStatement* stmt) { | 487 void AsmTyper::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 487 FAIL(stmt, "debugger statement encountered"); | 488 FAIL(stmt, "debugger statement encountered"); |
| 488 } | 489 } |
| 489 | 490 |
| 490 | 491 |
| 491 void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) { | 492 void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 492 Scope* scope = expr->scope(); | |
| 493 DCHECK(scope->is_function_scope()); | |
| 494 if (in_function_) { | 493 if (in_function_) { |
| 495 FAIL(expr, "invalid nested function"); | 494 FAIL(expr, "invalid nested function"); |
| 496 } | 495 } |
| 496 Scope* scope = expr->scope(); |
| 497 DCHECK(scope->is_function_scope()); |
| 497 | 498 |
| 498 if (!expr->bounds().upper->IsFunction()) { | 499 if (!expr->bounds().upper->IsFunction()) { |
| 499 FAIL(expr, "invalid function literal"); | 500 FAIL(expr, "invalid function literal"); |
| 500 } | 501 } |
| 501 | 502 |
| 502 Type::FunctionType* type = expr->bounds().upper->AsFunction(); | 503 Type::FunctionType* type = expr->bounds().upper->AsFunction(); |
| 503 Type* save_return_type = return_type_; | 504 Type* save_return_type = return_type_; |
| 504 return_type_ = type->Result(); | 505 return_type_ = type->Result(); |
| 505 in_function_ = true; | 506 in_function_ = true; |
| 506 local_variable_type_.Clear(); | 507 local_variable_type_.Clear(); |
| 507 RECURSE(VisitDeclarations(scope->declarations())); | 508 RECURSE(VisitDeclarations(scope->declarations())); |
| 508 RECURSE(VisitStatements(expr->body())); | 509 RECURSE(VisitStatements(expr->body())); |
| 509 in_function_ = false; | 510 in_function_ = false; |
| 510 return_type_ = save_return_type; | 511 return_type_ = save_return_type; |
| 511 IntersectResult(expr, type); | 512 IntersectResult(expr, type); |
| 512 } | 513 } |
| 513 | 514 |
| 514 | 515 |
| 515 void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 516 void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
| 516 FAIL(expr, "function info literal encountered"); | 517 FAIL(expr, "function info literal encountered"); |
| 517 } | 518 } |
| 518 | 519 |
| 519 | 520 |
| 520 void AsmTyper::VisitDoExpression(DoExpression* expr) { | 521 void AsmTyper::VisitDoExpression(DoExpression* expr) { |
| 521 FAIL(expr, "do-expression encountered"); | 522 FAIL(expr, "do-expression encountered"); |
| 522 } | 523 } |
| 523 | 524 |
| 524 | 525 |
| 525 void AsmTyper::VisitConditional(Conditional* expr) { | 526 void AsmTyper::VisitConditional(Conditional* expr) { |
| 526 RECURSE(VisitWithExpectation(expr->condition(), Type::Number(), | 527 if (!in_function_) { |
| 528 FAIL(expr, "ternary operator inside module body"); |
| 529 } |
| 530 RECURSE(VisitWithExpectation(expr->condition(), Type::Number(zone()), |
| 527 "condition expected to be integer")); | 531 "condition expected to be integer")); |
| 528 if (!computed_type_->Is(cache_.kAsmInt)) { | 532 if (!computed_type_->Is(cache_.kAsmInt)) { |
| 529 FAIL(expr->condition(), "condition must be of type int"); | 533 FAIL(expr->condition(), "condition must be of type int"); |
| 530 } | 534 } |
| 531 | 535 |
| 532 RECURSE(VisitWithExpectation( | 536 RECURSE(VisitWithExpectation( |
| 533 expr->then_expression(), expected_type_, | 537 expr->then_expression(), expected_type_, |
| 534 "conditional then branch type mismatch with enclosing expression")); | 538 "conditional then branch type mismatch with enclosing expression")); |
| 535 Type* then_type = StorageType(computed_type_); | 539 Type* then_type = StorageType(computed_type_); |
| 536 if (intish_ != 0 || !then_type->Is(cache_.kAsmComparable)) { | 540 if (intish_ != 0 || !then_type->Is(cache_.kAsmComparable)) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 547 | 551 |
| 548 if (!then_type->Is(else_type) || !else_type->Is(then_type)) { | 552 if (!then_type->Is(else_type) || !else_type->Is(then_type)) { |
| 549 FAIL(expr, "then and else expressions in ? must have the same type"); | 553 FAIL(expr, "then and else expressions in ? must have the same type"); |
| 550 } | 554 } |
| 551 | 555 |
| 552 IntersectResult(expr, then_type); | 556 IntersectResult(expr, then_type); |
| 553 } | 557 } |
| 554 | 558 |
| 555 | 559 |
| 556 void AsmTyper::VisitVariableProxy(VariableProxy* expr) { | 560 void AsmTyper::VisitVariableProxy(VariableProxy* expr) { |
| 561 VisitVariableProxy(expr, false); |
| 562 } |
| 563 |
| 564 void AsmTyper::VisitVariableProxy(VariableProxy* expr, bool assignment) { |
| 557 Variable* var = expr->var(); | 565 Variable* var = expr->var(); |
| 558 VariableInfo* info = GetVariableInfo(var, false); | 566 VariableInfo* info = GetVariableInfo(var, false); |
| 567 if (!assignment && !in_function_ && !building_function_tables_ && |
| 568 !visiting_exports_) { |
| 569 if (var->location() != VariableLocation::PARAMETER || var->index() >= 3) { |
| 570 FAIL(expr, "illegal variable reference in module body"); |
| 571 } |
| 572 } |
| 559 if (info == NULL || info->type == NULL) { | 573 if (info == NULL || info->type == NULL) { |
| 560 if (var->mode() == TEMPORARY) { | 574 if (var->mode() == TEMPORARY) { |
| 561 SetType(var, Type::Any(zone())); | 575 SetType(var, Type::Any(zone())); |
| 562 info = GetVariableInfo(var, false); | 576 info = GetVariableInfo(var, false); |
| 563 } else { | 577 } else { |
| 564 FAIL(expr, "unbound variable"); | 578 FAIL(expr, "unbound variable"); |
| 565 } | 579 } |
| 566 } | 580 } |
| 567 if (property_info_ != NULL) { | 581 if (property_info_ != NULL) { |
| 568 SetVariableInfo(var, property_info_); | 582 SetVariableInfo(var, property_info_); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 | 649 |
| 636 void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) { | 650 void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) { |
| 637 if (in_function_) { | 651 if (in_function_) { |
| 638 FAIL(expr, "array literal inside a function"); | 652 FAIL(expr, "array literal inside a function"); |
| 639 } | 653 } |
| 640 // Allowed for function tables. | 654 // Allowed for function tables. |
| 641 ZoneList<Expression*>* values = expr->values(); | 655 ZoneList<Expression*>* values = expr->values(); |
| 642 Type* elem_type = Type::None(zone()); | 656 Type* elem_type = Type::None(zone()); |
| 643 for (int i = 0; i < values->length(); ++i) { | 657 for (int i = 0; i < values->length(); ++i) { |
| 644 Expression* value = values->at(i); | 658 Expression* value = values->at(i); |
| 645 RECURSE(VisitWithExpectation(value, Type::Any(), "UNREACHABLE")); | 659 RECURSE(VisitWithExpectation(value, Type::Any(zone()), "UNREACHABLE")); |
| 646 if (!computed_type_->IsFunction()) { | 660 if (!computed_type_->IsFunction()) { |
| 647 FAIL(value, "array component expected to be a function"); | 661 FAIL(value, "array component expected to be a function"); |
| 648 } | 662 } |
| 649 elem_type = Type::Union(elem_type, computed_type_, zone()); | 663 elem_type = Type::Union(elem_type, computed_type_, zone()); |
| 650 } | 664 } |
| 651 array_size_ = values->length(); | 665 array_size_ = values->length(); |
| 652 IntersectResult(expr, Type::Array(elem_type, zone())); | 666 IntersectResult(expr, Type::Array(elem_type, zone())); |
| 653 } | 667 } |
| 654 | 668 |
| 655 | 669 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 668 } | 682 } |
| 669 if (expr->is_compound()) FAIL(expr, "compound assignment encountered"); | 683 if (expr->is_compound()) FAIL(expr, "compound assignment encountered"); |
| 670 Type* type = expected_type_; | 684 Type* type = expected_type_; |
| 671 RECURSE(VisitWithExpectation( | 685 RECURSE(VisitWithExpectation( |
| 672 expr->value(), type, "assignment value expected to match surrounding")); | 686 expr->value(), type, "assignment value expected to match surrounding")); |
| 673 Type* target_type = StorageType(computed_type_); | 687 Type* target_type = StorageType(computed_type_); |
| 674 if (intish_ != 0) { | 688 if (intish_ != 0) { |
| 675 FAIL(expr, "intish or floatish assignment"); | 689 FAIL(expr, "intish or floatish assignment"); |
| 676 } | 690 } |
| 677 if (expr->target()->IsVariableProxy()) { | 691 if (expr->target()->IsVariableProxy()) { |
| 678 RECURSE(VisitWithExpectation(expr->target(), target_type, | 692 expected_type_ = target_type; |
| 679 "assignment target expected to match value")); | 693 VisitVariableProxy(expr->target()->AsVariableProxy(), true); |
| 680 } else if (expr->target()->IsProperty()) { | 694 } else if (expr->target()->IsProperty()) { |
| 681 Property* property = expr->target()->AsProperty(); | 695 Property* property = expr->target()->AsProperty(); |
| 682 RECURSE(VisitWithExpectation(property->obj(), Type::Any(), | 696 RECURSE(VisitWithExpectation(property->obj(), Type::Any(zone()), |
| 683 "bad propety object")); | 697 "bad propety object")); |
| 684 if (!computed_type_->IsArray()) { | 698 if (!computed_type_->IsArray()) { |
| 685 FAIL(property->obj(), "array expected"); | 699 FAIL(property->obj(), "array expected"); |
| 686 } | 700 } |
| 687 VisitHeapAccess(property, true, target_type); | 701 VisitHeapAccess(property, true, target_type); |
| 688 } | 702 } |
| 689 IntersectResult(expr, target_type); | 703 IntersectResult(expr, target_type); |
| 690 } | 704 } |
| 691 | 705 |
| 692 | 706 |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 #undef V | 895 #undef V |
| 882 if (IsStdlibObject(expr->obj())) { | 896 if (IsStdlibObject(expr->obj())) { |
| 883 VisitLibraryAccess(&stdlib_types_, expr); | 897 VisitLibraryAccess(&stdlib_types_, expr); |
| 884 return; | 898 return; |
| 885 } | 899 } |
| 886 | 900 |
| 887 property_info_ = NULL; | 901 property_info_ = NULL; |
| 888 | 902 |
| 889 // Only recurse at this point so that we avoid needing | 903 // Only recurse at this point so that we avoid needing |
| 890 // stdlib.Math to have a real type. | 904 // stdlib.Math to have a real type. |
| 891 RECURSE(VisitWithExpectation(expr->obj(), Type::Any(), "bad propety object")); | 905 RECURSE(VisitWithExpectation(expr->obj(), Type::Any(zone()), |
| 906 "bad propety object")); |
| 892 | 907 |
| 893 // For heap view or function table access. | 908 // For heap view or function table access. |
| 894 if (computed_type_->IsArray()) { | 909 if (computed_type_->IsArray()) { |
| 895 VisitHeapAccess(expr, false, NULL); | 910 VisitHeapAccess(expr, false, NULL); |
| 896 return; | 911 return; |
| 897 } | 912 } |
| 898 | 913 |
| 899 // stdlib.x or foreign.x | 914 // stdlib.x or foreign.x |
| 900 VariableProxy* proxy = expr->obj()->AsVariableProxy(); | 915 VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
| 901 if (proxy != NULL) { | 916 if (proxy != NULL) { |
| 902 Variable* var = proxy->var(); | 917 Variable* var = proxy->var(); |
| 903 if (var->location() == VariableLocation::PARAMETER && var->index() == 1) { | 918 if (var->location() == VariableLocation::PARAMETER && var->index() == 1) { |
| 904 // foreign.x is ok. | 919 // foreign.x is ok. |
| 905 SetResult(expr, expected_type_); | 920 SetResult(expr, expected_type_); |
| 906 return; | 921 return; |
| 907 } | 922 } |
| 908 } | 923 } |
| 909 | 924 |
| 910 FAIL(expr, "invalid property access"); | 925 FAIL(expr, "invalid property access"); |
| 911 } | 926 } |
| 912 | 927 |
| 913 | 928 |
| 914 void AsmTyper::VisitCall(Call* expr) { | 929 void AsmTyper::VisitCall(Call* expr) { |
| 915 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), | 930 Type* expected_type = expected_type_; |
| 931 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(zone()), |
| 916 "callee expected to be any")); | 932 "callee expected to be any")); |
| 917 StandardMember standard_member = kNone; | 933 StandardMember standard_member = kNone; |
| 918 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 934 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 919 if (proxy) { | 935 if (proxy) { |
| 920 standard_member = VariableAsStandardMember(proxy->var()); | 936 standard_member = VariableAsStandardMember(proxy->var()); |
| 921 } | 937 } |
| 922 if (!in_function_ && (proxy == NULL || standard_member != kMathFround)) { | 938 if (!in_function_ && (proxy == NULL || standard_member != kMathFround)) { |
| 923 FAIL(expr, "calls forbidden outside function bodies"); | 939 FAIL(expr, "calls forbidden outside function bodies"); |
| 924 } | 940 } |
| 925 if (proxy == NULL && !expr->expression()->IsProperty()) { | 941 if (proxy == NULL && !expr->expression()->IsProperty()) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 960 Type* other = Type::Intersect(args->at(0)->bounds().upper, | 976 Type* other = Type::Intersect(args->at(0)->bounds().upper, |
| 961 args->at(1)->bounds().upper, zone()); | 977 args->at(1)->bounds().upper, zone()); |
| 962 if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) && | 978 if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) && |
| 963 !other->Is(cache_.kAsmSigned)) { | 979 !other->Is(cache_.kAsmSigned)) { |
| 964 FAIL(expr, "function arguments types don't match"); | 980 FAIL(expr, "function arguments types don't match"); |
| 965 } | 981 } |
| 966 } | 982 } |
| 967 } | 983 } |
| 968 intish_ = 0; | 984 intish_ = 0; |
| 969 IntersectResult(expr, result_type); | 985 IntersectResult(expr, result_type); |
| 970 } else if (computed_type_->Is(Type::Any())) { | 986 } else if (computed_type_->Is(Type::Any(zone()))) { |
| 971 // For foreign calls. | 987 // For foreign calls. |
| 972 ZoneList<Expression*>* args = expr->arguments(); | 988 ZoneList<Expression*>* args = expr->arguments(); |
| 973 for (int i = 0; i < args->length(); ++i) { | 989 for (int i = 0; i < args->length(); ++i) { |
| 974 Expression* arg = args->at(i); | 990 Expression* arg = args->at(i); |
| 975 RECURSE(VisitWithExpectation(arg, Type::Any(), | 991 RECURSE(VisitWithExpectation(arg, Type::Any(zone()), |
| 976 "foreign call argument expected to be any")); | 992 "foreign call argument expected to be any")); |
| 993 // Checking for asm extern types explicitly, as the type system |
| 994 // doesn't correctly check their inheritance relationship. |
| 995 if (!computed_type_->Is(cache_.kAsmSigned) && |
| 996 !computed_type_->Is(cache_.kAsmFixnum) && |
| 997 !computed_type_->Is(cache_.kAsmDouble)) { |
| 998 FAIL(arg, |
| 999 "foreign call argument expected to be int, double, or fixnum"); |
| 1000 } |
| 977 } | 1001 } |
| 978 intish_ = kMaxUncombinedAdditiveSteps; | 1002 intish_ = kMaxUncombinedAdditiveSteps; |
| 979 IntersectResult(expr, Type::Number()); | 1003 IntersectResult(expr, expected_type); |
| 980 } else { | 1004 } else { |
| 981 FAIL(expr, "invalid callee"); | 1005 FAIL(expr, "invalid callee"); |
| 982 } | 1006 } |
| 983 } | 1007 } |
| 984 | 1008 |
| 985 | 1009 |
| 986 void AsmTyper::VisitCallNew(CallNew* expr) { | 1010 void AsmTyper::VisitCallNew(CallNew* expr) { |
| 987 if (in_function_) { | 1011 if (in_function_) { |
| 988 FAIL(expr, "new not allowed in module function"); | 1012 FAIL(expr, "new not allowed in module function"); |
| 989 } | 1013 } |
| 990 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), | 1014 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(zone()), |
| 991 "expected stdlib function")); | 1015 "expected stdlib function")); |
| 992 if (computed_type_->IsFunction()) { | 1016 if (computed_type_->IsFunction()) { |
| 993 Type::FunctionType* fun_type = computed_type_->AsFunction(); | 1017 Type::FunctionType* fun_type = computed_type_->AsFunction(); |
| 994 ZoneList<Expression*>* args = expr->arguments(); | 1018 ZoneList<Expression*>* args = expr->arguments(); |
| 995 if (fun_type->Arity() != args->length()) | 1019 if (fun_type->Arity() != args->length()) |
| 996 FAIL(expr, "call with wrong arity"); | 1020 FAIL(expr, "call with wrong arity"); |
| 997 for (int i = 0; i < args->length(); ++i) { | 1021 for (int i = 0; i < args->length(); ++i) { |
| 998 Expression* arg = args->at(i); | 1022 Expression* arg = args->at(i); |
| 999 RECURSE(VisitWithExpectation( | 1023 RECURSE(VisitWithExpectation( |
| 1000 arg, fun_type->Parameter(i), | 1024 arg, fun_type->Parameter(i), |
| 1001 "constructor argument expected to match callee parameter")); | 1025 "constructor argument expected to match callee parameter")); |
| 1002 } | 1026 } |
| 1003 IntersectResult(expr, fun_type->Result()); | 1027 IntersectResult(expr, fun_type->Result()); |
| 1004 return; | 1028 return; |
| 1005 } | 1029 } |
| 1006 | 1030 |
| 1007 FAIL(expr, "ill-typed new operator"); | 1031 FAIL(expr, "ill-typed new operator"); |
| 1008 } | 1032 } |
| 1009 | 1033 |
| 1010 | 1034 |
| 1011 void AsmTyper::VisitCallRuntime(CallRuntime* expr) { | 1035 void AsmTyper::VisitCallRuntime(CallRuntime* expr) { |
| 1012 // Allow runtime calls for now. | 1036 // Allow runtime calls for now. |
| 1013 } | 1037 } |
| 1014 | 1038 |
| 1015 | 1039 |
| 1016 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) { | 1040 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) { |
| 1041 if (!in_function_) { |
| 1042 FAIL(expr, "unary operator inside module body"); |
| 1043 } |
| 1017 switch (expr->op()) { | 1044 switch (expr->op()) { |
| 1018 case Token::NOT: // Used to encode != and !== | 1045 case Token::NOT: // Used to encode != and !== |
| 1019 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt, | 1046 RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt, |
| 1020 "operand expected to be integer")); | 1047 "operand expected to be integer")); |
| 1021 IntersectResult(expr, cache_.kAsmSigned); | 1048 IntersectResult(expr, cache_.kAsmSigned); |
| 1022 return; | 1049 return; |
| 1023 case Token::DELETE: | 1050 case Token::DELETE: |
| 1024 FAIL(expr, "delete operator encountered"); | 1051 FAIL(expr, "delete operator encountered"); |
| 1025 case Token::VOID: | 1052 case Token::VOID: |
| 1026 FAIL(expr, "void operator encountered"); | 1053 FAIL(expr, "void operator encountered"); |
| 1027 case Token::TYPEOF: | 1054 case Token::TYPEOF: |
| 1028 FAIL(expr, "typeof operator encountered"); | 1055 FAIL(expr, "typeof operator encountered"); |
| 1029 default: | 1056 default: |
| 1030 UNREACHABLE(); | 1057 UNREACHABLE(); |
| 1031 } | 1058 } |
| 1032 } | 1059 } |
| 1033 | 1060 |
| 1034 | 1061 |
| 1035 void AsmTyper::VisitCountOperation(CountOperation* expr) { | 1062 void AsmTyper::VisitCountOperation(CountOperation* expr) { |
| 1036 FAIL(expr, "increment or decrement operator encountered"); | 1063 FAIL(expr, "increment or decrement operator encountered"); |
| 1037 } | 1064 } |
| 1038 | 1065 |
| 1039 | 1066 |
| 1040 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr, | 1067 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr, |
| 1041 Type* left_expected, | 1068 Type* left_expected, |
| 1042 Type* right_expected, | 1069 Type* right_expected, |
| 1043 Type* result_type, bool conversion) { | 1070 Type* result_type, bool conversion) { |
| 1044 RECURSE(VisitWithExpectation(expr->left(), Type::Number(), | 1071 RECURSE(VisitWithExpectation(expr->left(), Type::Number(zone()), |
| 1045 "left bitwise operand expected to be a number")); | 1072 "left bitwise operand expected to be a number")); |
| 1046 int left_intish = intish_; | 1073 int left_intish = intish_; |
| 1047 Type* left_type = computed_type_; | 1074 Type* left_type = computed_type_; |
| 1048 if (!left_type->Is(left_expected)) { | 1075 if (!left_type->Is(left_expected)) { |
| 1049 FAIL(expr->left(), "left bitwise operand expected to be an integer"); | 1076 FAIL(expr->left(), "left bitwise operand expected to be an integer"); |
| 1050 } | 1077 } |
| 1051 if (left_intish > kMaxUncombinedAdditiveSteps) { | 1078 if (left_intish > kMaxUncombinedAdditiveSteps) { |
| 1052 FAIL(expr->left(), "too many consecutive additive ops"); | 1079 FAIL(expr->left(), "too many consecutive additive ops"); |
| 1053 } | 1080 } |
| 1054 | 1081 |
| 1055 RECURSE( | 1082 RECURSE( |
| 1056 VisitWithExpectation(expr->right(), Type::Number(), | 1083 VisitWithExpectation(expr->right(), Type::Number(zone()), |
| 1057 "right bitwise operand expected to be a number")); | 1084 "right bitwise operand expected to be a number")); |
| 1058 int right_intish = intish_; | 1085 int right_intish = intish_; |
| 1059 Type* right_type = computed_type_; | 1086 Type* right_type = computed_type_; |
| 1060 if (!right_type->Is(right_expected)) { | 1087 if (!right_type->Is(right_expected)) { |
| 1061 FAIL(expr->right(), "right bitwise operand expected to be an integer"); | 1088 FAIL(expr->right(), "right bitwise operand expected to be an integer"); |
| 1062 } | 1089 } |
| 1063 if (right_intish > kMaxUncombinedAdditiveSteps) { | 1090 if (right_intish > kMaxUncombinedAdditiveSteps) { |
| 1064 FAIL(expr->right(), "too many consecutive additive ops"); | 1091 FAIL(expr->right(), "too many consecutive additive ops"); |
| 1065 } | 1092 } |
| 1066 | 1093 |
| 1067 intish_ = 0; | 1094 intish_ = 0; |
| 1068 | 1095 |
| 1069 if (left_type->Is(cache_.kAsmFixnum) && right_type->Is(cache_.kAsmInt)) { | 1096 if (left_type->Is(cache_.kAsmFixnum) && right_type->Is(cache_.kAsmInt)) { |
| 1070 left_type = right_type; | 1097 left_type = right_type; |
| 1071 } | 1098 } |
| 1072 if (right_type->Is(cache_.kAsmFixnum) && left_type->Is(cache_.kAsmInt)) { | 1099 if (right_type->Is(cache_.kAsmFixnum) && left_type->Is(cache_.kAsmInt)) { |
| 1073 right_type = left_type; | 1100 right_type = left_type; |
| 1074 } | 1101 } |
| 1075 if (!conversion) { | 1102 if (!conversion) { |
| 1076 if (!left_type->Is(right_type) || !right_type->Is(left_type)) { | 1103 if (!left_type->Is(right_type) || !right_type->Is(left_type)) { |
| 1077 FAIL(expr, "ill-typed bitwise operation"); | 1104 FAIL(expr, "ill-typed bitwise operation"); |
| 1078 } | 1105 } |
| 1079 } | 1106 } |
| 1080 IntersectResult(expr, result_type); | 1107 IntersectResult(expr, result_type); |
| 1081 } | 1108 } |
| 1082 | 1109 |
| 1083 | 1110 |
| 1084 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { | 1111 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { |
| 1112 if (!in_function_) { |
| 1113 if (expr->op() != Token::BIT_OR && expr->op() != Token::MUL) { |
| 1114 FAIL(expr, "illegal binary operator inside module body"); |
| 1115 } |
| 1116 if (!(expr->left()->IsProperty() || expr->left()->IsVariableProxy()) || |
| 1117 !expr->right()->IsLiteral()) { |
| 1118 FAIL(expr, "illegal computation inside module body"); |
| 1119 } |
| 1120 } |
| 1085 switch (expr->op()) { | 1121 switch (expr->op()) { |
| 1086 case Token::COMMA: { | 1122 case Token::COMMA: { |
| 1087 RECURSE(VisitWithExpectation(expr->left(), Type::Any(), | 1123 RECURSE(VisitWithExpectation(expr->left(), Type::Any(zone()), |
| 1088 "left comma operand expected to be any")); | 1124 "left comma operand expected to be any")); |
| 1089 RECURSE(VisitWithExpectation(expr->right(), Type::Any(), | 1125 RECURSE(VisitWithExpectation(expr->right(), Type::Any(zone()), |
| 1090 "right comma operand expected to be any")); | 1126 "right comma operand expected to be any")); |
| 1091 IntersectResult(expr, computed_type_); | 1127 IntersectResult(expr, computed_type_); |
| 1092 return; | 1128 return; |
| 1093 } | 1129 } |
| 1094 case Token::OR: | 1130 case Token::OR: |
| 1095 case Token::AND: | 1131 case Token::AND: |
| 1096 FAIL(expr, "illegal logical operator"); | 1132 FAIL(expr, "illegal logical operator"); |
| 1097 case Token::BIT_OR: { | 1133 case Token::BIT_OR: { |
| 1098 // BIT_OR allows Any since it is used as a type coercion. | 1134 // BIT_OR allows Any since it is used as a type coercion. |
| 1099 VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmInt, | 1135 VisitIntegerBitwiseOperator(expr, Type::Any(zone()), cache_.kAsmInt, |
| 1100 cache_.kAsmSigned, true); | 1136 cache_.kAsmSigned, true); |
| 1137 if (expr->left()->IsCall() && expr->op() == Token::BIT_OR) { |
| 1138 IntersectResult(expr->left(), cache_.kAsmSigned); |
| 1139 } |
| 1101 return; | 1140 return; |
| 1102 } | 1141 } |
| 1103 case Token::BIT_XOR: { | 1142 case Token::BIT_XOR: { |
| 1104 // Handle booleans specially to handle de-sugared ! | 1143 // Handle booleans specially to handle de-sugared ! |
| 1105 Literal* left = expr->left()->AsLiteral(); | 1144 Literal* left = expr->left()->AsLiteral(); |
| 1106 if (left && left->value()->IsBoolean()) { | 1145 if (left && left->value()->IsBoolean()) { |
| 1107 if (left->ToBooleanIsTrue()) { | 1146 if (left->ToBooleanIsTrue()) { |
| 1108 left->set_bounds(Bounds(cache_.kSingletonOne)); | 1147 left->set_bounds(Bounds(cache_.kSingletonOne)); |
| 1109 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmInt, | 1148 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmInt, |
| 1110 "not operator expects an integer")); | 1149 "not operator expects an integer")); |
| 1111 IntersectResult(expr, cache_.kAsmSigned); | 1150 IntersectResult(expr, cache_.kAsmSigned); |
| 1112 return; | 1151 return; |
| 1113 } else { | 1152 } else { |
| 1114 FAIL(left, "unexpected false"); | 1153 FAIL(left, "unexpected false"); |
| 1115 } | 1154 } |
| 1116 } | 1155 } |
| 1117 // BIT_XOR allows Number since it is used as a type coercion (via ~~). | 1156 // BIT_XOR allows Number since it is used as a type coercion (via ~~). |
| 1118 VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kAsmInt, | 1157 VisitIntegerBitwiseOperator(expr, Type::Number(zone()), cache_.kAsmInt, |
| 1119 cache_.kAsmSigned, true); | 1158 cache_.kAsmSigned, true); |
| 1120 return; | 1159 return; |
| 1121 } | 1160 } |
| 1122 case Token::SHR: { | 1161 case Token::SHR: { |
| 1123 VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, | 1162 VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, |
| 1124 cache_.kAsmUnsigned, false); | 1163 cache_.kAsmUnsigned, false); |
| 1125 return; | 1164 return; |
| 1126 } | 1165 } |
| 1127 case Token::SHL: | 1166 case Token::SHL: |
| 1128 case Token::SAR: | 1167 case Token::SAR: |
| 1129 case Token::BIT_AND: { | 1168 case Token::BIT_AND: { |
| 1130 VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, | 1169 VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt, |
| 1131 cache_.kAsmSigned, false); | 1170 cache_.kAsmSigned, false); |
| 1132 return; | 1171 return; |
| 1133 } | 1172 } |
| 1134 case Token::ADD: | 1173 case Token::ADD: |
| 1135 case Token::SUB: | 1174 case Token::SUB: |
| 1136 case Token::MUL: | 1175 case Token::MUL: |
| 1137 case Token::DIV: | 1176 case Token::DIV: |
| 1138 case Token::MOD: { | 1177 case Token::MOD: { |
| 1139 RECURSE(VisitWithExpectation( | 1178 RECURSE(VisitWithExpectation( |
| 1140 expr->left(), Type::Number(), | 1179 expr->left(), Type::Number(zone()), |
| 1141 "left arithmetic operand expected to be number")); | 1180 "left arithmetic operand expected to be number")); |
| 1142 Type* left_type = computed_type_; | 1181 Type* left_type = computed_type_; |
| 1143 int left_intish = intish_; | 1182 int left_intish = intish_; |
| 1144 RECURSE(VisitWithExpectation( | 1183 RECURSE(VisitWithExpectation( |
| 1145 expr->right(), Type::Number(), | 1184 expr->right(), Type::Number(zone()), |
| 1146 "right arithmetic operand expected to be number")); | 1185 "right arithmetic operand expected to be number")); |
| 1147 Type* right_type = computed_type_; | 1186 Type* right_type = computed_type_; |
| 1148 int right_intish = intish_; | 1187 int right_intish = intish_; |
| 1149 Type* type = Type::Union(left_type, right_type, zone()); | 1188 Type* type = Type::Union(left_type, right_type, zone()); |
| 1150 if (type->Is(cache_.kAsmInt)) { | 1189 if (type->Is(cache_.kAsmInt)) { |
| 1151 if (expr->op() == Token::MUL) { | 1190 if (expr->op() == Token::MUL) { |
| 1152 Literal* right = expr->right()->AsLiteral(); | 1191 Literal* right = expr->right()->AsLiteral(); |
| 1153 if (!right) { | 1192 if (!right) { |
| 1154 FAIL(expr, "direct integer multiply forbidden"); | 1193 FAIL(expr, "direct integer multiply forbidden"); |
| 1155 } | 1194 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1177 if (intish_ > kMaxUncombinedMultiplicativeSteps) { | 1216 if (intish_ > kMaxUncombinedMultiplicativeSteps) { |
| 1178 FAIL(expr, "too many consecutive multiplicative ops"); | 1217 FAIL(expr, "too many consecutive multiplicative ops"); |
| 1179 } | 1218 } |
| 1180 } | 1219 } |
| 1181 IntersectResult(expr, cache_.kAsmInt); | 1220 IntersectResult(expr, cache_.kAsmInt); |
| 1182 return; | 1221 return; |
| 1183 } | 1222 } |
| 1184 } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() && | 1223 } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() && |
| 1185 right_type->Is(cache_.kAsmDouble)) { | 1224 right_type->Is(cache_.kAsmDouble)) { |
| 1186 // For unary +, expressed as x * 1.0 | 1225 // For unary +, expressed as x * 1.0 |
| 1226 if (expr->left()->IsCall() && expr->op() == Token::MUL) { |
| 1227 IntersectResult(expr->left(), cache_.kAsmDouble); |
| 1228 } |
| 1187 IntersectResult(expr, cache_.kAsmDouble); | 1229 IntersectResult(expr, cache_.kAsmDouble); |
| 1188 return; | 1230 return; |
| 1189 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) { | 1231 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) { |
| 1190 if (left_intish != 0 || right_intish != 0) { | 1232 if (left_intish != 0 || right_intish != 0) { |
| 1191 FAIL(expr, "float operation before required fround"); | 1233 FAIL(expr, "float operation before required fround"); |
| 1192 } | 1234 } |
| 1193 IntersectResult(expr, cache_.kAsmFloat); | 1235 IntersectResult(expr, cache_.kAsmFloat); |
| 1194 intish_ = 1; | 1236 intish_ = 1; |
| 1195 return; | 1237 return; |
| 1196 } else if (type->Is(cache_.kAsmDouble)) { | 1238 } else if (type->Is(cache_.kAsmDouble)) { |
| 1197 IntersectResult(expr, cache_.kAsmDouble); | 1239 IntersectResult(expr, cache_.kAsmDouble); |
| 1198 return; | 1240 return; |
| 1199 } else { | 1241 } else { |
| 1200 FAIL(expr, "ill-typed arithmetic operation"); | 1242 FAIL(expr, "ill-typed arithmetic operation"); |
| 1201 } | 1243 } |
| 1202 } | 1244 } |
| 1203 default: | 1245 default: |
| 1204 UNREACHABLE(); | 1246 UNREACHABLE(); |
| 1205 } | 1247 } |
| 1206 } | 1248 } |
| 1207 | 1249 |
| 1208 | 1250 |
| 1209 void AsmTyper::VisitCompareOperation(CompareOperation* expr) { | 1251 void AsmTyper::VisitCompareOperation(CompareOperation* expr) { |
| 1252 if (!in_function_) { |
| 1253 FAIL(expr, "comparison inside module body"); |
| 1254 } |
| 1210 Token::Value op = expr->op(); | 1255 Token::Value op = expr->op(); |
| 1211 if (op != Token::EQ && op != Token::NE && op != Token::LT && | 1256 if (op != Token::EQ && op != Token::NE && op != Token::LT && |
| 1212 op != Token::LTE && op != Token::GT && op != Token::GTE) { | 1257 op != Token::LTE && op != Token::GT && op != Token::GTE) { |
| 1213 FAIL(expr, "illegal comparison operator"); | 1258 FAIL(expr, "illegal comparison operator"); |
| 1214 } | 1259 } |
| 1215 | 1260 |
| 1216 RECURSE( | 1261 RECURSE( |
| 1217 VisitWithExpectation(expr->left(), Type::Number(), | 1262 VisitWithExpectation(expr->left(), Type::Number(zone()), |
| 1218 "left comparison operand expected to be number")); | 1263 "left comparison operand expected to be number")); |
| 1219 Type* left_type = computed_type_; | 1264 Type* left_type = computed_type_; |
| 1220 if (!left_type->Is(cache_.kAsmComparable)) { | 1265 if (!left_type->Is(cache_.kAsmComparable)) { |
| 1221 FAIL(expr->left(), "bad type on left side of comparison"); | 1266 FAIL(expr->left(), "bad type on left side of comparison"); |
| 1222 } | 1267 } |
| 1223 | 1268 |
| 1224 RECURSE( | 1269 RECURSE( |
| 1225 VisitWithExpectation(expr->right(), Type::Number(), | 1270 VisitWithExpectation(expr->right(), Type::Number(zone()), |
| 1226 "right comparison operand expected to be number")); | 1271 "right comparison operand expected to be number")); |
| 1227 Type* right_type = computed_type_; | 1272 Type* right_type = computed_type_; |
| 1228 if (!right_type->Is(cache_.kAsmComparable)) { | 1273 if (!right_type->Is(cache_.kAsmComparable)) { |
| 1229 FAIL(expr->right(), "bad type on right side of comparison"); | 1274 FAIL(expr->right(), "bad type on right side of comparison"); |
| 1230 } | 1275 } |
| 1231 | 1276 |
| 1232 if (!left_type->Is(right_type) && !right_type->Is(left_type)) { | 1277 if (!left_type->Is(right_type) && !right_type->Is(left_type)) { |
| 1233 FAIL(expr, "left and right side of comparison must match"); | 1278 FAIL(expr, "left and right side of comparison must match"); |
| 1234 } | 1279 } |
| 1235 | 1280 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1274 | 1319 |
| 1275 | 1320 |
| 1276 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) { | 1321 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) { |
| 1277 FAIL(expr, "call reference not allowed"); | 1322 FAIL(expr, "call reference not allowed"); |
| 1278 } | 1323 } |
| 1279 | 1324 |
| 1280 | 1325 |
| 1281 void AsmTyper::InitializeStdlibSIMD() { | 1326 void AsmTyper::InitializeStdlibSIMD() { |
| 1282 #define V(NAME, Name, name, lane_count, lane_type) \ | 1327 #define V(NAME, Name, name, lane_count, lane_type) \ |
| 1283 { \ | 1328 { \ |
| 1284 Type* type = Type::Function(Type::Name(isolate_, zone()), Type::Any(), \ | 1329 Type* type = Type::Function(Type::Name(isolate_, zone()), \ |
| 1285 lane_count, zone()); \ | 1330 Type::Any(zone()), lane_count, zone()); \ |
| 1286 for (int i = 0; i < lane_count; ++i) { \ | 1331 for (int i = 0; i < lane_count; ++i) { \ |
| 1287 type->AsFunction()->InitParameter(i, Type::Number()); \ | 1332 type->AsFunction()->InitParameter(i, Type::Number(zone())); \ |
| 1288 } \ | 1333 } \ |
| 1289 stdlib_simd_##name##_constructor_type_ = new (zone()) VariableInfo(type); \ | 1334 stdlib_simd_##name##_constructor_type_ = new (zone()) VariableInfo(type); \ |
| 1290 stdlib_simd_##name##_constructor_type_->is_constructor_function = true; \ | 1335 stdlib_simd_##name##_constructor_type_->is_constructor_function = true; \ |
| 1291 } | 1336 } |
| 1292 SIMD128_TYPES(V) | 1337 SIMD128_TYPES(V) |
| 1293 #undef V | 1338 #undef V |
| 1294 } | 1339 } |
| 1295 | 1340 |
| 1296 | 1341 |
| 1297 void AsmTyper::InitializeStdlib() { | 1342 void AsmTyper::InitializeStdlib() { |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1486 | 1531 |
| 1487 | 1532 |
| 1488 void AsmTyper::VisitRewritableAssignmentExpression( | 1533 void AsmTyper::VisitRewritableAssignmentExpression( |
| 1489 RewritableAssignmentExpression* expr) { | 1534 RewritableAssignmentExpression* expr) { |
| 1490 RECURSE(Visit(expr->expression())); | 1535 RECURSE(Visit(expr->expression())); |
| 1491 } | 1536 } |
| 1492 | 1537 |
| 1493 | 1538 |
| 1494 } // namespace internal | 1539 } // namespace internal |
| 1495 } // namespace v8 | 1540 } // namespace v8 |
| OLD | NEW |