| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/crankshaft/typing.h" | 5 #include "src/crankshaft/typing.h" |
| 6 | 6 |
| 7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/frames.h" | 8 #include "src/frames.h" |
| 9 #include "src/frames-inl.h" | 9 #include "src/frames-inl.h" |
| 10 #include "src/ostreams.h" | 10 #include "src/ostreams.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 oracle_(isolate, zone, handle(closure->shared()->code()), | 26 oracle_(isolate, zone, handle(closure->shared()->code()), |
| 27 handle(closure->feedback_vector()), | 27 handle(closure->feedback_vector()), |
| 28 handle(closure->context()->native_context())), | 28 handle(closure->context()->native_context())), |
| 29 store_(zone), | 29 store_(zone), |
| 30 bounds_(bounds) { | 30 bounds_(bounds) { |
| 31 InitializeAstVisitor(isolate); | 31 InitializeAstVisitor(isolate); |
| 32 } | 32 } |
| 33 | 33 |
| 34 | 34 |
| 35 #ifdef OBJECT_PRINT | 35 #ifdef OBJECT_PRINT |
| 36 static void PrintObserved(Variable* var, Object* value, Type* type) { | 36 static void PrintObserved(Variable* var, Object* value, AstType* type) { |
| 37 OFStream os(stdout); | 37 OFStream os(stdout); |
| 38 os << " observed " << (var->IsParameter() ? "param" : "local") << " "; | 38 os << " observed " << (var->IsParameter() ? "param" : "local") << " "; |
| 39 var->name()->Print(os); | 39 var->name()->Print(os); |
| 40 os << " : " << Brief(value) << " -> "; | 40 os << " : " << Brief(value) << " -> "; |
| 41 type->PrintTo(os); | 41 type->PrintTo(os); |
| 42 os << std::endl; | 42 os << std::endl; |
| 43 } | 43 } |
| 44 #endif // OBJECT_PRINT | 44 #endif // OBJECT_PRINT |
| 45 | 45 |
| 46 | 46 |
| 47 Effect AstTyper::ObservedOnStack(Object* value) { | 47 Effect AstTyper::ObservedOnStack(Object* value) { |
| 48 Type* lower = Type::NowOf(value, zone()); | 48 AstType* lower = AstType::NowOf(value, zone()); |
| 49 return Effect(Bounds(lower, Type::Any())); | 49 return Effect(AstBounds(lower, AstType::Any())); |
| 50 } | 50 } |
| 51 | 51 |
| 52 | 52 |
| 53 void AstTyper::ObserveTypesAtOsrEntry(IterationStatement* stmt) { | 53 void AstTyper::ObserveTypesAtOsrEntry(IterationStatement* stmt) { |
| 54 if (stmt->OsrEntryId() != osr_ast_id_) return; | 54 if (stmt->OsrEntryId() != osr_ast_id_) return; |
| 55 | 55 |
| 56 DisallowHeapAllocation no_gc; | 56 DisallowHeapAllocation no_gc; |
| 57 JavaScriptFrameIterator it(isolate_); | 57 JavaScriptFrameIterator it(isolate_); |
| 58 JavaScriptFrame* frame = it.frame(); | 58 JavaScriptFrame* frame = it.frame(); |
| 59 | 59 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 bool complex_effects = false; // True for label effects or fall-through. | 199 bool complex_effects = false; // True for label effects or fall-through. |
| 200 | 200 |
| 201 for (int i = 0; i < clauses->length(); ++i) { | 201 for (int i = 0; i < clauses->length(); ++i) { |
| 202 CaseClause* clause = clauses->at(i); | 202 CaseClause* clause = clauses->at(i); |
| 203 | 203 |
| 204 Effects clause_effects = EnterEffects(); | 204 Effects clause_effects = EnterEffects(); |
| 205 | 205 |
| 206 if (!clause->is_default()) { | 206 if (!clause->is_default()) { |
| 207 Expression* label = clause->label(); | 207 Expression* label = clause->label(); |
| 208 // Collect type feedback. | 208 // Collect type feedback. |
| 209 Type* tag_type; | 209 AstType* tag_type; |
| 210 Type* label_type; | 210 AstType* label_type; |
| 211 Type* combined_type; | 211 AstType* combined_type; |
| 212 oracle()->CompareType(clause->CompareId(), | 212 oracle()->CompareType(clause->CompareId(), |
| 213 &tag_type, &label_type, &combined_type); | 213 &tag_type, &label_type, &combined_type); |
| 214 NarrowLowerType(stmt->tag(), tag_type); | 214 NarrowLowerType(stmt->tag(), tag_type); |
| 215 NarrowLowerType(label, label_type); | 215 NarrowLowerType(label, label_type); |
| 216 clause->set_compare_type(combined_type); | 216 clause->set_compare_type(combined_type); |
| 217 | 217 |
| 218 RECURSE(Visit(label)); | 218 RECURSE(Visit(label)); |
| 219 if (!clause_effects.IsEmpty()) complex_effects = true; | 219 if (!clause_effects.IsEmpty()) complex_effects = true; |
| 220 } | 220 } |
| 221 | 221 |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 Effects then_effects = EnterEffects(); | 360 Effects then_effects = EnterEffects(); |
| 361 RECURSE(Visit(expr->then_expression())); | 361 RECURSE(Visit(expr->then_expression())); |
| 362 ExitEffects(); | 362 ExitEffects(); |
| 363 Effects else_effects = EnterEffects(); | 363 Effects else_effects = EnterEffects(); |
| 364 RECURSE(Visit(expr->else_expression())); | 364 RECURSE(Visit(expr->else_expression())); |
| 365 ExitEffects(); | 365 ExitEffects(); |
| 366 then_effects.Alt(else_effects); | 366 then_effects.Alt(else_effects); |
| 367 store_.Seq(then_effects); | 367 store_.Seq(then_effects); |
| 368 | 368 |
| 369 NarrowType(expr, | 369 NarrowType(expr, |
| 370 Bounds::Either(bounds_->get(expr->then_expression()), | 370 AstBounds::Either(bounds_->get(expr->then_expression()), |
| 371 bounds_->get(expr->else_expression()), zone())); | 371 bounds_->get(expr->else_expression()), zone())); |
| 372 } | 372 } |
| 373 | 373 |
| 374 | 374 |
| 375 void AstTyper::VisitVariableProxy(VariableProxy* expr) { | 375 void AstTyper::VisitVariableProxy(VariableProxy* expr) { |
| 376 Variable* var = expr->var(); | 376 Variable* var = expr->var(); |
| 377 if (var->IsStackAllocated()) { | 377 if (var->IsStackAllocated()) { |
| 378 NarrowType(expr, store_.LookupBounds(variable_index(var))); | 378 NarrowType(expr, store_.LookupBounds(variable_index(var))); |
| 379 } | 379 } |
| 380 } | 380 } |
| 381 | 381 |
| 382 | 382 |
| 383 void AstTyper::VisitLiteral(Literal* expr) { | 383 void AstTyper::VisitLiteral(Literal* expr) { |
| 384 Type* type = Type::Constant(expr->value(), zone()); | 384 AstType* type = AstType::Constant(expr->value(), zone()); |
| 385 NarrowType(expr, Bounds(type)); | 385 NarrowType(expr, AstBounds(type)); |
| 386 } | 386 } |
| 387 | 387 |
| 388 | 388 |
| 389 void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) { | 389 void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 390 // TODO(rossberg): Reintroduce RegExp type. | 390 // TODO(rossberg): Reintroduce RegExp type. |
| 391 NarrowType(expr, Bounds(Type::Object())); | 391 NarrowType(expr, AstBounds(AstType::Object())); |
| 392 } | 392 } |
| 393 | 393 |
| 394 | 394 |
| 395 void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) { | 395 void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) { |
| 396 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); | 396 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); |
| 397 for (int i = 0; i < properties->length(); ++i) { | 397 for (int i = 0; i < properties->length(); ++i) { |
| 398 ObjectLiteral::Property* prop = properties->at(i); | 398 ObjectLiteral::Property* prop = properties->at(i); |
| 399 | 399 |
| 400 // Collect type feedback. | 400 // Collect type feedback. |
| 401 if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL && | 401 if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL && |
| 402 !CompileTimeValue::IsCompileTimeValue(prop->value())) || | 402 !CompileTimeValue::IsCompileTimeValue(prop->value())) || |
| 403 prop->kind() == ObjectLiteral::Property::COMPUTED) { | 403 prop->kind() == ObjectLiteral::Property::COMPUTED) { |
| 404 if (!prop->is_computed_name() && | 404 if (!prop->is_computed_name() && |
| 405 prop->key()->AsLiteral()->value()->IsInternalizedString() && | 405 prop->key()->AsLiteral()->value()->IsInternalizedString() && |
| 406 prop->emit_store()) { | 406 prop->emit_store()) { |
| 407 // Record type feed back for the property. | 407 // Record type feed back for the property. |
| 408 FeedbackVectorSlot slot = prop->GetSlot(); | 408 FeedbackVectorSlot slot = prop->GetSlot(); |
| 409 SmallMapList maps; | 409 SmallMapList maps; |
| 410 oracle()->CollectReceiverTypes(slot, &maps); | 410 oracle()->CollectReceiverTypes(slot, &maps); |
| 411 prop->set_receiver_type(maps.length() == 1 ? maps.at(0) | 411 prop->set_receiver_type(maps.length() == 1 ? maps.at(0) |
| 412 : Handle<Map>::null()); | 412 : Handle<Map>::null()); |
| 413 } | 413 } |
| 414 } | 414 } |
| 415 | 415 |
| 416 RECURSE(Visit(prop->value())); | 416 RECURSE(Visit(prop->value())); |
| 417 } | 417 } |
| 418 | 418 |
| 419 NarrowType(expr, Bounds(Type::Object())); | 419 NarrowType(expr, AstBounds(AstType::Object())); |
| 420 } | 420 } |
| 421 | 421 |
| 422 | 422 |
| 423 void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) { | 423 void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) { |
| 424 ZoneList<Expression*>* values = expr->values(); | 424 ZoneList<Expression*>* values = expr->values(); |
| 425 for (int i = 0; i < values->length(); ++i) { | 425 for (int i = 0; i < values->length(); ++i) { |
| 426 Expression* value = values->at(i); | 426 Expression* value = values->at(i); |
| 427 RECURSE(Visit(value)); | 427 RECURSE(Visit(value)); |
| 428 } | 428 } |
| 429 | 429 |
| 430 NarrowType(expr, Bounds(Type::Object())); | 430 NarrowType(expr, AstBounds(AstType::Object())); |
| 431 } | 431 } |
| 432 | 432 |
| 433 | 433 |
| 434 void AstTyper::VisitAssignment(Assignment* expr) { | 434 void AstTyper::VisitAssignment(Assignment* expr) { |
| 435 // Collect type feedback. | 435 // Collect type feedback. |
| 436 Property* prop = expr->target()->AsProperty(); | 436 Property* prop = expr->target()->AsProperty(); |
| 437 if (prop != NULL) { | 437 if (prop != NULL) { |
| 438 FeedbackVectorSlot slot = expr->AssignmentSlot(); | 438 FeedbackVectorSlot slot = expr->AssignmentSlot(); |
| 439 expr->set_is_uninitialized(oracle()->StoreIsUninitialized(slot)); | 439 expr->set_is_uninitialized(oracle()->StoreIsUninitialized(slot)); |
| 440 if (!expr->IsUninitialized()) { | 440 if (!expr->IsUninitialized()) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 RECURSE(Visit(expr->expression())); | 473 RECURSE(Visit(expr->expression())); |
| 474 | 474 |
| 475 // We don't know anything about the result type. | 475 // We don't know anything about the result type. |
| 476 } | 476 } |
| 477 | 477 |
| 478 | 478 |
| 479 void AstTyper::VisitThrow(Throw* expr) { | 479 void AstTyper::VisitThrow(Throw* expr) { |
| 480 RECURSE(Visit(expr->exception())); | 480 RECURSE(Visit(expr->exception())); |
| 481 // TODO(rossberg): is it worth having a non-termination effect? | 481 // TODO(rossberg): is it worth having a non-termination effect? |
| 482 | 482 |
| 483 NarrowType(expr, Bounds(Type::None())); | 483 NarrowType(expr, AstBounds(AstType::None())); |
| 484 } | 484 } |
| 485 | 485 |
| 486 | 486 |
| 487 void AstTyper::VisitProperty(Property* expr) { | 487 void AstTyper::VisitProperty(Property* expr) { |
| 488 // Collect type feedback. | 488 // Collect type feedback. |
| 489 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); | 489 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); |
| 490 expr->set_inline_cache_state(oracle()->LoadInlineCacheState(slot)); | 490 expr->set_inline_cache_state(oracle()->LoadInlineCacheState(slot)); |
| 491 | 491 |
| 492 if (!expr->IsUninitialized()) { | 492 if (!expr->IsUninitialized()) { |
| 493 if (expr->key()->IsPropertyName()) { | 493 if (expr->key()->IsPropertyName()) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 expr->set_target(oracle()->GetCallNewTarget(expr->CallNewFeedbackSlot())); | 556 expr->set_target(oracle()->GetCallNewTarget(expr->CallNewFeedbackSlot())); |
| 557 } | 557 } |
| 558 | 558 |
| 559 RECURSE(Visit(expr->expression())); | 559 RECURSE(Visit(expr->expression())); |
| 560 ZoneList<Expression*>* args = expr->arguments(); | 560 ZoneList<Expression*>* args = expr->arguments(); |
| 561 for (int i = 0; i < args->length(); ++i) { | 561 for (int i = 0; i < args->length(); ++i) { |
| 562 Expression* arg = args->at(i); | 562 Expression* arg = args->at(i); |
| 563 RECURSE(Visit(arg)); | 563 RECURSE(Visit(arg)); |
| 564 } | 564 } |
| 565 | 565 |
| 566 NarrowType(expr, Bounds(Type::None(), Type::Receiver())); | 566 NarrowType(expr, AstBounds(AstType::None(), AstType::Receiver())); |
| 567 } | 567 } |
| 568 | 568 |
| 569 | 569 |
| 570 void AstTyper::VisitCallRuntime(CallRuntime* expr) { | 570 void AstTyper::VisitCallRuntime(CallRuntime* expr) { |
| 571 ZoneList<Expression*>* args = expr->arguments(); | 571 ZoneList<Expression*>* args = expr->arguments(); |
| 572 for (int i = 0; i < args->length(); ++i) { | 572 for (int i = 0; i < args->length(); ++i) { |
| 573 Expression* arg = args->at(i); | 573 Expression* arg = args->at(i); |
| 574 RECURSE(Visit(arg)); | 574 RECURSE(Visit(arg)); |
| 575 } | 575 } |
| 576 | 576 |
| 577 // We don't know anything about the result type. | 577 // We don't know anything about the result type. |
| 578 } | 578 } |
| 579 | 579 |
| 580 | 580 |
| 581 void AstTyper::VisitUnaryOperation(UnaryOperation* expr) { | 581 void AstTyper::VisitUnaryOperation(UnaryOperation* expr) { |
| 582 // Collect type feedback. | 582 // Collect type feedback. |
| 583 if (expr->op() == Token::NOT) { | 583 if (expr->op() == Token::NOT) { |
| 584 // TODO(rossberg): only do in test or value context. | 584 // TODO(rossberg): only do in test or value context. |
| 585 expr->expression()->RecordToBooleanTypeFeedback(oracle()); | 585 expr->expression()->RecordToBooleanTypeFeedback(oracle()); |
| 586 } | 586 } |
| 587 | 587 |
| 588 RECURSE(Visit(expr->expression())); | 588 RECURSE(Visit(expr->expression())); |
| 589 | 589 |
| 590 switch (expr->op()) { | 590 switch (expr->op()) { |
| 591 case Token::NOT: | 591 case Token::NOT: |
| 592 case Token::DELETE: | 592 case Token::DELETE: |
| 593 NarrowType(expr, Bounds(Type::Boolean())); | 593 NarrowType(expr, AstBounds(AstType::Boolean())); |
| 594 break; | 594 break; |
| 595 case Token::VOID: | 595 case Token::VOID: |
| 596 NarrowType(expr, Bounds(Type::Undefined())); | 596 NarrowType(expr, AstBounds(AstType::Undefined())); |
| 597 break; | 597 break; |
| 598 case Token::TYPEOF: | 598 case Token::TYPEOF: |
| 599 NarrowType(expr, Bounds(Type::InternalizedString())); | 599 NarrowType(expr, AstBounds(AstType::InternalizedString())); |
| 600 break; | 600 break; |
| 601 default: | 601 default: |
| 602 UNREACHABLE(); | 602 UNREACHABLE(); |
| 603 } | 603 } |
| 604 } | 604 } |
| 605 | 605 |
| 606 | 606 |
| 607 void AstTyper::VisitCountOperation(CountOperation* expr) { | 607 void AstTyper::VisitCountOperation(CountOperation* expr) { |
| 608 // Collect type feedback. | 608 // Collect type feedback. |
| 609 FeedbackVectorSlot slot = expr->CountSlot(); | 609 FeedbackVectorSlot slot = expr->CountSlot(); |
| 610 KeyedAccessStoreMode store_mode; | 610 KeyedAccessStoreMode store_mode; |
| 611 IcCheckType key_type; | 611 IcCheckType key_type; |
| 612 oracle()->GetStoreModeAndKeyType(slot, &store_mode, &key_type); | 612 oracle()->GetStoreModeAndKeyType(slot, &store_mode, &key_type); |
| 613 oracle()->CountReceiverTypes(slot, expr->GetReceiverTypes()); | 613 oracle()->CountReceiverTypes(slot, expr->GetReceiverTypes()); |
| 614 expr->set_store_mode(store_mode); | 614 expr->set_store_mode(store_mode); |
| 615 expr->set_key_type(key_type); | 615 expr->set_key_type(key_type); |
| 616 expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId())); | 616 expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId())); |
| 617 // TODO(rossberg): merge the count type with the generic expression type. | 617 // TODO(rossberg): merge the count type with the generic expression type. |
| 618 | 618 |
| 619 RECURSE(Visit(expr->expression())); | 619 RECURSE(Visit(expr->expression())); |
| 620 | 620 |
| 621 NarrowType(expr, Bounds(Type::SignedSmall(), Type::Number())); | 621 NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Number())); |
| 622 | 622 |
| 623 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 623 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 624 if (proxy != NULL && proxy->var()->IsStackAllocated()) { | 624 if (proxy != NULL && proxy->var()->IsStackAllocated()) { |
| 625 store_.Seq(variable_index(proxy->var()), Effect(bounds_->get(expr))); | 625 store_.Seq(variable_index(proxy->var()), Effect(bounds_->get(expr))); |
| 626 } | 626 } |
| 627 } | 627 } |
| 628 | 628 |
| 629 | 629 |
| 630 void AstTyper::VisitBinaryOperation(BinaryOperation* expr) { | 630 void AstTyper::VisitBinaryOperation(BinaryOperation* expr) { |
| 631 // Collect type feedback. | 631 // Collect type feedback. |
| 632 Type* type; | 632 AstType* type; |
| 633 Type* left_type; | 633 AstType* left_type; |
| 634 Type* right_type; | 634 AstType* right_type; |
| 635 Maybe<int> fixed_right_arg = Nothing<int>(); | 635 Maybe<int> fixed_right_arg = Nothing<int>(); |
| 636 Handle<AllocationSite> allocation_site; | 636 Handle<AllocationSite> allocation_site; |
| 637 oracle()->BinaryType(expr->BinaryOperationFeedbackId(), | 637 oracle()->BinaryType(expr->BinaryOperationFeedbackId(), |
| 638 &left_type, &right_type, &type, &fixed_right_arg, | 638 &left_type, &right_type, &type, &fixed_right_arg, |
| 639 &allocation_site, expr->op()); | 639 &allocation_site, expr->op()); |
| 640 NarrowLowerType(expr, type); | 640 NarrowLowerType(expr, type); |
| 641 NarrowLowerType(expr->left(), left_type); | 641 NarrowLowerType(expr->left(), left_type); |
| 642 NarrowLowerType(expr->right(), right_type); | 642 NarrowLowerType(expr->right(), right_type); |
| 643 expr->set_allocation_site(allocation_site); | 643 expr->set_allocation_site(allocation_site); |
| 644 expr->set_fixed_right_arg(fixed_right_arg); | 644 expr->set_fixed_right_arg(fixed_right_arg); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 656 case Token::AND: { | 656 case Token::AND: { |
| 657 Effects left_effects = EnterEffects(); | 657 Effects left_effects = EnterEffects(); |
| 658 RECURSE(Visit(expr->left())); | 658 RECURSE(Visit(expr->left())); |
| 659 ExitEffects(); | 659 ExitEffects(); |
| 660 Effects right_effects = EnterEffects(); | 660 Effects right_effects = EnterEffects(); |
| 661 RECURSE(Visit(expr->right())); | 661 RECURSE(Visit(expr->right())); |
| 662 ExitEffects(); | 662 ExitEffects(); |
| 663 left_effects.Alt(right_effects); | 663 left_effects.Alt(right_effects); |
| 664 store_.Seq(left_effects); | 664 store_.Seq(left_effects); |
| 665 | 665 |
| 666 NarrowType(expr, Bounds::Either(bounds_->get(expr->left()), | 666 NarrowType(expr, AstBounds::Either(bounds_->get(expr->left()), |
| 667 bounds_->get(expr->right()), zone())); | 667 bounds_->get(expr->right()), zone())); |
| 668 break; | 668 break; |
| 669 } | 669 } |
| 670 case Token::BIT_OR: | 670 case Token::BIT_OR: |
| 671 case Token::BIT_AND: { | 671 case Token::BIT_AND: { |
| 672 RECURSE(Visit(expr->left())); | 672 RECURSE(Visit(expr->left())); |
| 673 RECURSE(Visit(expr->right())); | 673 RECURSE(Visit(expr->right())); |
| 674 Type* upper = Type::Union(bounds_->get(expr->left()).upper, | 674 AstType* upper = |
| 675 bounds_->get(expr->right()).upper, zone()); | 675 AstType::Union(bounds_->get(expr->left()).upper, |
| 676 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(); | 676 bounds_->get(expr->right()).upper, zone()); |
| 677 Type* lower = Type::Intersect(Type::SignedSmall(), upper, zone()); | 677 if (!upper->Is(AstType::Signed32())) upper = AstType::Signed32(); |
| 678 NarrowType(expr, Bounds(lower, upper)); | 678 AstType* lower = |
| 679 AstType::Intersect(AstType::SignedSmall(), upper, zone()); |
| 680 NarrowType(expr, AstBounds(lower, upper)); |
| 679 break; | 681 break; |
| 680 } | 682 } |
| 681 case Token::BIT_XOR: | 683 case Token::BIT_XOR: |
| 682 case Token::SHL: | 684 case Token::SHL: |
| 683 case Token::SAR: | 685 case Token::SAR: |
| 684 RECURSE(Visit(expr->left())); | 686 RECURSE(Visit(expr->left())); |
| 685 RECURSE(Visit(expr->right())); | 687 RECURSE(Visit(expr->right())); |
| 686 NarrowType(expr, Bounds(Type::SignedSmall(), Type::Signed32())); | 688 NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Signed32())); |
| 687 break; | 689 break; |
| 688 case Token::SHR: | 690 case Token::SHR: |
| 689 RECURSE(Visit(expr->left())); | 691 RECURSE(Visit(expr->left())); |
| 690 RECURSE(Visit(expr->right())); | 692 RECURSE(Visit(expr->right())); |
| 691 // TODO(rossberg): The upper bound would be Unsigned32, but since there | 693 // TODO(rossberg): The upper bound would be Unsigned32, but since there |
| 692 // is no 'positive Smi' type for the lower bound, we use the smallest | 694 // is no 'positive Smi' type for the lower bound, we use the smallest |
| 693 // union of Smi and Unsigned32 as upper bound instead. | 695 // union of Smi and Unsigned32 as upper bound instead. |
| 694 NarrowType(expr, Bounds(Type::SignedSmall(), Type::Number())); | 696 NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Number())); |
| 695 break; | 697 break; |
| 696 case Token::ADD: { | 698 case Token::ADD: { |
| 697 RECURSE(Visit(expr->left())); | 699 RECURSE(Visit(expr->left())); |
| 698 RECURSE(Visit(expr->right())); | 700 RECURSE(Visit(expr->right())); |
| 699 Bounds l = bounds_->get(expr->left()); | 701 AstBounds l = bounds_->get(expr->left()); |
| 700 Bounds r = bounds_->get(expr->right()); | 702 AstBounds r = bounds_->get(expr->right()); |
| 701 Type* lower = | 703 AstType* lower = |
| 702 !l.lower->IsInhabited() || !r.lower->IsInhabited() | 704 !l.lower->IsInhabited() || !r.lower->IsInhabited() |
| 703 ? Type::None() | 705 ? AstType::None() |
| 704 : l.lower->Is(Type::String()) || r.lower->Is(Type::String()) | 706 : l.lower->Is(AstType::String()) || r.lower->Is(AstType::String()) |
| 705 ? Type::String() | 707 ? AstType::String() |
| 706 : l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) | 708 : l.lower->Is(AstType::Number()) && |
| 707 ? Type::SignedSmall() | 709 r.lower->Is(AstType::Number()) |
| 708 : Type::None(); | 710 ? AstType::SignedSmall() |
| 709 Type* upper = | 711 : AstType::None(); |
| 710 l.upper->Is(Type::String()) || r.upper->Is(Type::String()) | 712 AstType* upper = |
| 711 ? Type::String() | 713 l.upper->Is(AstType::String()) || r.upper->Is(AstType::String()) |
| 712 : l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) | 714 ? AstType::String() |
| 713 ? Type::Number() | 715 : l.upper->Is(AstType::Number()) && r.upper->Is(AstType::Number()) |
| 714 : Type::NumberOrString(); | 716 ? AstType::Number() |
| 715 NarrowType(expr, Bounds(lower, upper)); | 717 : AstType::NumberOrString(); |
| 718 NarrowType(expr, AstBounds(lower, upper)); |
| 716 break; | 719 break; |
| 717 } | 720 } |
| 718 case Token::SUB: | 721 case Token::SUB: |
| 719 case Token::MUL: | 722 case Token::MUL: |
| 720 case Token::DIV: | 723 case Token::DIV: |
| 721 case Token::MOD: | 724 case Token::MOD: |
| 722 RECURSE(Visit(expr->left())); | 725 RECURSE(Visit(expr->left())); |
| 723 RECURSE(Visit(expr->right())); | 726 RECURSE(Visit(expr->right())); |
| 724 NarrowType(expr, Bounds(Type::SignedSmall(), Type::Number())); | 727 NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Number())); |
| 725 break; | 728 break; |
| 726 default: | 729 default: |
| 727 UNREACHABLE(); | 730 UNREACHABLE(); |
| 728 } | 731 } |
| 729 } | 732 } |
| 730 | 733 |
| 731 | 734 |
| 732 void AstTyper::VisitCompareOperation(CompareOperation* expr) { | 735 void AstTyper::VisitCompareOperation(CompareOperation* expr) { |
| 733 // Collect type feedback. | 736 // Collect type feedback. |
| 734 Type* left_type; | 737 AstType* left_type; |
| 735 Type* right_type; | 738 AstType* right_type; |
| 736 Type* combined_type; | 739 AstType* combined_type; |
| 737 oracle()->CompareType(expr->CompareOperationFeedbackId(), | 740 oracle()->CompareType(expr->CompareOperationFeedbackId(), |
| 738 &left_type, &right_type, &combined_type); | 741 &left_type, &right_type, &combined_type); |
| 739 NarrowLowerType(expr->left(), left_type); | 742 NarrowLowerType(expr->left(), left_type); |
| 740 NarrowLowerType(expr->right(), right_type); | 743 NarrowLowerType(expr->right(), right_type); |
| 741 expr->set_combined_type(combined_type); | 744 expr->set_combined_type(combined_type); |
| 742 | 745 |
| 743 RECURSE(Visit(expr->left())); | 746 RECURSE(Visit(expr->left())); |
| 744 RECURSE(Visit(expr->right())); | 747 RECURSE(Visit(expr->right())); |
| 745 | 748 |
| 746 NarrowType(expr, Bounds(Type::Boolean())); | 749 NarrowType(expr, AstBounds(AstType::Boolean())); |
| 747 } | 750 } |
| 748 | 751 |
| 749 | 752 |
| 750 void AstTyper::VisitSpread(Spread* expr) { UNREACHABLE(); } | 753 void AstTyper::VisitSpread(Spread* expr) { UNREACHABLE(); } |
| 751 | 754 |
| 752 | 755 |
| 753 void AstTyper::VisitEmptyParentheses(EmptyParentheses* expr) { | 756 void AstTyper::VisitEmptyParentheses(EmptyParentheses* expr) { |
| 754 UNREACHABLE(); | 757 UNREACHABLE(); |
| 755 } | 758 } |
| 756 | 759 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 781 } | 784 } |
| 782 | 785 |
| 783 | 786 |
| 784 void AstTyper::VisitFunctionDeclaration(FunctionDeclaration* declaration) { | 787 void AstTyper::VisitFunctionDeclaration(FunctionDeclaration* declaration) { |
| 785 RECURSE(Visit(declaration->fun())); | 788 RECURSE(Visit(declaration->fun())); |
| 786 } | 789 } |
| 787 | 790 |
| 788 | 791 |
| 789 } // namespace internal | 792 } // namespace internal |
| 790 } // namespace v8 | 793 } // namespace v8 |
| OLD | NEW |