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 |