Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(195)

Side by Side Diff: src/hydrogen.cc

Issue 149133004: A64: Synchronize with r17807. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-dehoist.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 phi->Verify(); 600 phi->Verify();
601 } 601 }
602 602
603 // Check that all join blocks have predecessors that end with an 603 // Check that all join blocks have predecessors that end with an
604 // unconditional goto and agree on their environment node id. 604 // unconditional goto and agree on their environment node id.
605 if (block->predecessors()->length() >= 2) { 605 if (block->predecessors()->length() >= 2) {
606 BailoutId id = 606 BailoutId id =
607 block->predecessors()->first()->last_environment()->ast_id(); 607 block->predecessors()->first()->last_environment()->ast_id();
608 for (int k = 0; k < block->predecessors()->length(); k++) { 608 for (int k = 0; k < block->predecessors()->length(); k++) {
609 HBasicBlock* predecessor = block->predecessors()->at(k); 609 HBasicBlock* predecessor = block->predecessors()->at(k);
610 ASSERT(predecessor->end()->IsGoto()); 610 ASSERT(predecessor->end()->IsGoto() ||
611 predecessor->end()->IsDeoptimize());
611 ASSERT(predecessor->last_environment()->ast_id() == id); 612 ASSERT(predecessor->last_environment()->ast_id() == id);
612 } 613 }
613 } 614 }
614 } 615 }
615 616
616 // Check special property of first block to have no predecessors. 617 // Check special property of first block to have no predecessors.
617 ASSERT(blocks_.at(0)->predecessors()->is_empty()); 618 ASSERT(blocks_.at(0)->predecessors()->is_empty());
618 619
619 if (do_full_verify) { 620 if (do_full_verify) {
620 // Check that the graph is fully connected. 621 // Check that the graph is fully connected.
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 if (IsConstantFalse(constant)) return true; 741 if (IsConstantFalse(constant)) return true;
741 if (IsConstantHole(constant)) return true; 742 if (IsConstantHole(constant)) return true;
742 if (IsConstantNull(constant)) return true; 743 if (IsConstantNull(constant)) return true;
743 return false; 744 return false;
744 } 745 }
745 746
746 747
747 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder) 748 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
748 : builder_(builder), 749 : builder_(builder),
749 finished_(false), 750 finished_(false),
750 deopt_then_(false),
751 deopt_else_(false),
752 did_then_(false), 751 did_then_(false),
753 did_else_(false), 752 did_else_(false),
753 did_else_if_(false),
754 did_and_(false), 754 did_and_(false),
755 did_or_(false), 755 did_or_(false),
756 captured_(false), 756 captured_(false),
757 needs_compare_(true), 757 needs_compare_(true),
758 pending_merge_block_(false),
758 split_edge_merge_block_(NULL), 759 split_edge_merge_block_(NULL),
759 merge_block_(NULL) { 760 merge_at_join_blocks_(NULL),
761 normal_merge_at_join_block_count_(0),
762 deopt_merge_at_join_block_count_(0) {
760 HEnvironment* env = builder->environment(); 763 HEnvironment* env = builder->environment();
761 first_true_block_ = builder->CreateBasicBlock(env->Copy()); 764 first_true_block_ = builder->CreateBasicBlock(env->Copy());
762 last_true_block_ = NULL;
763 first_false_block_ = builder->CreateBasicBlock(env->Copy()); 765 first_false_block_ = builder->CreateBasicBlock(env->Copy());
764 } 766 }
765 767
766 768
767 HGraphBuilder::IfBuilder::IfBuilder( 769 HGraphBuilder::IfBuilder::IfBuilder(
768 HGraphBuilder* builder, 770 HGraphBuilder* builder,
769 HIfContinuation* continuation) 771 HIfContinuation* continuation)
770 : builder_(builder), 772 : builder_(builder),
771 finished_(false), 773 finished_(false),
772 deopt_then_(false),
773 deopt_else_(false),
774 did_then_(false), 774 did_then_(false),
775 did_else_(false), 775 did_else_(false),
776 did_else_if_(false),
776 did_and_(false), 777 did_and_(false),
777 did_or_(false), 778 did_or_(false),
778 captured_(false), 779 captured_(false),
779 needs_compare_(false), 780 needs_compare_(false),
781 pending_merge_block_(false),
780 first_true_block_(NULL), 782 first_true_block_(NULL),
781 last_true_block_(NULL),
782 first_false_block_(NULL), 783 first_false_block_(NULL),
783 split_edge_merge_block_(NULL), 784 split_edge_merge_block_(NULL),
784 merge_block_(NULL) { 785 merge_at_join_blocks_(NULL),
786 normal_merge_at_join_block_count_(0),
787 deopt_merge_at_join_block_count_(0) {
785 continuation->Continue(&first_true_block_, 788 continuation->Continue(&first_true_block_,
786 &first_false_block_); 789 &first_false_block_);
787 } 790 }
788 791
789 792
790 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare( 793 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
791 HControlInstruction* compare) { 794 HControlInstruction* compare) {
795 ASSERT(did_then_ == did_else_);
796 if (did_else_) {
797 // Handle if-then-elseif
798 did_else_if_ = true;
799 did_else_ = false;
800 did_then_ = false;
801 did_and_ = false;
802 did_or_ = false;
803 pending_merge_block_ = false;
804 split_edge_merge_block_ = NULL;
805 HEnvironment* env = builder_->environment();
806 first_true_block_ = builder_->CreateBasicBlock(env->Copy());
807 first_false_block_ = builder_->CreateBasicBlock(env->Copy());
808 }
792 if (split_edge_merge_block_ != NULL) { 809 if (split_edge_merge_block_ != NULL) {
793 HEnvironment* env = first_false_block_->last_environment(); 810 HEnvironment* env = first_false_block_->last_environment();
794 HBasicBlock* split_edge = 811 HBasicBlock* split_edge =
795 builder_->CreateBasicBlock(env->Copy()); 812 builder_->CreateBasicBlock(env->Copy());
796 if (did_or_) { 813 if (did_or_) {
797 compare->SetSuccessorAt(0, split_edge); 814 compare->SetSuccessorAt(0, split_edge);
798 compare->SetSuccessorAt(1, first_false_block_); 815 compare->SetSuccessorAt(1, first_false_block_);
799 } else { 816 } else {
800 compare->SetSuccessorAt(0, first_true_block_); 817 compare->SetSuccessorAt(0, first_true_block_);
801 compare->SetSuccessorAt(1, split_edge); 818 compare->SetSuccessorAt(1, split_edge);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 builder_->GotoNoSimulate(first_false_block_, split_edge_merge_block_); 854 builder_->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
838 first_false_block_ = split_edge_merge_block_; 855 first_false_block_ = split_edge_merge_block_;
839 } 856 }
840 builder_->set_current_block(first_true_block_); 857 builder_->set_current_block(first_true_block_);
841 first_true_block_ = builder_->CreateBasicBlock(env->Copy()); 858 first_true_block_ = builder_->CreateBasicBlock(env->Copy());
842 } 859 }
843 860
844 861
845 void HGraphBuilder::IfBuilder::CaptureContinuation( 862 void HGraphBuilder::IfBuilder::CaptureContinuation(
846 HIfContinuation* continuation) { 863 HIfContinuation* continuation) {
864 ASSERT(!did_else_if_);
847 ASSERT(!finished_); 865 ASSERT(!finished_);
848 ASSERT(!captured_); 866 ASSERT(!captured_);
849 HBasicBlock* true_block = last_true_block_ == NULL 867
850 ? first_true_block_ 868 HBasicBlock* true_block = NULL;
851 : last_true_block_; 869 HBasicBlock* false_block = NULL;
852 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) 870 Finish(&true_block, &false_block);
853 ? builder_->current_block() 871 ASSERT(true_block != NULL);
854 : first_false_block_; 872 ASSERT(false_block != NULL);
855 continuation->Capture(true_block, false_block); 873 continuation->Capture(true_block, false_block);
856 captured_ = true; 874 captured_ = true;
875 builder_->set_current_block(NULL);
857 End(); 876 End();
858 } 877 }
859 878
860 879
861 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { 880 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
881 ASSERT(!did_else_if_);
862 ASSERT(!finished_); 882 ASSERT(!finished_);
863 ASSERT(!captured_); 883 ASSERT(!captured_);
864 ASSERT(did_then_); 884 HBasicBlock* true_block = NULL;
865 if (!did_else_) Else(); 885 HBasicBlock* false_block = NULL;
866 HBasicBlock* true_block = last_true_block_ == NULL 886 Finish(&true_block, &false_block);
867 ? first_true_block_ 887 merge_at_join_blocks_ = NULL;
868 : last_true_block_;
869 HBasicBlock* false_block = builder_->current_block();
870 if (true_block != NULL && !true_block->IsFinished()) { 888 if (true_block != NULL && !true_block->IsFinished()) {
871 ASSERT(continuation->IsTrueReachable()); 889 ASSERT(continuation->IsTrueReachable());
872 builder_->GotoNoSimulate(true_block, continuation->true_branch()); 890 builder_->GotoNoSimulate(true_block, continuation->true_branch());
873 } 891 }
874 if (false_block != NULL && !false_block->IsFinished()) { 892 if (false_block != NULL && !false_block->IsFinished()) {
875 ASSERT(continuation->IsFalseReachable()); 893 ASSERT(continuation->IsFalseReachable());
876 builder_->GotoNoSimulate(false_block, continuation->false_branch()); 894 builder_->GotoNoSimulate(false_block, continuation->false_branch());
877 } 895 }
878 captured_ = true; 896 captured_ = true;
879 End(); 897 End();
(...skipping 10 matching lines...) Expand all
890 // so that the graph builder visits it and sees any live range extending 908 // so that the graph builder visits it and sees any live range extending
891 // constructs within it. 909 // constructs within it.
892 HConstant* constant_false = builder_->graph()->GetConstantFalse(); 910 HConstant* constant_false = builder_->graph()->GetConstantFalse();
893 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); 911 ToBooleanStub::Types boolean_type = ToBooleanStub::Types();
894 boolean_type.Add(ToBooleanStub::BOOLEAN); 912 boolean_type.Add(ToBooleanStub::BOOLEAN);
895 HBranch* branch = builder()->New<HBranch>( 913 HBranch* branch = builder()->New<HBranch>(
896 constant_false, boolean_type, first_true_block_, first_false_block_); 914 constant_false, boolean_type, first_true_block_, first_false_block_);
897 builder_->FinishCurrentBlock(branch); 915 builder_->FinishCurrentBlock(branch);
898 } 916 }
899 builder_->set_current_block(first_true_block_); 917 builder_->set_current_block(first_true_block_);
918 pending_merge_block_ = true;
900 } 919 }
901 920
902 921
903 void HGraphBuilder::IfBuilder::Else() { 922 void HGraphBuilder::IfBuilder::Else() {
904 ASSERT(did_then_); 923 ASSERT(did_then_);
905 ASSERT(!captured_); 924 ASSERT(!captured_);
906 ASSERT(!finished_); 925 ASSERT(!finished_);
907 last_true_block_ = builder_->current_block(); 926 AddMergeAtJoinBlock(false);
908 builder_->set_current_block(first_false_block_); 927 builder_->set_current_block(first_false_block_);
928 pending_merge_block_ = true;
909 did_else_ = true; 929 did_else_ = true;
910 } 930 }
911 931
912 932
913 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { 933 void HGraphBuilder::IfBuilder::Deopt(const char* reason) {
914 ASSERT(did_then_); 934 ASSERT(did_then_);
915 if (did_else_) {
916 deopt_else_ = true;
917 } else {
918 deopt_then_ = true;
919 }
920 builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER); 935 builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
936 AddMergeAtJoinBlock(true);
921 } 937 }
922 938
923 939
924 void HGraphBuilder::IfBuilder::Return(HValue* value) { 940 void HGraphBuilder::IfBuilder::Return(HValue* value) {
925 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); 941 HValue* parameter_count = builder_->graph()->GetConstantMinus1();
926 builder_->FinishExitCurrentBlock( 942 builder_->FinishExitCurrentBlock(
927 builder_->New<HReturn>(value, parameter_count)); 943 builder_->New<HReturn>(value, parameter_count));
928 if (did_else_) { 944 AddMergeAtJoinBlock(false);
929 first_false_block_ = NULL;
930 } else {
931 first_true_block_ = NULL;
932 }
933 } 945 }
934 946
935 947
936 void HGraphBuilder::IfBuilder::End() { 948 void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(bool deopt) {
937 if (!captured_) { 949 if (!pending_merge_block_) return;
938 ASSERT(did_then_); 950 HBasicBlock* block = builder_->current_block();
939 if (!did_else_) { 951 ASSERT(block == NULL || !block->IsFinished());
940 last_true_block_ = builder_->current_block(); 952 MergeAtJoinBlock* record =
953 new(builder_->zone()) MergeAtJoinBlock(block, deopt,
954 merge_at_join_blocks_);
955 merge_at_join_blocks_ = record;
956 if (block != NULL) {
957 ASSERT(block->end() == NULL);
958 if (deopt) {
959 normal_merge_at_join_block_count_++;
960 } else {
961 deopt_merge_at_join_block_count_++;
941 } 962 }
942 if (last_true_block_ == NULL || last_true_block_->IsFinished()) { 963 }
943 ASSERT(did_else_); 964 builder_->set_current_block(NULL);
944 // Return on true. Nothing to do, just continue the false block. 965 pending_merge_block_ = false;
945 } else if (first_false_block_ == NULL || 966 }
946 (did_else_ && builder_->current_block()->IsFinished())) { 967
947 // Deopt on false. Nothing to do except switching to the true block. 968
948 builder_->set_current_block(last_true_block_); 969 void HGraphBuilder::IfBuilder::Finish() {
949 } else { 970 ASSERT(!finished_);
950 merge_block_ = builder_->graph()->CreateBasicBlock(); 971 if (!did_then_) {
951 ASSERT(!finished_); 972 Then();
952 if (!did_else_) Else(); 973 }
953 ASSERT(!last_true_block_->IsFinished()); 974 AddMergeAtJoinBlock(false);
954 HBasicBlock* last_false_block = builder_->current_block(); 975 if (!did_else_) {
955 ASSERT(!last_false_block->IsFinished()); 976 Else();
956 if (deopt_then_) { 977 AddMergeAtJoinBlock(false);
957 builder_->GotoNoSimulate(last_false_block, merge_block_);
958 builder_->PadEnvironmentForContinuation(last_true_block_,
959 merge_block_);
960 builder_->GotoNoSimulate(last_true_block_, merge_block_);
961 } else {
962 builder_->GotoNoSimulate(last_true_block_, merge_block_);
963 if (deopt_else_) {
964 builder_->PadEnvironmentForContinuation(last_false_block,
965 merge_block_);
966 }
967 builder_->GotoNoSimulate(last_false_block, merge_block_);
968 }
969 builder_->set_current_block(merge_block_);
970 }
971 } 978 }
972 finished_ = true; 979 finished_ = true;
973 } 980 }
974 981
975 982
983 void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation,
984 HBasicBlock** else_continuation) {
985 Finish();
986
987 MergeAtJoinBlock* else_record = merge_at_join_blocks_;
988 if (else_continuation != NULL) {
989 *else_continuation = else_record->block_;
990 }
991 MergeAtJoinBlock* then_record = else_record->next_;
992 if (then_continuation != NULL) {
993 *then_continuation = then_record->block_;
994 }
995 ASSERT(then_record->next_ == NULL);
996 }
997
998
999 void HGraphBuilder::IfBuilder::End() {
1000 if (captured_) return;
1001 Finish();
1002
1003 int total_merged_blocks = normal_merge_at_join_block_count_ +
1004 deopt_merge_at_join_block_count_;
1005 ASSERT(total_merged_blocks >= 1);
1006 HBasicBlock* merge_block = total_merged_blocks == 1
1007 ? NULL : builder_->graph()->CreateBasicBlock();
1008
1009 // Merge non-deopt blocks first to ensure environment has right size for
1010 // padding.
1011 MergeAtJoinBlock* current = merge_at_join_blocks_;
1012 while (current != NULL) {
1013 if (!current->deopt_ && current->block_ != NULL) {
1014 // If there is only one block that makes it through to the end of the
1015 // if, then just set it as the current block and continue rather then
1016 // creating an unnecessary merge block.
1017 if (total_merged_blocks == 1) {
1018 builder_->set_current_block(current->block_);
1019 return;
1020 }
1021 builder_->GotoNoSimulate(current->block_, merge_block);
1022 }
1023 current = current->next_;
1024 }
1025
1026 // Merge deopt blocks, padding when necessary.
1027 current = merge_at_join_blocks_;
1028 while (current != NULL) {
1029 if (current->deopt_ && current->block_ != NULL) {
1030 builder_->PadEnvironmentForContinuation(current->block_,
1031 merge_block);
1032 builder_->GotoNoSimulate(current->block_, merge_block);
1033 }
1034 current = current->next_;
1035 }
1036 builder_->set_current_block(merge_block);
1037 }
1038
1039
976 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, 1040 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder,
977 HValue* context, 1041 HValue* context,
978 LoopBuilder::Direction direction) 1042 LoopBuilder::Direction direction)
979 : builder_(builder), 1043 : builder_(builder),
980 context_(context), 1044 context_(context),
981 direction_(direction), 1045 direction_(direction),
982 finished_(false) { 1046 finished_(false) {
983 header_block_ = builder->CreateLoopHeaderBlock(); 1047 header_block_ = builder->CreateLoopHeaderBlock();
984 body_block_ = NULL; 1048 body_block_ = NULL;
985 exit_block_ = NULL; 1049 exit_block_ = NULL;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1046 1110
1047 void HGraphBuilder::LoopBuilder::Break() { 1111 void HGraphBuilder::LoopBuilder::Break() {
1048 if (exit_trampoline_block_ == NULL) { 1112 if (exit_trampoline_block_ == NULL) {
1049 // Its the first time we saw a break. 1113 // Its the first time we saw a break.
1050 HEnvironment* env = exit_block_->last_environment()->Copy(); 1114 HEnvironment* env = exit_block_->last_environment()->Copy();
1051 exit_trampoline_block_ = builder_->CreateBasicBlock(env); 1115 exit_trampoline_block_ = builder_->CreateBasicBlock(env);
1052 builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_); 1116 builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
1053 } 1117 }
1054 1118
1055 builder_->GotoNoSimulate(exit_trampoline_block_); 1119 builder_->GotoNoSimulate(exit_trampoline_block_);
1120 builder_->set_current_block(NULL);
1056 } 1121 }
1057 1122
1058 1123
1059 void HGraphBuilder::LoopBuilder::EndBody() { 1124 void HGraphBuilder::LoopBuilder::EndBody() {
1060 ASSERT(!finished_); 1125 ASSERT(!finished_);
1061 1126
1062 if (direction_ == kPostIncrement || direction_ == kPostDecrement) { 1127 if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
1063 if (direction_ == kPostIncrement) { 1128 if (direction_ == kPostIncrement) {
1064 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_); 1129 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_);
1065 } else { 1130 } else {
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
1335 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, 1400 BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
1336 array_length, elements_length); 1401 array_length, elements_length);
1337 1402
1338 if_builder.End(); 1403 if_builder.End();
1339 } 1404 }
1340 1405
1341 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); 1406 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
1342 } 1407 }
1343 1408
1344 1409
1410 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoadHelper(
1411 HValue* elements,
1412 HValue* key,
1413 HValue* hash,
1414 HValue* mask,
1415 int current_probe) {
1416 if (current_probe == kNumberDictionaryProbes) {
1417 return NULL;
1418 }
1419
1420 int32_t offset = SeededNumberDictionary::GetProbeOffset(current_probe);
1421 HValue* raw_index = (current_probe == 0)
1422 ? hash
1423 : Add<HAdd>(hash, Add<HConstant>(offset));
1424 raw_index = Add<HBitwise>(Token::BIT_AND, raw_index, mask);
1425 int32_t entry_size = SeededNumberDictionary::kEntrySize;
1426 raw_index = Add<HMul>(raw_index, Add<HConstant>(entry_size));
1427 raw_index->ClearFlag(HValue::kCanOverflow);
1428
1429 int32_t base_offset = SeededNumberDictionary::kElementsStartIndex;
1430 HValue* key_index = Add<HAdd>(raw_index, Add<HConstant>(base_offset));
1431 key_index->ClearFlag(HValue::kCanOverflow);
1432
1433 HValue* candidate_key = Add<HLoadKeyed>(elements, key_index,
1434 static_cast<HValue*>(NULL),
1435 FAST_SMI_ELEMENTS);
1436
1437 IfBuilder key_compare(this);
1438 key_compare.IfNot<HCompareObjectEqAndBranch>(key, candidate_key);
1439 key_compare.Then();
1440 {
1441 // Key at the current probe doesn't match, try at the next probe.
1442 HValue* result = BuildUncheckedDictionaryElementLoadHelper(
1443 elements, key, hash, mask, current_probe + 1);
1444 if (result == NULL) {
1445 key_compare.Deopt("probes exhausted in keyed load dictionary lookup");
1446 result = graph()->GetConstantUndefined();
1447 } else {
1448 Push(result);
1449 }
1450 }
1451 key_compare.Else();
1452 {
1453 // Key at current probe matches. Details must be zero, otherwise the
1454 // dictionary element requires special handling.
1455 HValue* details_index = Add<HAdd>(raw_index,
1456 Add<HConstant>(base_offset + 2));
1457 details_index->ClearFlag(HValue::kCanOverflow);
1458
1459 HValue* details = Add<HLoadKeyed>(elements, details_index,
1460 static_cast<HValue*>(NULL),
1461 FAST_SMI_ELEMENTS);
1462 IfBuilder details_compare(this);
1463 details_compare.If<HCompareNumericAndBranch>(details,
1464 graph()->GetConstant0(),
1465 Token::NE);
1466 details_compare.ThenDeopt("keyed load dictionary element not fast case");
1467
1468 details_compare.Else();
1469 {
1470 // Key matches and details are zero --> fast case. Load and return the
1471 // value.
1472 HValue* result_index = Add<HAdd>(raw_index,
1473 Add<HConstant>(base_offset + 1));
1474 result_index->ClearFlag(HValue::kCanOverflow);
1475
1476 Push(Add<HLoadKeyed>(elements, result_index,
1477 static_cast<HValue*>(NULL),
1478 FAST_ELEMENTS));
1479 }
1480 details_compare.End();
1481 }
1482 key_compare.End();
1483
1484 return Pop();
1485 }
1486
1487
1488 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) {
1489 int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed());
1490 HValue* seed = Add<HConstant>(seed_value);
1491 HValue* hash = Add<HBitwise>(Token::BIT_XOR, index, seed);
1492
1493 // hash = ~hash + (hash << 15);
1494 HValue* shifted_hash = Add<HShl>(hash, Add<HConstant>(15));
1495 HValue* not_hash = Add<HBitwise>(Token::BIT_XOR, hash,
1496 graph()->GetConstantMinus1());
1497 hash = Add<HAdd>(shifted_hash, not_hash);
1498
1499 // hash = hash ^ (hash >> 12);
1500 shifted_hash = Add<HShr>(hash, Add<HConstant>(12));
1501 hash = Add<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1502
1503 // hash = hash + (hash << 2);
1504 shifted_hash = Add<HShl>(hash, Add<HConstant>(2));
1505 hash = Add<HAdd>(hash, shifted_hash);
1506
1507 // hash = hash ^ (hash >> 4);
1508 shifted_hash = Add<HShr>(hash, Add<HConstant>(4));
1509 hash = Add<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1510
1511 // hash = hash * 2057;
1512 hash = Add<HMul>(hash, Add<HConstant>(2057));
1513 hash->ClearFlag(HValue::kCanOverflow);
1514
1515 // hash = hash ^ (hash >> 16);
1516 shifted_hash = Add<HShr>(hash, Add<HConstant>(16));
1517 return Add<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1518 }
1519
1520
1521 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
1522 HValue* key) {
1523 HValue* elements = AddLoadElements(receiver);
1524
1525 HValue* hash = BuildElementIndexHash(key);
1526
1527 HValue* capacity = Add<HLoadKeyed>(
1528 elements,
1529 Add<HConstant>(NameDictionary::kCapacityIndex),
1530 static_cast<HValue*>(NULL),
1531 FAST_SMI_ELEMENTS);
1532
1533 HValue* mask = Add<HSub>(capacity, graph()->GetConstant1());
1534 mask->ChangeRepresentation(Representation::Integer32());
1535 mask->ClearFlag(HValue::kCanOverflow);
1536
1537 return BuildUncheckedDictionaryElementLoadHelper(elements, key,
1538 hash, mask, 0);
1539 }
1540
1541
1345 HValue* HGraphBuilder::BuildNumberToString(HValue* object, 1542 HValue* HGraphBuilder::BuildNumberToString(HValue* object,
1346 Handle<Type> type) { 1543 Handle<Type> type) {
1347 NoObservableSideEffectsScope scope(this); 1544 NoObservableSideEffectsScope scope(this);
1348 1545
1349 // Create a joinable continuation. 1546 // Create a joinable continuation.
1350 HIfContinuation found(graph()->CreateBasicBlock(), 1547 HIfContinuation found(graph()->CreateBasicBlock(),
1351 graph()->CreateBasicBlock()); 1548 graph()->CreateBasicBlock());
1352 1549
1353 // Load the number string cache. 1550 // Load the number string cache.
1354 HValue* number_string_cache = 1551 HValue* number_string_cache =
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after
1854 IfBuilder length_checker(this); 2051 IfBuilder length_checker(this);
1855 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); 2052 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
1856 length_checker.Then(); 2053 length_checker.Then();
1857 IfBuilder negative_checker(this); 2054 IfBuilder negative_checker(this);
1858 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( 2055 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
1859 key, graph()->GetConstant0(), Token::GTE); 2056 key, graph()->GetConstant0(), Token::GTE);
1860 negative_checker.Then(); 2057 negative_checker.Then();
1861 HInstruction* result = AddElementAccess( 2058 HInstruction* result = AddElementAccess(
1862 external_elements, key, val, bounds_check, elements_kind, is_store); 2059 external_elements, key, val, bounds_check, elements_kind, is_store);
1863 negative_checker.ElseDeopt("Negative key encountered"); 2060 negative_checker.ElseDeopt("Negative key encountered");
2061 negative_checker.End();
1864 length_checker.End(); 2062 length_checker.End();
1865 return result; 2063 return result;
1866 } else { 2064 } else {
1867 ASSERT(store_mode == STANDARD_STORE); 2065 ASSERT(store_mode == STANDARD_STORE);
1868 checked_key = Add<HBoundsCheck>(key, length); 2066 checked_key = Add<HBoundsCheck>(key, length);
1869 HLoadExternalArrayPointer* external_elements = 2067 HLoadExternalArrayPointer* external_elements =
1870 Add<HLoadExternalArrayPointer>(elements); 2068 Add<HLoadExternalArrayPointer>(elements);
1871 return AddElementAccess( 2069 return AddElementAccess(
1872 external_elements, checked_key, val, 2070 external_elements, checked_key, val,
1873 checked_object, elements_kind, is_store); 2071 checked_object, elements_kind, is_store);
(...skipping 30 matching lines...) Expand all
1904 elements, isolate()->factory()->fixed_array_map(), top_info()); 2102 elements, isolate()->factory()->fixed_array_map(), top_info());
1905 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 2103 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1906 } 2104 }
1907 } 2105 }
1908 } 2106 }
1909 return AddElementAccess(elements, checked_key, val, checked_object, 2107 return AddElementAccess(elements, checked_key, val, checked_object,
1910 elements_kind, is_store, load_mode); 2108 elements_kind, is_store, load_mode);
1911 } 2109 }
1912 2110
1913 2111
2112
2113 HValue* HGraphBuilder::BuildAllocateArrayFromLength(
2114 JSArrayBuilder* array_builder,
2115 HValue* length_argument) {
2116 if (length_argument->IsConstant() &&
2117 HConstant::cast(length_argument)->HasSmiValue()) {
2118 int array_length = HConstant::cast(length_argument)->Integer32Value();
2119 HValue* new_object = array_length == 0
2120 ? array_builder->AllocateEmptyArray()
2121 : array_builder->AllocateArray(length_argument, length_argument);
2122 return new_object;
2123 }
2124
2125 HValue* constant_zero = graph()->GetConstant0();
2126 HConstant* max_alloc_length =
2127 Add<HConstant>(JSObject::kInitialMaxFastElementArray);
2128 HInstruction* checked_length = Add<HBoundsCheck>(length_argument,
2129 max_alloc_length);
2130 IfBuilder if_builder(this);
2131 if_builder.If<HCompareNumericAndBranch>(checked_length, constant_zero,
2132 Token::EQ);
2133 if_builder.Then();
2134 const int initial_capacity = JSArray::kPreallocatedArrayElements;
2135 HConstant* initial_capacity_node = Add<HConstant>(initial_capacity);
2136 Push(initial_capacity_node); // capacity
2137 Push(constant_zero); // length
2138 if_builder.Else();
2139 if (!(top_info()->IsStub()) &&
2140 IsFastPackedElementsKind(array_builder->kind())) {
2141 // We'll come back later with better (holey) feedback.
2142 if_builder.Deopt("Holey array despite packed elements_kind feedback");
2143 } else {
2144 Push(checked_length); // capacity
2145 Push(checked_length); // length
2146 }
2147 if_builder.End();
2148
2149 // Figure out total size
2150 HValue* length = Pop();
2151 HValue* capacity = Pop();
2152 return array_builder->AllocateArray(capacity, length);
2153 }
2154
1914 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, 2155 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
1915 HValue* capacity) { 2156 HValue* capacity) {
1916 int elements_size; 2157 int elements_size;
1917 InstanceType instance_type; 2158 InstanceType instance_type;
1918 2159
1919 if (IsFastDoubleElementsKind(kind)) { 2160 if (IsFastDoubleElementsKind(kind)) {
1920 elements_size = kDoubleSize; 2161 elements_size = kDoubleSize;
1921 instance_type = FIXED_DOUBLE_ARRAY_TYPE; 2162 instance_type = FIXED_DOUBLE_ARRAY_TYPE;
1922 } else { 2163 } else {
1923 elements_size = kPointerSize; 2164 elements_size = kPointerSize;
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
2092 // Fast elements kinds need to be initialized in case statements below cause 2333 // Fast elements kinds need to be initialized in case statements below cause
2093 // a garbage collection. 2334 // a garbage collection.
2094 Factory* factory = isolate()->factory(); 2335 Factory* factory = isolate()->factory();
2095 2336
2096 double nan_double = FixedDoubleArray::hole_nan_as_double(); 2337 double nan_double = FixedDoubleArray::hole_nan_as_double();
2097 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) 2338 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
2098 ? Add<HConstant>(factory->the_hole_value()) 2339 ? Add<HConstant>(factory->the_hole_value())
2099 : Add<HConstant>(nan_double); 2340 : Add<HConstant>(nan_double);
2100 2341
2101 // Special loop unfolding case 2342 // Special loop unfolding case
2102 static const int kLoopUnfoldLimit = 4; 2343 static const int kLoopUnfoldLimit = 8;
2103 bool unfold_loop = false; 2344 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit);
2104 int initial_capacity = JSArray::kPreallocatedArrayElements; 2345 int initial_capacity = -1;
2105 if (from->IsConstant() && to->IsConstant() && 2346 if (from->IsInteger32Constant() && to->IsInteger32Constant()) {
2106 initial_capacity <= kLoopUnfoldLimit) { 2347 int constant_from = from->GetInteger32Constant();
2107 HConstant* constant_from = HConstant::cast(from); 2348 int constant_to = to->GetInteger32Constant();
2108 HConstant* constant_to = HConstant::cast(to);
2109 2349
2110 if (constant_from->HasInteger32Value() && 2350 if (constant_from == 0 && constant_to <= kLoopUnfoldLimit) {
2111 constant_from->Integer32Value() == 0 && 2351 initial_capacity = constant_to;
2112 constant_to->HasInteger32Value() &&
2113 constant_to->Integer32Value() == initial_capacity) {
2114 unfold_loop = true;
2115 } 2352 }
2116 } 2353 }
2117 2354
2118 // Since we're about to store a hole value, the store instruction below must 2355 // Since we're about to store a hole value, the store instruction below must
2119 // assume an elements kind that supports heap object values. 2356 // assume an elements kind that supports heap object values.
2120 if (IsFastSmiOrObjectElementsKind(elements_kind)) { 2357 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
2121 elements_kind = FAST_HOLEY_ELEMENTS; 2358 elements_kind = FAST_HOLEY_ELEMENTS;
2122 } 2359 }
2123 2360
2124 if (unfold_loop) { 2361 if (initial_capacity >= 0) {
2125 for (int i = 0; i < initial_capacity; i++) { 2362 for (int i = 0; i < initial_capacity; i++) {
2126 HInstruction* key = Add<HConstant>(i); 2363 HInstruction* key = Add<HConstant>(i);
2127 Add<HStoreKeyed>(elements, key, hole, elements_kind); 2364 Add<HStoreKeyed>(elements, key, hole, elements_kind);
2128 } 2365 }
2129 } else { 2366 } else {
2130 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); 2367 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
2131 2368
2132 HValue* key = builder.BeginBody(from, to, Token::LT); 2369 HValue* key = builder.BeginBody(from, to, Token::LT);
2133 2370
2134 Add<HStoreKeyed>(elements, key, hole, elements_kind); 2371 Add<HStoreKeyed>(elements, key, hole, elements_kind);
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
2373 HValue* constructor_function) : 2610 HValue* constructor_function) :
2374 builder_(builder), 2611 builder_(builder),
2375 kind_(kind), 2612 kind_(kind),
2376 mode_(DONT_TRACK_ALLOCATION_SITE), 2613 mode_(DONT_TRACK_ALLOCATION_SITE),
2377 allocation_site_payload_(NULL), 2614 allocation_site_payload_(NULL),
2378 constructor_function_(constructor_function) { 2615 constructor_function_(constructor_function) {
2379 } 2616 }
2380 2617
2381 2618
2382 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { 2619 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
2383 if (kind_ == GetInitialFastElementsKind()) { 2620 if (!builder()->top_info()->IsStub()) {
2621 // A constant map is fine.
2622 Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_),
2623 builder()->isolate());
2624 return builder()->Add<HConstant>(map);
2625 }
2626
2627 if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) {
2384 // No need for a context lookup if the kind_ matches the initial 2628 // No need for a context lookup if the kind_ matches the initial
2385 // map, because we can just load the map in that case. 2629 // map, because we can just load the map in that case.
2386 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 2630 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
2387 return builder()->AddLoadNamedField(constructor_function_, access); 2631 return builder()->AddLoadNamedField(constructor_function_, access);
2388 } 2632 }
2389 2633
2390 HInstruction* native_context = builder()->BuildGetNativeContext(); 2634 HInstruction* native_context = builder()->BuildGetNativeContext();
2391 HInstruction* index = builder()->Add<HConstant>( 2635 HInstruction* index = builder()->Add<HConstant>(
2392 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); 2636 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
2393 2637
(...skipping 21 matching lines...) Expand all
2415 int base_size = JSArray::kSize; 2659 int base_size = JSArray::kSize;
2416 if (mode_ == TRACK_ALLOCATION_SITE) { 2660 if (mode_ == TRACK_ALLOCATION_SITE) {
2417 base_size += AllocationMemento::kSize; 2661 base_size += AllocationMemento::kSize;
2418 } 2662 }
2419 2663
2420 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); 2664 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
2421 base_size += FixedArray::kHeaderSize; 2665 base_size += FixedArray::kHeaderSize;
2422 2666
2423 HInstruction* elements_size_value = 2667 HInstruction* elements_size_value =
2424 builder()->Add<HConstant>(elements_size()); 2668 builder()->Add<HConstant>(elements_size());
2425 HInstruction* mul = builder()->Add<HMul>(length_node, elements_size_value); 2669 HInstruction* mul = HMul::NewImul(builder()->zone(), builder()->context(),
2426 mul->ClearFlag(HValue::kCanOverflow); 2670 length_node, elements_size_value);
2427 2671 builder()->AddInstruction(mul);
2428 HInstruction* base = builder()->Add<HConstant>(base_size); 2672 HInstruction* base = builder()->Add<HConstant>(base_size);
2429 HInstruction* total_size = builder()->Add<HAdd>(base, mul); 2673 HInstruction* total_size = HAdd::New(builder()->zone(), builder()->context(),
2674 base, mul);
2430 total_size->ClearFlag(HValue::kCanOverflow); 2675 total_size->ClearFlag(HValue::kCanOverflow);
2676 builder()->AddInstruction(total_size);
2431 return total_size; 2677 return total_size;
2432 } 2678 }
2433 2679
2434 2680
2435 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { 2681 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() {
2436 int base_size = JSArray::kSize; 2682 int base_size = JSArray::kSize;
2437 if (mode_ == TRACK_ALLOCATION_SITE) { 2683 if (mode_ == TRACK_ALLOCATION_SITE) {
2438 base_size += AllocationMemento::kSize; 2684 base_size += AllocationMemento::kSize;
2439 } 2685 }
2440 2686
2441 base_size += IsFastDoubleElementsKind(kind_) 2687 base_size += IsFastDoubleElementsKind(kind_)
2442 ? FixedDoubleArray::SizeFor(initial_capacity()) 2688 ? FixedDoubleArray::SizeFor(initial_capacity())
2443 : FixedArray::SizeFor(initial_capacity()); 2689 : FixedArray::SizeFor(initial_capacity());
2444 2690
2445 return builder()->Add<HConstant>(base_size); 2691 return builder()->Add<HConstant>(base_size);
2446 } 2692 }
2447 2693
2448 2694
2449 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { 2695 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() {
2450 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); 2696 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize();
2451 HConstant* capacity = builder()->Add<HConstant>(initial_capacity()); 2697 HConstant* capacity = builder()->Add<HConstant>(initial_capacity());
2452 return AllocateArray(size_in_bytes, 2698 return AllocateArray(size_in_bytes,
2453 capacity, 2699 capacity,
2454 builder()->graph()->GetConstant0(), 2700 builder()->graph()->GetConstant0());
2455 true);
2456 } 2701 }
2457 2702
2458 2703
2459 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, 2704 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity,
2460 HValue* length_field, 2705 HValue* length_field,
2461 bool fill_with_hole) { 2706 FillMode fill_mode) {
2462 HValue* size_in_bytes = EstablishAllocationSize(capacity); 2707 HValue* size_in_bytes = EstablishAllocationSize(capacity);
2463 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); 2708 return AllocateArray(size_in_bytes, capacity, length_field, fill_mode);
2464 } 2709 }
2465 2710
2466 2711
2467 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, 2712 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
2468 HValue* capacity, 2713 HValue* capacity,
2469 HValue* length_field, 2714 HValue* length_field,
2470 bool fill_with_hole) { 2715 FillMode fill_mode) {
2471 // These HForceRepresentations are because we store these as fields in the 2716 // These HForceRepresentations are because we store these as fields in the
2472 // objects we construct, and an int32-to-smi HChange could deopt. Accept 2717 // objects we construct, and an int32-to-smi HChange could deopt. Accept
2473 // the deopt possibility now, before allocation occurs. 2718 // the deopt possibility now, before allocation occurs.
2474 capacity = builder()->Add<HForceRepresentation>(capacity, 2719 capacity = builder()->Add<HForceRepresentation>(capacity,
2475 Representation::Smi()); 2720 Representation::Smi());
2476 length_field = builder()->Add<HForceRepresentation>(length_field, 2721 length_field = builder()->Add<HForceRepresentation>(length_field,
2477 Representation::Smi()); 2722 Representation::Smi());
2478 // Allocate (dealing with failure appropriately) 2723 // Allocate (dealing with failure appropriately)
2479 HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes, 2724 HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes,
2480 HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE); 2725 HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE);
(...skipping 13 matching lines...) Expand all
2494 elements_location_ = builder()->BuildJSArrayHeader(new_object, 2739 elements_location_ = builder()->BuildJSArrayHeader(new_object,
2495 map, 2740 map,
2496 mode_, 2741 mode_,
2497 kind_, 2742 kind_,
2498 allocation_site_payload_, 2743 allocation_site_payload_,
2499 length_field); 2744 length_field);
2500 2745
2501 // Initialize the elements 2746 // Initialize the elements
2502 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); 2747 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
2503 2748
2504 if (fill_with_hole) { 2749 if (fill_mode == FILL_WITH_HOLE) {
2505 builder()->BuildFillElementsWithHole(elements_location_, kind_, 2750 builder()->BuildFillElementsWithHole(elements_location_, kind_,
2506 graph()->GetConstant0(), capacity); 2751 graph()->GetConstant0(), capacity);
2507 } 2752 }
2508 2753
2509 return new_object; 2754 return new_object;
2510 } 2755 }
2511 2756
2512 2757
2513 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, 2758 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object,
2514 Handle<Map> map) { 2759 Handle<Map> map) {
(...skipping 4185 matching lines...) Expand 10 before | Expand all | Expand 10 after
6700 6945
6701 6946
6702 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) { 6947 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
6703 if (!FLAG_use_inlining) return kNotInlinable; 6948 if (!FLAG_use_inlining) return kNotInlinable;
6704 6949
6705 // Precondition: call is monomorphic and we have found a target with the 6950 // Precondition: call is monomorphic and we have found a target with the
6706 // appropriate arity. 6951 // appropriate arity.
6707 Handle<JSFunction> caller = current_info()->closure(); 6952 Handle<JSFunction> caller = current_info()->closure();
6708 Handle<SharedFunctionInfo> target_shared(target->shared()); 6953 Handle<SharedFunctionInfo> target_shared(target->shared());
6709 6954
6955 // Always inline builtins marked for inlining.
6956 if (target->IsBuiltin()) {
6957 return target_shared->inline_builtin() ? 0 : kNotInlinable;
6958 }
6959
6710 // Do a quick check on source code length to avoid parsing large 6960 // Do a quick check on source code length to avoid parsing large
6711 // inlining candidates. 6961 // inlining candidates.
6712 if (target_shared->SourceSize() > 6962 if (target_shared->SourceSize() >
6713 Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) { 6963 Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
6714 TraceInline(target, caller, "target text too big"); 6964 TraceInline(target, caller, "target text too big");
6715 return kNotInlinable; 6965 return kNotInlinable;
6716 } 6966 }
6717 6967
6718 // Target must be inlineable. 6968 // Target must be inlineable.
6719 if (!target->IsInlineable()) { 6969 if (!target_shared->IsInlineable()) {
6720 TraceInline(target, caller, "target not inlineable"); 6970 TraceInline(target, caller, "target not inlineable");
6721 return kNotInlinable; 6971 return kNotInlinable;
6722 } 6972 }
6723 if (target_shared->dont_inline() || target_shared->dont_optimize()) { 6973 if (target_shared->dont_inline() || target_shared->dont_optimize()) {
6724 TraceInline(target, caller, "target contains unsupported syntax [early]"); 6974 TraceInline(target, caller, "target contains unsupported syntax [early]");
6725 return kNotInlinable; 6975 return kNotInlinable;
6726 } 6976 }
6727 6977
6728 int nodes_added = target_shared->ast_node_count(); 6978 int nodes_added = target_shared->ast_node_count();
6729 return nodes_added; 6979 return nodes_added;
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
7089 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 7339 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
7090 switch (id) { 7340 switch (id) {
7091 case kMathExp: 7341 case kMathExp:
7092 if (!FLAG_fast_math) break; 7342 if (!FLAG_fast_math) break;
7093 // Fall through if FLAG_fast_math. 7343 // Fall through if FLAG_fast_math.
7094 case kMathRound: 7344 case kMathRound:
7095 case kMathFloor: 7345 case kMathFloor:
7096 case kMathAbs: 7346 case kMathAbs:
7097 case kMathSqrt: 7347 case kMathSqrt:
7098 case kMathLog: 7348 case kMathLog:
7099 case kMathSin:
7100 case kMathCos:
7101 case kMathTan:
7102 if (expr->arguments()->length() == 1) { 7349 if (expr->arguments()->length() == 1) {
7103 HValue* argument = Pop(); 7350 HValue* argument = Pop();
7104 Drop(1); // Receiver. 7351 Drop(1); // Receiver.
7105 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id); 7352 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
7106 if (drop_extra) Drop(1); // Optionally drop the function. 7353 if (drop_extra) Drop(1); // Optionally drop the function.
7107 ast_context()->ReturnInstruction(op, expr->id()); 7354 ast_context()->ReturnInstruction(op, expr->id());
7108 return true; 7355 return true;
7109 } 7356 }
7110 break; 7357 break;
7111 case kMathImul: 7358 case kMathImul:
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
7170 } 7417 }
7171 break; 7418 break;
7172 case kMathExp: 7419 case kMathExp:
7173 if (!FLAG_fast_math) break; 7420 if (!FLAG_fast_math) break;
7174 // Fall through if FLAG_fast_math. 7421 // Fall through if FLAG_fast_math.
7175 case kMathRound: 7422 case kMathRound:
7176 case kMathFloor: 7423 case kMathFloor:
7177 case kMathAbs: 7424 case kMathAbs:
7178 case kMathSqrt: 7425 case kMathSqrt:
7179 case kMathLog: 7426 case kMathLog:
7180 case kMathSin:
7181 case kMathCos:
7182 case kMathTan:
7183 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { 7427 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
7184 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 7428 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7185 HValue* argument = Pop(); 7429 HValue* argument = Pop();
7186 Drop(1); // Receiver. 7430 Drop(1); // Receiver.
7187 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id); 7431 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
7188 ast_context()->ReturnInstruction(op, expr->id()); 7432 ast_context()->ReturnInstruction(op, expr->id());
7189 return true; 7433 return true;
7190 } 7434 }
7191 break; 7435 break;
7192 case kMathPow: 7436 case kMathPow:
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
7351 ASSERT(current_block() != NULL); 7595 ASSERT(current_block() != NULL);
7352 ASSERT(current_block()->HasPredecessor()); 7596 ASSERT(current_block()->HasPredecessor());
7353 Expression* callee = expr->expression(); 7597 Expression* callee = expr->expression();
7354 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 7598 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
7355 HInstruction* call = NULL; 7599 HInstruction* call = NULL;
7356 7600
7357 Property* prop = callee->AsProperty(); 7601 Property* prop = callee->AsProperty();
7358 if (prop != NULL) { 7602 if (prop != NULL) {
7359 if (!prop->key()->IsPropertyName()) { 7603 if (!prop->key()->IsPropertyName()) {
7360 // Keyed function call. 7604 // Keyed function call.
7361 CHECK_ALIVE(VisitArgument(prop->obj())); 7605 CHECK_ALIVE(VisitForValue(prop->obj()));
7606 CHECK_ALIVE(VisitForValue(prop->key()));
7362 7607
7363 CHECK_ALIVE(VisitForValue(prop->key()));
7364 // Push receiver and key like the non-optimized code generator expects it. 7608 // Push receiver and key like the non-optimized code generator expects it.
7365 HValue* key = Pop(); 7609 HValue* key = Pop();
7366 HValue* receiver = Pop(); 7610 HValue* receiver = Pop();
7367 Push(key); 7611 Push(key);
7368 Push(receiver); 7612 Push(Add<HPushArgument>(receiver));
7369
7370 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 7613 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7371 7614
7372 call = New<HCallKeyed>(key, argument_count); 7615 if (expr->IsMonomorphic()) {
7616 BuildCheckHeapObject(receiver);
7617 ElementsKind kind = expr->KeyedArrayCallIsHoley()
7618 ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
7619
7620 Handle<Map> map(isolate()->get_initial_js_array_map(kind));
7621
7622 HValue* function = BuildMonomorphicElementAccess(
7623 receiver, key, NULL, NULL, map, false, STANDARD_STORE);
7624
7625 call = New<HCallFunction>(function, argument_count);
7626 } else {
7627 call = New<HCallKeyed>(key, argument_count);
7628 }
7373 Drop(argument_count + 1); // 1 is the key. 7629 Drop(argument_count + 1); // 1 is the key.
7374 return ast_context()->ReturnInstruction(call, expr->id()); 7630 return ast_context()->ReturnInstruction(call, expr->id());
7375 } 7631 }
7376 7632
7377 // Named function call. 7633 // Named function call.
7378 if (TryCallApply(expr)) return; 7634 if (TryCallApply(expr)) return;
7379 7635
7380 CHECK_ALIVE(VisitForValue(prop->obj())); 7636 CHECK_ALIVE(VisitForValue(prop->obj()));
7381 CHECK_ALIVE(VisitExpressions(expr->arguments())); 7637 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7382 7638
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
7531 7787
7532 call = New<HCallFunction>(function, argument_count); 7788 call = New<HCallFunction>(function, argument_count);
7533 Drop(argument_count + 1); 7789 Drop(argument_count + 1);
7534 } 7790 }
7535 } 7791 }
7536 7792
7537 return ast_context()->ReturnInstruction(call, expr->id()); 7793 return ast_context()->ReturnInstruction(call, expr->id());
7538 } 7794 }
7539 7795
7540 7796
7797 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) {
7798 NoObservableSideEffectsScope no_effects(this);
7799
7800 int argument_count = expr->arguments()->length();
7801 // We should at least have the constructor on the expression stack.
7802 HValue* constructor = environment()->ExpressionStackAt(argument_count);
7803
7804 ElementsKind kind = expr->elements_kind();
7805 Handle<Cell> cell = expr->allocation_info_cell();
7806 AllocationSite* site = AllocationSite::cast(cell->value());
7807
7808 // Register on the site for deoptimization if the cell value changes.
7809 site->AddDependentCompilationInfo(AllocationSite::TRANSITIONS, top_info());
7810 HInstruction* cell_instruction = Add<HConstant>(cell);
7811
7812 // In the single constant argument case, we may have to adjust elements kind
7813 // to avoid creating a packed non-empty array.
7814 if (argument_count == 1 && !IsHoleyElementsKind(kind)) {
7815 HValue* argument = environment()->Top();
7816 if (argument->IsConstant()) {
7817 HConstant* constant_argument = HConstant::cast(argument);
7818 ASSERT(constant_argument->HasSmiValue());
7819 int constant_array_size = constant_argument->Integer32Value();
7820 if (constant_array_size != 0) {
7821 kind = GetHoleyElementsKind(kind);
7822 }
7823 }
7824 }
7825
7826 // Build the array.
7827 JSArrayBuilder array_builder(this,
7828 kind,
7829 cell_instruction,
7830 constructor,
7831 DISABLE_ALLOCATION_SITES);
7832 HValue* new_object;
7833 if (argument_count == 0) {
7834 new_object = array_builder.AllocateEmptyArray();
7835 } else if (argument_count == 1) {
7836 HValue* argument = environment()->Top();
7837 new_object = BuildAllocateArrayFromLength(&array_builder, argument);
7838 } else {
7839 HValue* length = Add<HConstant>(argument_count);
7840 // Smi arrays need to initialize array elements with the hole because
7841 // bailout could occur if the arguments don't fit in a smi.
7842 //
7843 // TODO(mvstanton): If all the arguments are constants in smi range, then
7844 // we could set fill_with_hole to false and save a few instructions.
7845 JSArrayBuilder::FillMode fill_mode = IsFastSmiElementsKind(kind)
7846 ? JSArrayBuilder::FILL_WITH_HOLE
7847 : JSArrayBuilder::DONT_FILL_WITH_HOLE;
7848 new_object = array_builder.AllocateArray(length, length, fill_mode);
7849 HValue* elements = array_builder.GetElementsLocation();
7850 for (int i = 0; i < argument_count; i++) {
7851 HValue* value = environment()->ExpressionStackAt(argument_count - i - 1);
7852 HValue* constant_i = Add<HConstant>(i);
7853 Add<HStoreKeyed>(elements, constant_i, value, kind);
7854 }
7855 }
7856
7857 Drop(argument_count + 1); // drop constructor and args.
7858 ast_context()->ReturnValue(new_object);
7859 }
7860
7861
7541 // Checks whether allocation using the given constructor can be inlined. 7862 // Checks whether allocation using the given constructor can be inlined.
7542 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { 7863 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
7543 return constructor->has_initial_map() && 7864 return constructor->has_initial_map() &&
7544 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && 7865 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
7545 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && 7866 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize &&
7546 constructor->initial_map()->InitialPropertiesLength() == 0; 7867 constructor->initial_map()->InitialPropertiesLength() == 0;
7547 } 7868 }
7548 7869
7549 7870
7871 bool HOptimizedGraphBuilder::IsCallNewArrayInlineable(CallNew* expr) {
7872 bool inline_ok = false;
7873 Handle<JSFunction> caller = current_info()->closure();
7874 Handle<JSFunction> target(isolate()->global_context()->array_function(),
7875 isolate());
7876 int argument_count = expr->arguments()->length();
7877 // We should have the function plus array arguments on the environment stack.
7878 ASSERT(environment()->length() >= (argument_count + 1));
7879 Handle<Cell> cell = expr->allocation_info_cell();
7880 AllocationSite* site = AllocationSite::cast(cell->value());
7881 if (site->CanInlineCall()) {
7882 // We also want to avoid inlining in certain 1 argument scenarios.
7883 if (argument_count == 1) {
7884 HValue* argument = Top();
7885 if (argument->IsConstant()) {
7886 // Do not inline if the constant length argument is not a smi or
7887 // outside the valid range for a fast array.
7888 HConstant* constant_argument = HConstant::cast(argument);
7889 if (constant_argument->HasSmiValue()) {
7890 int value = constant_argument->Integer32Value();
7891 inline_ok = value >= 0 &&
7892 value < JSObject::kInitialMaxFastElementArray;
7893 if (!inline_ok) {
7894 TraceInline(target, caller,
7895 "Length outside of valid array range");
7896 }
7897 }
7898 } else {
7899 inline_ok = true;
7900 }
7901 } else {
7902 inline_ok = true;
7903 }
7904 } else {
7905 TraceInline(target, caller, "AllocationSite requested no inlining.");
7906 }
7907
7908 if (inline_ok) {
7909 TraceInline(target, caller, NULL);
7910 }
7911 return inline_ok;
7912 }
7913
7914
7550 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { 7915 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
7551 ASSERT(!HasStackOverflow()); 7916 ASSERT(!HasStackOverflow());
7552 ASSERT(current_block() != NULL); 7917 ASSERT(current_block() != NULL);
7553 ASSERT(current_block()->HasPredecessor()); 7918 ASSERT(current_block()->HasPredecessor());
7554 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); 7919 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
7555 int argument_count = expr->arguments()->length() + 1; // Plus constructor. 7920 int argument_count = expr->arguments()->length() + 1; // Plus constructor.
7556 Factory* factory = isolate()->factory(); 7921 Factory* factory = isolate()->factory();
7557 7922
7923 // The constructor function is on the stack in the unoptimized code
7924 // during evaluation of the arguments.
7925 CHECK_ALIVE(VisitForValue(expr->expression()));
7926 HValue* function = Top();
7927 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7928
7558 if (FLAG_inline_construct && 7929 if (FLAG_inline_construct &&
7559 expr->IsMonomorphic() && 7930 expr->IsMonomorphic() &&
7560 IsAllocationInlineable(expr->target())) { 7931 IsAllocationInlineable(expr->target())) {
7561 // The constructor function is on the stack in the unoptimized code
7562 // during evaluation of the arguments.
7563 CHECK_ALIVE(VisitForValue(expr->expression()));
7564 HValue* function = Top();
7565 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7566 Handle<JSFunction> constructor = expr->target(); 7932 Handle<JSFunction> constructor = expr->target();
7567 HValue* check = Add<HCheckValue>(function, constructor); 7933 HValue* check = Add<HCheckValue>(function, constructor);
7568 7934
7569 // Force completion of inobject slack tracking before generating 7935 // Force completion of inobject slack tracking before generating
7570 // allocation code to finalize instance size. 7936 // allocation code to finalize instance size.
7571 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { 7937 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) {
7572 constructor->shared()->CompleteInobjectSlackTracking(); 7938 constructor->shared()->CompleteInobjectSlackTracking();
7573 } 7939 }
7574 7940
7575 // Calculate instance size from initial map of constructor. 7941 // Calculate instance size from initial map of constructor.
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
7642 check->DeleteAndReplaceWith(NULL); 8008 check->DeleteAndReplaceWith(NULL);
7643 environment()->SetExpressionStackAt(receiver_index, function); 8009 environment()->SetExpressionStackAt(receiver_index, function);
7644 HInstruction* call = 8010 HInstruction* call =
7645 PreProcessCall(New<HCallNew>(function, argument_count)); 8011 PreProcessCall(New<HCallNew>(function, argument_count));
7646 return ast_context()->ReturnInstruction(call, expr->id()); 8012 return ast_context()->ReturnInstruction(call, expr->id());
7647 } else { 8013 } else {
7648 // The constructor function is both an operand to the instruction and an 8014 // The constructor function is both an operand to the instruction and an
7649 // argument to the construct call. 8015 // argument to the construct call.
7650 Handle<JSFunction> array_function( 8016 Handle<JSFunction> array_function(
7651 isolate()->global_context()->array_function(), isolate()); 8017 isolate()->global_context()->array_function(), isolate());
7652 CHECK_ALIVE(VisitArgument(expr->expression())); 8018 bool use_call_new_array = expr->target().is_identical_to(array_function);
7653 HValue* constructor = HPushArgument::cast(Top())->argument(); 8019 Handle<Cell> cell = expr->allocation_info_cell();
7654 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 8020 if (use_call_new_array && IsCallNewArrayInlineable(expr)) {
8021 // Verify we are still calling the array function for our native context.
8022 Add<HCheckValue>(function, array_function);
8023 BuildInlinedCallNewArray(expr);
8024 return;
8025 }
8026
7655 HBinaryCall* call; 8027 HBinaryCall* call;
7656 if (expr->target().is_identical_to(array_function)) { 8028 if (use_call_new_array) {
7657 Handle<Cell> cell = expr->allocation_info_cell(); 8029 Add<HCheckValue>(function, array_function);
7658 Add<HCheckValue>(constructor, array_function); 8030 call = New<HCallNewArray>(function, argument_count, cell,
7659 call = New<HCallNewArray>(constructor, argument_count, 8031 expr->elements_kind());
7660 cell, expr->elements_kind());
7661 } else { 8032 } else {
7662 call = New<HCallNew>(constructor, argument_count); 8033 call = New<HCallNew>(function, argument_count);
7663 } 8034 }
7664 Drop(argument_count); 8035 PreProcessCall(call);
7665 return ast_context()->ReturnInstruction(call, expr->id()); 8036 return ast_context()->ReturnInstruction(call, expr->id());
7666 } 8037 }
7667 } 8038 }
7668 8039
7669 8040
7670 // Support for generating inlined runtime functions. 8041 // Support for generating inlined runtime functions.
7671 8042
7672 // Lookup table for generators for runtime calls that are generated inline. 8043 // Lookup table for generators for runtime calls that are generated inline.
7673 // Elements of the table are member pointers to functions of 8044 // Elements of the table are member pointers to functions of
7674 // HOptimizedGraphBuilder. 8045 // HOptimizedGraphBuilder.
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after
8191 Deoptimizer::SOFT); 8562 Deoptimizer::SOFT);
8192 right_type = handle(Type::Any(), isolate()); 8563 right_type = handle(Type::Any(), isolate());
8193 } else { 8564 } else {
8194 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); 8565 if (!maybe_string_add) right = TruncateToNumber(right, &right_type);
8195 right_rep = Representation::FromType(right_type); 8566 right_rep = Representation::FromType(right_type);
8196 } 8567 }
8197 8568
8198 // Special case for string addition here. 8569 // Special case for string addition here.
8199 if (op == Token::ADD && 8570 if (op == Token::ADD &&
8200 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { 8571 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
8572 // Validate type feedback for left argument.
8201 if (left_type->Is(Type::String())) { 8573 if (left_type->Is(Type::String())) {
8202 IfBuilder if_isstring(this); 8574 IfBuilder if_isstring(this);
8203 if_isstring.If<HIsStringAndBranch>(left); 8575 if_isstring.If<HIsStringAndBranch>(left);
8204 if_isstring.Then(); 8576 if_isstring.Then();
8205 if_isstring.ElseDeopt("Expected string for LHS of binary operation"); 8577 if_isstring.ElseDeopt("Expected string for LHS of binary operation");
8206 } else if (left_type->Is(Type::Number())) { 8578 }
8579
8580 // Validate type feedback for right argument.
8581 if (right_type->Is(Type::String())) {
8582 IfBuilder if_isstring(this);
8583 if_isstring.If<HIsStringAndBranch>(right);
8584 if_isstring.Then();
8585 if_isstring.ElseDeopt("Expected string for RHS of binary operation");
8586 }
8587
8588 // Convert left argument as necessary.
8589 if (left_type->Is(Type::Number())) {
8590 ASSERT(right_type->Is(Type::String()));
8207 left = BuildNumberToString(left, left_type); 8591 left = BuildNumberToString(left, left_type);
8208 } else { 8592 } else if (!left_type->Is(Type::String())) {
8209 ASSERT(right_type->Is(Type::String())); 8593 ASSERT(right_type->Is(Type::String()));
8210 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT); 8594 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT);
8211 Add<HPushArgument>(left); 8595 Add<HPushArgument>(left);
8212 Add<HPushArgument>(right); 8596 Add<HPushArgument>(right);
8213 return NewUncasted<HInvokeFunction>(function, 2); 8597 return NewUncasted<HInvokeFunction>(function, 2);
8214 } 8598 }
8215 8599
8216 if (right_type->Is(Type::String())) { 8600 // Convert right argument as necessary.
8217 IfBuilder if_isstring(this); 8601 if (right_type->Is(Type::Number())) {
8218 if_isstring.If<HIsStringAndBranch>(right); 8602 ASSERT(left_type->Is(Type::String()));
8219 if_isstring.Then();
8220 if_isstring.ElseDeopt("Expected string for RHS of binary operation");
8221 } else if (right_type->Is(Type::Number())) {
8222 right = BuildNumberToString(right, right_type); 8603 right = BuildNumberToString(right, right_type);
8223 } else { 8604 } else if (!right_type->Is(Type::String())) {
8224 ASSERT(left_type->Is(Type::String())); 8605 ASSERT(left_type->Is(Type::String()));
8225 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); 8606 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT);
8226 Add<HPushArgument>(left); 8607 Add<HPushArgument>(left);
8227 Add<HPushArgument>(right); 8608 Add<HPushArgument>(right);
8228 return NewUncasted<HInvokeFunction>(function, 2); 8609 return NewUncasted<HInvokeFunction>(function, 2);
8229 } 8610 }
8230 8611
8231 return NewUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_NONE); 8612 return NewUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_NONE);
8232 } 8613 }
8233 8614
(...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after
9109 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) { 9490 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) {
9110 ASSERT(call->arguments()->length() == 1); 9491 ASSERT(call->arguments()->length() == 1);
9111 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9492 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9112 HValue* value = Pop(); 9493 HValue* value = Pop();
9113 HHasInstanceTypeAndBranch* result = 9494 HHasInstanceTypeAndBranch* result =
9114 New<HHasInstanceTypeAndBranch>(value, JS_FUNCTION_TYPE); 9495 New<HHasInstanceTypeAndBranch>(value, JS_FUNCTION_TYPE);
9115 return ast_context()->ReturnControl(result, call->id()); 9496 return ast_context()->ReturnControl(result, call->id());
9116 } 9497 }
9117 9498
9118 9499
9500 void HOptimizedGraphBuilder::GenerateIsMinusZero(CallRuntime* call) {
9501 ASSERT(call->arguments()->length() == 1);
9502 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9503 HValue* value = Pop();
9504 HCompareMinusZeroAndBranch* result = New<HCompareMinusZeroAndBranch>(value);
9505 return ast_context()->ReturnControl(result, call->id());
9506 }
9507
9508
9119 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { 9509 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
9120 ASSERT(call->arguments()->length() == 1); 9510 ASSERT(call->arguments()->length() == 1);
9121 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9511 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9122 HValue* value = Pop(); 9512 HValue* value = Pop();
9123 HHasCachedArrayIndexAndBranch* result = 9513 HHasCachedArrayIndexAndBranch* result =
9124 New<HHasCachedArrayIndexAndBranch>(value); 9514 New<HHasCachedArrayIndexAndBranch>(value);
9125 return ast_context()->ReturnControl(result, call->id()); 9515 return ast_context()->ReturnControl(result, call->id());
9126 } 9516 }
9127 9517
9128 9518
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
9492 ASSERT_EQ(2, call->arguments()->length()); 9882 ASSERT_EQ(2, call->arguments()->length());
9493 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9883 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9494 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 9884 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9495 HValue* right = Pop(); 9885 HValue* right = Pop();
9496 HValue* left = Pop(); 9886 HValue* left = Pop();
9497 HInstruction* result = NewUncasted<HPower>(left, right); 9887 HInstruction* result = NewUncasted<HPower>(left, right);
9498 return ast_context()->ReturnInstruction(result, call->id()); 9888 return ast_context()->ReturnInstruction(result, call->id());
9499 } 9889 }
9500 9890
9501 9891
9502 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) {
9503 ASSERT_EQ(1, call->arguments()->length());
9504 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9505 HCallStub* result = New<HCallStub>(CodeStub::TranscendentalCache, 1);
9506 result->set_transcendental_type(TranscendentalCache::SIN);
9507 Drop(1);
9508 return ast_context()->ReturnInstruction(result, call->id());
9509 }
9510
9511
9512 void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) {
9513 ASSERT_EQ(1, call->arguments()->length());
9514 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9515 HCallStub* result = New<HCallStub>(CodeStub::TranscendentalCache, 1);
9516 result->set_transcendental_type(TranscendentalCache::COS);
9517 Drop(1);
9518 return ast_context()->ReturnInstruction(result, call->id());
9519 }
9520
9521
9522 void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) {
9523 ASSERT_EQ(1, call->arguments()->length());
9524 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9525 HCallStub* result = New<HCallStub>(CodeStub::TranscendentalCache, 1);
9526 result->set_transcendental_type(TranscendentalCache::TAN);
9527 Drop(1);
9528 return ast_context()->ReturnInstruction(result, call->id());
9529 }
9530
9531
9532 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) { 9892 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) {
9533 ASSERT_EQ(1, call->arguments()->length()); 9893 ASSERT_EQ(1, call->arguments()->length());
9534 CHECK_ALIVE(VisitArgumentList(call->arguments())); 9894 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9535 HCallStub* result = New<HCallStub>(CodeStub::TranscendentalCache, 1); 9895 HCallStub* result = New<HCallStub>(CodeStub::TranscendentalCache, 1);
9536 result->set_transcendental_type(TranscendentalCache::LOG); 9896 result->set_transcendental_type(TranscendentalCache::LOG);
9537 Drop(1); 9897 Drop(1);
9538 return ast_context()->ReturnInstruction(result, call->id()); 9898 return ast_context()->ReturnInstruction(result, call->id());
9539 } 9899 }
9540 9900
9541 9901
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after
10192 if (ShouldProduceTraceOutput()) { 10552 if (ShouldProduceTraceOutput()) {
10193 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 10553 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
10194 } 10554 }
10195 10555
10196 #ifdef DEBUG 10556 #ifdef DEBUG
10197 graph_->Verify(false); // No full verify. 10557 graph_->Verify(false); // No full verify.
10198 #endif 10558 #endif
10199 } 10559 }
10200 10560
10201 } } // namespace v8::internal 10561 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-dehoist.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698