| 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" |
| 11 #include "src/parsing/parser.h" // for CompileTimeValue; TODO(rossberg): move | 11 #include "src/parsing/parser.h" // for CompileTimeValue; TODO(rossberg): move |
| 12 #include "src/splay-tree-inl.h" | 12 #include "src/splay-tree-inl.h" |
| 13 | 13 |
| 14 namespace v8 { | 14 namespace v8 { |
| 15 namespace internal { | 15 namespace internal { |
| 16 | 16 |
| 17 | |
| 18 AstTyper::AstTyper(Isolate* isolate, Zone* zone, Handle<JSFunction> closure, | 17 AstTyper::AstTyper(Isolate* isolate, Zone* zone, Handle<JSFunction> closure, |
| 19 Scope* scope, BailoutId osr_ast_id, FunctionLiteral* root) | 18 Scope* scope, BailoutId osr_ast_id, FunctionLiteral* root, |
| 19 AstTypeBounds* bounds) |
| 20 : isolate_(isolate), | 20 : isolate_(isolate), |
| 21 zone_(zone), | 21 zone_(zone), |
| 22 closure_(closure), | 22 closure_(closure), |
| 23 scope_(scope), | 23 scope_(scope), |
| 24 osr_ast_id_(osr_ast_id), | 24 osr_ast_id_(osr_ast_id), |
| 25 root_(root), | 25 root_(root), |
| 26 oracle_(isolate, zone, handle(closure->shared()->code()), | 26 oracle_(isolate, zone, handle(closure->shared()->code()), |
| 27 handle(closure->shared()->feedback_vector()), | 27 handle(closure->shared()->feedback_vector()), |
| 28 handle(closure->context()->native_context())), | 28 handle(closure->context()->native_context())), |
| 29 store_(zone) { | 29 store_(zone), |
| 30 bounds_(bounds) { |
| 30 InitializeAstVisitor(isolate); | 31 InitializeAstVisitor(isolate); |
| 31 } | 32 } |
| 32 | 33 |
| 33 | 34 |
| 34 #ifdef OBJECT_PRINT | 35 #ifdef OBJECT_PRINT |
| 35 static void PrintObserved(Variable* var, Object* value, Type* type) { | 36 static void PrintObserved(Variable* var, Object* value, Type* type) { |
| 36 OFStream os(stdout); | 37 OFStream os(stdout); |
| 37 os << " observed " << (var->IsParameter() ? "param" : "local") << " "; | 38 os << " observed " << (var->IsParameter() ? "param" : "local") << " "; |
| 38 var->name()->Print(os); | 39 var->name()->Print(os); |
| 39 os << " : " << Brief(value) << " -> "; | 40 os << " : " << Brief(value) << " -> "; |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 void AstTyper::VisitClassLiteral(ClassLiteral* expr) {} | 347 void AstTyper::VisitClassLiteral(ClassLiteral* expr) {} |
| 347 | 348 |
| 348 | 349 |
| 349 void AstTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 350 void AstTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
| 350 } | 351 } |
| 351 | 352 |
| 352 | 353 |
| 353 void AstTyper::VisitDoExpression(DoExpression* expr) { | 354 void AstTyper::VisitDoExpression(DoExpression* expr) { |
| 354 RECURSE(VisitBlock(expr->block())); | 355 RECURSE(VisitBlock(expr->block())); |
| 355 RECURSE(VisitVariableProxy(expr->result())); | 356 RECURSE(VisitVariableProxy(expr->result())); |
| 356 NarrowType(expr, expr->result()->bounds()); | 357 NarrowType(expr, bounds_->get(expr->result())); |
| 357 } | 358 } |
| 358 | 359 |
| 359 | 360 |
| 360 void AstTyper::VisitConditional(Conditional* expr) { | 361 void AstTyper::VisitConditional(Conditional* expr) { |
| 361 // Collect type feedback. | 362 // Collect type feedback. |
| 362 expr->condition()->RecordToBooleanTypeFeedback(oracle()); | 363 expr->condition()->RecordToBooleanTypeFeedback(oracle()); |
| 363 | 364 |
| 364 RECURSE(Visit(expr->condition())); | 365 RECURSE(Visit(expr->condition())); |
| 365 Effects then_effects = EnterEffects(); | 366 Effects then_effects = EnterEffects(); |
| 366 RECURSE(Visit(expr->then_expression())); | 367 RECURSE(Visit(expr->then_expression())); |
| 367 ExitEffects(); | 368 ExitEffects(); |
| 368 Effects else_effects = EnterEffects(); | 369 Effects else_effects = EnterEffects(); |
| 369 RECURSE(Visit(expr->else_expression())); | 370 RECURSE(Visit(expr->else_expression())); |
| 370 ExitEffects(); | 371 ExitEffects(); |
| 371 then_effects.Alt(else_effects); | 372 then_effects.Alt(else_effects); |
| 372 store_.Seq(then_effects); | 373 store_.Seq(then_effects); |
| 373 | 374 |
| 374 NarrowType(expr, Bounds::Either( | 375 NarrowType(expr, |
| 375 expr->then_expression()->bounds(), | 376 Bounds::Either(bounds_->get(expr->then_expression()), |
| 376 expr->else_expression()->bounds(), zone())); | 377 bounds_->get(expr->else_expression()), zone())); |
| 377 } | 378 } |
| 378 | 379 |
| 379 | 380 |
| 380 void AstTyper::VisitVariableProxy(VariableProxy* expr) { | 381 void AstTyper::VisitVariableProxy(VariableProxy* expr) { |
| 381 Variable* var = expr->var(); | 382 Variable* var = expr->var(); |
| 382 if (var->IsStackAllocated()) { | 383 if (var->IsStackAllocated()) { |
| 383 NarrowType(expr, store_.LookupBounds(variable_index(var))); | 384 NarrowType(expr, store_.LookupBounds(variable_index(var))); |
| 384 } | 385 } |
| 385 } | 386 } |
| 386 | 387 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 expr->set_store_mode(store_mode); | 458 expr->set_store_mode(store_mode); |
| 458 expr->set_key_type(key_type); | 459 expr->set_key_type(key_type); |
| 459 } | 460 } |
| 460 } | 461 } |
| 461 } | 462 } |
| 462 | 463 |
| 463 Expression* rhs = | 464 Expression* rhs = |
| 464 expr->is_compound() ? expr->binary_operation() : expr->value(); | 465 expr->is_compound() ? expr->binary_operation() : expr->value(); |
| 465 RECURSE(Visit(expr->target())); | 466 RECURSE(Visit(expr->target())); |
| 466 RECURSE(Visit(rhs)); | 467 RECURSE(Visit(rhs)); |
| 467 NarrowType(expr, rhs->bounds()); | 468 NarrowType(expr, bounds_->get(rhs)); |
| 468 | 469 |
| 469 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 470 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
| 470 if (proxy != NULL && proxy->var()->IsStackAllocated()) { | 471 if (proxy != NULL && proxy->var()->IsStackAllocated()) { |
| 471 store_.Seq(variable_index(proxy->var()), Effect(expr->bounds())); | 472 store_.Seq(variable_index(proxy->var()), Effect(bounds_->get(expr))); |
| 472 } | 473 } |
| 473 } | 474 } |
| 474 | 475 |
| 475 | 476 |
| 476 void AstTyper::VisitYield(Yield* expr) { | 477 void AstTyper::VisitYield(Yield* expr) { |
| 477 RECURSE(Visit(expr->generator_object())); | 478 RECURSE(Visit(expr->generator_object())); |
| 478 RECURSE(Visit(expr->expression())); | 479 RECURSE(Visit(expr->expression())); |
| 479 | 480 |
| 480 // We don't know anything about the result type. | 481 // We don't know anything about the result type. |
| 481 } | 482 } |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 expr->set_key_type(key_type); | 622 expr->set_key_type(key_type); |
| 622 expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId())); | 623 expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId())); |
| 623 // TODO(rossberg): merge the count type with the generic expression type. | 624 // TODO(rossberg): merge the count type with the generic expression type. |
| 624 | 625 |
| 625 RECURSE(Visit(expr->expression())); | 626 RECURSE(Visit(expr->expression())); |
| 626 | 627 |
| 627 NarrowType(expr, Bounds(Type::SignedSmall(), Type::Number())); | 628 NarrowType(expr, Bounds(Type::SignedSmall(), Type::Number())); |
| 628 | 629 |
| 629 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 630 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 630 if (proxy != NULL && proxy->var()->IsStackAllocated()) { | 631 if (proxy != NULL && proxy->var()->IsStackAllocated()) { |
| 631 store_.Seq(variable_index(proxy->var()), Effect(expr->bounds())); | 632 store_.Seq(variable_index(proxy->var()), Effect(bounds_->get(expr))); |
| 632 } | 633 } |
| 633 } | 634 } |
| 634 | 635 |
| 635 | 636 |
| 636 void AstTyper::VisitBinaryOperation(BinaryOperation* expr) { | 637 void AstTyper::VisitBinaryOperation(BinaryOperation* expr) { |
| 637 // Collect type feedback. | 638 // Collect type feedback. |
| 638 Type* type; | 639 Type* type; |
| 639 Type* left_type; | 640 Type* left_type; |
| 640 Type* right_type; | 641 Type* right_type; |
| 641 Maybe<int> fixed_right_arg = Nothing<int>(); | 642 Maybe<int> fixed_right_arg = Nothing<int>(); |
| 642 Handle<AllocationSite> allocation_site; | 643 Handle<AllocationSite> allocation_site; |
| 643 oracle()->BinaryType(expr->BinaryOperationFeedbackId(), | 644 oracle()->BinaryType(expr->BinaryOperationFeedbackId(), |
| 644 &left_type, &right_type, &type, &fixed_right_arg, | 645 &left_type, &right_type, &type, &fixed_right_arg, |
| 645 &allocation_site, expr->op()); | 646 &allocation_site, expr->op()); |
| 646 NarrowLowerType(expr, type); | 647 NarrowLowerType(expr, type); |
| 647 NarrowLowerType(expr->left(), left_type); | 648 NarrowLowerType(expr->left(), left_type); |
| 648 NarrowLowerType(expr->right(), right_type); | 649 NarrowLowerType(expr->right(), right_type); |
| 649 expr->set_allocation_site(allocation_site); | 650 expr->set_allocation_site(allocation_site); |
| 650 expr->set_fixed_right_arg(fixed_right_arg); | 651 expr->set_fixed_right_arg(fixed_right_arg); |
| 651 if (expr->op() == Token::OR || expr->op() == Token::AND) { | 652 if (expr->op() == Token::OR || expr->op() == Token::AND) { |
| 652 expr->left()->RecordToBooleanTypeFeedback(oracle()); | 653 expr->left()->RecordToBooleanTypeFeedback(oracle()); |
| 653 } | 654 } |
| 654 | 655 |
| 655 switch (expr->op()) { | 656 switch (expr->op()) { |
| 656 case Token::COMMA: | 657 case Token::COMMA: |
| 657 RECURSE(Visit(expr->left())); | 658 RECURSE(Visit(expr->left())); |
| 658 RECURSE(Visit(expr->right())); | 659 RECURSE(Visit(expr->right())); |
| 659 NarrowType(expr, expr->right()->bounds()); | 660 NarrowType(expr, bounds_->get(expr->right())); |
| 660 break; | 661 break; |
| 661 case Token::OR: | 662 case Token::OR: |
| 662 case Token::AND: { | 663 case Token::AND: { |
| 663 Effects left_effects = EnterEffects(); | 664 Effects left_effects = EnterEffects(); |
| 664 RECURSE(Visit(expr->left())); | 665 RECURSE(Visit(expr->left())); |
| 665 ExitEffects(); | 666 ExitEffects(); |
| 666 Effects right_effects = EnterEffects(); | 667 Effects right_effects = EnterEffects(); |
| 667 RECURSE(Visit(expr->right())); | 668 RECURSE(Visit(expr->right())); |
| 668 ExitEffects(); | 669 ExitEffects(); |
| 669 left_effects.Alt(right_effects); | 670 left_effects.Alt(right_effects); |
| 670 store_.Seq(left_effects); | 671 store_.Seq(left_effects); |
| 671 | 672 |
| 672 NarrowType(expr, Bounds::Either( | 673 NarrowType(expr, Bounds::Either(bounds_->get(expr->left()), |
| 673 expr->left()->bounds(), expr->right()->bounds(), zone())); | 674 bounds_->get(expr->right()), zone())); |
| 674 break; | 675 break; |
| 675 } | 676 } |
| 676 case Token::BIT_OR: | 677 case Token::BIT_OR: |
| 677 case Token::BIT_AND: { | 678 case Token::BIT_AND: { |
| 678 RECURSE(Visit(expr->left())); | 679 RECURSE(Visit(expr->left())); |
| 679 RECURSE(Visit(expr->right())); | 680 RECURSE(Visit(expr->right())); |
| 680 Type* upper = Type::Union( | 681 Type* upper = Type::Union(bounds_->get(expr->left()).upper, |
| 681 expr->left()->bounds().upper, expr->right()->bounds().upper, zone()); | 682 bounds_->get(expr->right()).upper, zone()); |
| 682 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(); | 683 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(); |
| 683 Type* lower = Type::Intersect(Type::SignedSmall(), upper, zone()); | 684 Type* lower = Type::Intersect(Type::SignedSmall(), upper, zone()); |
| 684 NarrowType(expr, Bounds(lower, upper)); | 685 NarrowType(expr, Bounds(lower, upper)); |
| 685 break; | 686 break; |
| 686 } | 687 } |
| 687 case Token::BIT_XOR: | 688 case Token::BIT_XOR: |
| 688 case Token::SHL: | 689 case Token::SHL: |
| 689 case Token::SAR: | 690 case Token::SAR: |
| 690 RECURSE(Visit(expr->left())); | 691 RECURSE(Visit(expr->left())); |
| 691 RECURSE(Visit(expr->right())); | 692 RECURSE(Visit(expr->right())); |
| 692 NarrowType(expr, Bounds(Type::SignedSmall(), Type::Signed32())); | 693 NarrowType(expr, Bounds(Type::SignedSmall(), Type::Signed32())); |
| 693 break; | 694 break; |
| 694 case Token::SHR: | 695 case Token::SHR: |
| 695 RECURSE(Visit(expr->left())); | 696 RECURSE(Visit(expr->left())); |
| 696 RECURSE(Visit(expr->right())); | 697 RECURSE(Visit(expr->right())); |
| 697 // TODO(rossberg): The upper bound would be Unsigned32, but since there | 698 // TODO(rossberg): The upper bound would be Unsigned32, but since there |
| 698 // is no 'positive Smi' type for the lower bound, we use the smallest | 699 // is no 'positive Smi' type for the lower bound, we use the smallest |
| 699 // union of Smi and Unsigned32 as upper bound instead. | 700 // union of Smi and Unsigned32 as upper bound instead. |
| 700 NarrowType(expr, Bounds(Type::SignedSmall(), Type::Number())); | 701 NarrowType(expr, Bounds(Type::SignedSmall(), Type::Number())); |
| 701 break; | 702 break; |
| 702 case Token::ADD: { | 703 case Token::ADD: { |
| 703 RECURSE(Visit(expr->left())); | 704 RECURSE(Visit(expr->left())); |
| 704 RECURSE(Visit(expr->right())); | 705 RECURSE(Visit(expr->right())); |
| 705 Bounds l = expr->left()->bounds(); | 706 Bounds l = bounds_->get(expr->left()); |
| 706 Bounds r = expr->right()->bounds(); | 707 Bounds r = bounds_->get(expr->right()); |
| 707 Type* lower = | 708 Type* lower = |
| 708 !l.lower->IsInhabited() || !r.lower->IsInhabited() | 709 !l.lower->IsInhabited() || !r.lower->IsInhabited() |
| 709 ? Type::None() | 710 ? Type::None() |
| 710 : l.lower->Is(Type::String()) || r.lower->Is(Type::String()) | 711 : l.lower->Is(Type::String()) || r.lower->Is(Type::String()) |
| 711 ? Type::String() | 712 ? Type::String() |
| 712 : l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) | 713 : l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) |
| 713 ? Type::SignedSmall() | 714 ? Type::SignedSmall() |
| 714 : Type::None(); | 715 : Type::None(); |
| 715 Type* upper = | 716 Type* upper = |
| 716 l.upper->Is(Type::String()) || r.upper->Is(Type::String()) | 717 l.upper->Is(Type::String()) || r.upper->Is(Type::String()) |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 void AstTyper::VisitImportDeclaration(ImportDeclaration* declaration) { | 796 void AstTyper::VisitImportDeclaration(ImportDeclaration* declaration) { |
| 796 } | 797 } |
| 797 | 798 |
| 798 | 799 |
| 799 void AstTyper::VisitExportDeclaration(ExportDeclaration* declaration) { | 800 void AstTyper::VisitExportDeclaration(ExportDeclaration* declaration) { |
| 800 } | 801 } |
| 801 | 802 |
| 802 | 803 |
| 803 } // namespace internal | 804 } // namespace internal |
| 804 } // namespace v8 | 805 } // namespace v8 |
| OLD | NEW |