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

Side by Side Diff: src/hydrogen.cc

Issue 110573004: Merge bleeding_edge 17696:18016. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 7 years 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
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 587 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 phi->Verify(); 598 phi->Verify();
599 } 599 }
600 600
601 // Check that all join blocks have predecessors that end with an 601 // Check that all join blocks have predecessors that end with an
602 // unconditional goto and agree on their environment node id. 602 // unconditional goto and agree on their environment node id.
603 if (block->predecessors()->length() >= 2) { 603 if (block->predecessors()->length() >= 2) {
604 BailoutId id = 604 BailoutId id =
605 block->predecessors()->first()->last_environment()->ast_id(); 605 block->predecessors()->first()->last_environment()->ast_id();
606 for (int k = 0; k < block->predecessors()->length(); k++) { 606 for (int k = 0; k < block->predecessors()->length(); k++) {
607 HBasicBlock* predecessor = block->predecessors()->at(k); 607 HBasicBlock* predecessor = block->predecessors()->at(k);
608 ASSERT(predecessor->end()->IsGoto()); 608 ASSERT(predecessor->end()->IsGoto() ||
609 predecessor->end()->IsDeoptimize());
609 ASSERT(predecessor->last_environment()->ast_id() == id); 610 ASSERT(predecessor->last_environment()->ast_id() == id);
610 } 611 }
611 } 612 }
612 } 613 }
613 614
614 // Check special property of first block to have no predecessors. 615 // Check special property of first block to have no predecessors.
615 ASSERT(blocks_.at(0)->predecessors()->is_empty()); 616 ASSERT(blocks_.at(0)->predecessors()->is_empty());
616 617
617 if (do_full_verify) { 618 if (do_full_verify) {
618 // Check that the graph is fully connected. 619 // Check that the graph is fully connected.
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 if (IsConstantFalse(constant)) return true; 739 if (IsConstantFalse(constant)) return true;
739 if (IsConstantHole(constant)) return true; 740 if (IsConstantHole(constant)) return true;
740 if (IsConstantNull(constant)) return true; 741 if (IsConstantNull(constant)) return true;
741 return false; 742 return false;
742 } 743 }
743 744
744 745
745 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder) 746 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
746 : builder_(builder), 747 : builder_(builder),
747 finished_(false), 748 finished_(false),
748 deopt_then_(false),
749 deopt_else_(false),
750 did_then_(false), 749 did_then_(false),
751 did_else_(false), 750 did_else_(false),
751 did_else_if_(false),
752 did_and_(false), 752 did_and_(false),
753 did_or_(false), 753 did_or_(false),
754 captured_(false), 754 captured_(false),
755 needs_compare_(true), 755 needs_compare_(true),
756 pending_merge_block_(false),
756 split_edge_merge_block_(NULL), 757 split_edge_merge_block_(NULL),
757 merge_block_(NULL) { 758 merge_at_join_blocks_(NULL),
759 normal_merge_at_join_block_count_(0),
760 deopt_merge_at_join_block_count_(0) {
758 HEnvironment* env = builder->environment(); 761 HEnvironment* env = builder->environment();
759 first_true_block_ = builder->CreateBasicBlock(env->Copy()); 762 first_true_block_ = builder->CreateBasicBlock(env->Copy());
760 last_true_block_ = NULL;
761 first_false_block_ = builder->CreateBasicBlock(env->Copy()); 763 first_false_block_ = builder->CreateBasicBlock(env->Copy());
762 } 764 }
763 765
764 766
765 HGraphBuilder::IfBuilder::IfBuilder( 767 HGraphBuilder::IfBuilder::IfBuilder(
766 HGraphBuilder* builder, 768 HGraphBuilder* builder,
767 HIfContinuation* continuation) 769 HIfContinuation* continuation)
768 : builder_(builder), 770 : builder_(builder),
769 finished_(false), 771 finished_(false),
770 deopt_then_(false),
771 deopt_else_(false),
772 did_then_(false), 772 did_then_(false),
773 did_else_(false), 773 did_else_(false),
774 did_else_if_(false),
774 did_and_(false), 775 did_and_(false),
775 did_or_(false), 776 did_or_(false),
776 captured_(false), 777 captured_(false),
777 needs_compare_(false), 778 needs_compare_(false),
779 pending_merge_block_(false),
778 first_true_block_(NULL), 780 first_true_block_(NULL),
779 last_true_block_(NULL),
780 first_false_block_(NULL), 781 first_false_block_(NULL),
781 split_edge_merge_block_(NULL), 782 split_edge_merge_block_(NULL),
782 merge_block_(NULL) { 783 merge_at_join_blocks_(NULL),
784 normal_merge_at_join_block_count_(0),
785 deopt_merge_at_join_block_count_(0) {
783 continuation->Continue(&first_true_block_, 786 continuation->Continue(&first_true_block_,
784 &first_false_block_); 787 &first_false_block_);
785 } 788 }
786 789
787 790
788 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare( 791 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
789 HControlInstruction* compare) { 792 HControlInstruction* compare) {
793 ASSERT(did_then_ == did_else_);
794 if (did_else_) {
795 // Handle if-then-elseif
796 did_else_if_ = true;
797 did_else_ = false;
798 did_then_ = false;
799 did_and_ = false;
800 did_or_ = false;
801 pending_merge_block_ = false;
802 split_edge_merge_block_ = NULL;
803 HEnvironment* env = builder_->environment();
804 first_true_block_ = builder_->CreateBasicBlock(env->Copy());
805 first_false_block_ = builder_->CreateBasicBlock(env->Copy());
806 }
790 if (split_edge_merge_block_ != NULL) { 807 if (split_edge_merge_block_ != NULL) {
791 HEnvironment* env = first_false_block_->last_environment(); 808 HEnvironment* env = first_false_block_->last_environment();
792 HBasicBlock* split_edge = 809 HBasicBlock* split_edge =
793 builder_->CreateBasicBlock(env->Copy()); 810 builder_->CreateBasicBlock(env->Copy());
794 if (did_or_) { 811 if (did_or_) {
795 compare->SetSuccessorAt(0, split_edge); 812 compare->SetSuccessorAt(0, split_edge);
796 compare->SetSuccessorAt(1, first_false_block_); 813 compare->SetSuccessorAt(1, first_false_block_);
797 } else { 814 } else {
798 compare->SetSuccessorAt(0, first_true_block_); 815 compare->SetSuccessorAt(0, first_true_block_);
799 compare->SetSuccessorAt(1, split_edge); 816 compare->SetSuccessorAt(1, split_edge);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
835 builder_->GotoNoSimulate(first_false_block_, split_edge_merge_block_); 852 builder_->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
836 first_false_block_ = split_edge_merge_block_; 853 first_false_block_ = split_edge_merge_block_;
837 } 854 }
838 builder_->set_current_block(first_true_block_); 855 builder_->set_current_block(first_true_block_);
839 first_true_block_ = builder_->CreateBasicBlock(env->Copy()); 856 first_true_block_ = builder_->CreateBasicBlock(env->Copy());
840 } 857 }
841 858
842 859
843 void HGraphBuilder::IfBuilder::CaptureContinuation( 860 void HGraphBuilder::IfBuilder::CaptureContinuation(
844 HIfContinuation* continuation) { 861 HIfContinuation* continuation) {
862 ASSERT(!did_else_if_);
845 ASSERT(!finished_); 863 ASSERT(!finished_);
846 ASSERT(!captured_); 864 ASSERT(!captured_);
847 HBasicBlock* true_block = last_true_block_ == NULL 865
848 ? first_true_block_ 866 HBasicBlock* true_block = NULL;
849 : last_true_block_; 867 HBasicBlock* false_block = NULL;
850 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) 868 Finish(&true_block, &false_block);
851 ? builder_->current_block() 869 ASSERT(true_block != NULL);
852 : first_false_block_; 870 ASSERT(false_block != NULL);
853 continuation->Capture(true_block, false_block); 871 continuation->Capture(true_block, false_block);
854 captured_ = true; 872 captured_ = true;
873 builder_->set_current_block(NULL);
855 End(); 874 End();
856 } 875 }
857 876
858 877
859 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { 878 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
879 ASSERT(!did_else_if_);
860 ASSERT(!finished_); 880 ASSERT(!finished_);
861 ASSERT(!captured_); 881 ASSERT(!captured_);
862 ASSERT(did_then_); 882 HBasicBlock* true_block = NULL;
863 if (!did_else_) Else(); 883 HBasicBlock* false_block = NULL;
864 HBasicBlock* true_block = last_true_block_ == NULL 884 Finish(&true_block, &false_block);
865 ? first_true_block_ 885 merge_at_join_blocks_ = NULL;
866 : last_true_block_;
867 HBasicBlock* false_block = builder_->current_block();
868 if (true_block != NULL && !true_block->IsFinished()) { 886 if (true_block != NULL && !true_block->IsFinished()) {
869 ASSERT(continuation->IsTrueReachable()); 887 ASSERT(continuation->IsTrueReachable());
870 builder_->GotoNoSimulate(true_block, continuation->true_branch()); 888 builder_->GotoNoSimulate(true_block, continuation->true_branch());
871 } 889 }
872 if (false_block != NULL && !false_block->IsFinished()) { 890 if (false_block != NULL && !false_block->IsFinished()) {
873 ASSERT(continuation->IsFalseReachable()); 891 ASSERT(continuation->IsFalseReachable());
874 builder_->GotoNoSimulate(false_block, continuation->false_branch()); 892 builder_->GotoNoSimulate(false_block, continuation->false_branch());
875 } 893 }
876 captured_ = true; 894 captured_ = true;
877 End(); 895 End();
(...skipping 10 matching lines...) Expand all
888 // so that the graph builder visits it and sees any live range extending 906 // so that the graph builder visits it and sees any live range extending
889 // constructs within it. 907 // constructs within it.
890 HConstant* constant_false = builder_->graph()->GetConstantFalse(); 908 HConstant* constant_false = builder_->graph()->GetConstantFalse();
891 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); 909 ToBooleanStub::Types boolean_type = ToBooleanStub::Types();
892 boolean_type.Add(ToBooleanStub::BOOLEAN); 910 boolean_type.Add(ToBooleanStub::BOOLEAN);
893 HBranch* branch = builder()->New<HBranch>( 911 HBranch* branch = builder()->New<HBranch>(
894 constant_false, boolean_type, first_true_block_, first_false_block_); 912 constant_false, boolean_type, first_true_block_, first_false_block_);
895 builder_->FinishCurrentBlock(branch); 913 builder_->FinishCurrentBlock(branch);
896 } 914 }
897 builder_->set_current_block(first_true_block_); 915 builder_->set_current_block(first_true_block_);
916 pending_merge_block_ = true;
898 } 917 }
899 918
900 919
901 void HGraphBuilder::IfBuilder::Else() { 920 void HGraphBuilder::IfBuilder::Else() {
902 ASSERT(did_then_); 921 ASSERT(did_then_);
903 ASSERT(!captured_); 922 ASSERT(!captured_);
904 ASSERT(!finished_); 923 ASSERT(!finished_);
905 last_true_block_ = builder_->current_block(); 924 AddMergeAtJoinBlock(false);
906 builder_->set_current_block(first_false_block_); 925 builder_->set_current_block(first_false_block_);
926 pending_merge_block_ = true;
907 did_else_ = true; 927 did_else_ = true;
908 } 928 }
909 929
910 930
911 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { 931 void HGraphBuilder::IfBuilder::Deopt(const char* reason) {
912 ASSERT(did_then_); 932 ASSERT(did_then_);
913 if (did_else_) {
914 deopt_else_ = true;
915 } else {
916 deopt_then_ = true;
917 }
918 builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER); 933 builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
934 AddMergeAtJoinBlock(true);
919 } 935 }
920 936
921 937
922 void HGraphBuilder::IfBuilder::Return(HValue* value) { 938 void HGraphBuilder::IfBuilder::Return(HValue* value) {
923 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); 939 HValue* parameter_count = builder_->graph()->GetConstantMinus1();
924 builder_->FinishExitCurrentBlock( 940 builder_->FinishExitCurrentBlock(
925 builder_->New<HReturn>(value, parameter_count)); 941 builder_->New<HReturn>(value, parameter_count));
926 if (did_else_) { 942 AddMergeAtJoinBlock(false);
927 first_false_block_ = NULL;
928 } else {
929 first_true_block_ = NULL;
930 }
931 } 943 }
932 944
933 945
934 void HGraphBuilder::IfBuilder::End() { 946 void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(bool deopt) {
935 if (!captured_) { 947 if (!pending_merge_block_) return;
936 ASSERT(did_then_); 948 HBasicBlock* block = builder_->current_block();
937 if (!did_else_) { 949 ASSERT(block == NULL || !block->IsFinished());
938 last_true_block_ = builder_->current_block(); 950 MergeAtJoinBlock* record =
951 new(builder_->zone()) MergeAtJoinBlock(block, deopt,
952 merge_at_join_blocks_);
953 merge_at_join_blocks_ = record;
954 if (block != NULL) {
955 ASSERT(block->end() == NULL);
956 if (deopt) {
957 normal_merge_at_join_block_count_++;
958 } else {
959 deopt_merge_at_join_block_count_++;
939 } 960 }
940 if (last_true_block_ == NULL || last_true_block_->IsFinished()) { 961 }
941 ASSERT(did_else_); 962 builder_->set_current_block(NULL);
942 // Return on true. Nothing to do, just continue the false block. 963 pending_merge_block_ = false;
943 } else if (first_false_block_ == NULL || 964 }
944 (did_else_ && builder_->current_block()->IsFinished())) { 965
945 // Deopt on false. Nothing to do except switching to the true block. 966
946 builder_->set_current_block(last_true_block_); 967 void HGraphBuilder::IfBuilder::Finish() {
947 } else { 968 ASSERT(!finished_);
948 merge_block_ = builder_->graph()->CreateBasicBlock(); 969 if (!did_then_) {
949 ASSERT(!finished_); 970 Then();
950 if (!did_else_) Else(); 971 }
951 ASSERT(!last_true_block_->IsFinished()); 972 AddMergeAtJoinBlock(false);
952 HBasicBlock* last_false_block = builder_->current_block(); 973 if (!did_else_) {
953 ASSERT(!last_false_block->IsFinished()); 974 Else();
954 if (deopt_then_) { 975 AddMergeAtJoinBlock(false);
955 builder_->GotoNoSimulate(last_false_block, merge_block_);
956 builder_->PadEnvironmentForContinuation(last_true_block_,
957 merge_block_);
958 builder_->GotoNoSimulate(last_true_block_, merge_block_);
959 } else {
960 builder_->GotoNoSimulate(last_true_block_, merge_block_);
961 if (deopt_else_) {
962 builder_->PadEnvironmentForContinuation(last_false_block,
963 merge_block_);
964 }
965 builder_->GotoNoSimulate(last_false_block, merge_block_);
966 }
967 builder_->set_current_block(merge_block_);
968 }
969 } 976 }
970 finished_ = true; 977 finished_ = true;
971 } 978 }
972 979
973 980
981 void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation,
982 HBasicBlock** else_continuation) {
983 Finish();
984
985 MergeAtJoinBlock* else_record = merge_at_join_blocks_;
986 if (else_continuation != NULL) {
987 *else_continuation = else_record->block_;
988 }
989 MergeAtJoinBlock* then_record = else_record->next_;
990 if (then_continuation != NULL) {
991 *then_continuation = then_record->block_;
992 }
993 ASSERT(then_record->next_ == NULL);
994 }
995
996
997 void HGraphBuilder::IfBuilder::End() {
998 if (captured_) return;
999 Finish();
1000
1001 int total_merged_blocks = normal_merge_at_join_block_count_ +
1002 deopt_merge_at_join_block_count_;
1003 ASSERT(total_merged_blocks >= 1);
1004 HBasicBlock* merge_block = total_merged_blocks == 1
1005 ? NULL : builder_->graph()->CreateBasicBlock();
1006
1007 // Merge non-deopt blocks first to ensure environment has right size for
1008 // padding.
1009 MergeAtJoinBlock* current = merge_at_join_blocks_;
1010 while (current != NULL) {
1011 if (!current->deopt_ && current->block_ != NULL) {
1012 // If there is only one block that makes it through to the end of the
1013 // if, then just set it as the current block and continue rather then
1014 // creating an unnecessary merge block.
1015 if (total_merged_blocks == 1) {
1016 builder_->set_current_block(current->block_);
1017 return;
1018 }
1019 builder_->GotoNoSimulate(current->block_, merge_block);
1020 }
1021 current = current->next_;
1022 }
1023
1024 // Merge deopt blocks, padding when necessary.
1025 current = merge_at_join_blocks_;
1026 while (current != NULL) {
1027 if (current->deopt_ && current->block_ != NULL) {
1028 builder_->PadEnvironmentForContinuation(current->block_,
1029 merge_block);
1030 builder_->GotoNoSimulate(current->block_, merge_block);
1031 }
1032 current = current->next_;
1033 }
1034 builder_->set_current_block(merge_block);
1035 }
1036
1037
974 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, 1038 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder,
975 HValue* context, 1039 HValue* context,
976 LoopBuilder::Direction direction) 1040 LoopBuilder::Direction direction)
977 : builder_(builder), 1041 : builder_(builder),
978 context_(context), 1042 context_(context),
979 direction_(direction), 1043 direction_(direction),
980 finished_(false) { 1044 finished_(false) {
981 header_block_ = builder->CreateLoopHeaderBlock(); 1045 header_block_ = builder->CreateLoopHeaderBlock();
982 body_block_ = NULL; 1046 body_block_ = NULL;
983 exit_block_ = NULL; 1047 exit_block_ = NULL;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1044 1108
1045 void HGraphBuilder::LoopBuilder::Break() { 1109 void HGraphBuilder::LoopBuilder::Break() {
1046 if (exit_trampoline_block_ == NULL) { 1110 if (exit_trampoline_block_ == NULL) {
1047 // Its the first time we saw a break. 1111 // Its the first time we saw a break.
1048 HEnvironment* env = exit_block_->last_environment()->Copy(); 1112 HEnvironment* env = exit_block_->last_environment()->Copy();
1049 exit_trampoline_block_ = builder_->CreateBasicBlock(env); 1113 exit_trampoline_block_ = builder_->CreateBasicBlock(env);
1050 builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_); 1114 builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
1051 } 1115 }
1052 1116
1053 builder_->GotoNoSimulate(exit_trampoline_block_); 1117 builder_->GotoNoSimulate(exit_trampoline_block_);
1118 builder_->set_current_block(NULL);
1054 } 1119 }
1055 1120
1056 1121
1057 void HGraphBuilder::LoopBuilder::EndBody() { 1122 void HGraphBuilder::LoopBuilder::EndBody() {
1058 ASSERT(!finished_); 1123 ASSERT(!finished_);
1059 1124
1060 if (direction_ == kPostIncrement || direction_ == kPostDecrement) { 1125 if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
1061 if (direction_ == kPostIncrement) { 1126 if (direction_ == kPostIncrement) {
1062 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_); 1127 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_);
1063 } else { 1128 } else {
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
1201 ASSERT(continuation->predecessors()->length() == 0); 1266 ASSERT(continuation->predecessors()->length() == 0);
1202 } 1267 }
1203 } 1268 }
1204 1269
1205 1270
1206 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) { 1271 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) {
1207 return Add<HCheckMaps>(obj, map, top_info()); 1272 return Add<HCheckMaps>(obj, map, top_info());
1208 } 1273 }
1209 1274
1210 1275
1276 HValue* HGraphBuilder::BuildCheckString(HValue* string) {
1277 if (!string->type().IsString()) {
1278 ASSERT(!string->IsConstant() ||
1279 !HConstant::cast(string)->HasStringValue());
1280 BuildCheckHeapObject(string);
1281 return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
1282 }
1283 return string;
1284 }
1285
1286
1211 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) { 1287 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
1212 if (object->type().IsJSObject()) return object; 1288 if (object->type().IsJSObject()) return object;
1213 return Add<HWrapReceiver>(object, function); 1289 return Add<HWrapReceiver>(object, function);
1214 } 1290 }
1215 1291
1216 1292
1217 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, 1293 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
1218 HValue* elements, 1294 HValue* elements,
1219 ElementsKind kind, 1295 ElementsKind kind,
1220 HValue* length, 1296 HValue* length,
1221 HValue* key, 1297 HValue* key,
1222 bool is_js_array) { 1298 bool is_js_array) {
1223 IfBuilder length_checker(this); 1299 IfBuilder length_checker(this);
1224 1300
1225 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; 1301 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
1226 length_checker.If<HCompareNumericAndBranch>(key, length, token); 1302 length_checker.If<HCompareNumericAndBranch>(key, length, token);
1227 1303
1228 length_checker.Then(); 1304 length_checker.Then();
1229 1305
1230 HValue* current_capacity = AddLoadFixedArrayLength(elements); 1306 HValue* current_capacity = AddLoadFixedArrayLength(elements);
1231 1307
1232 IfBuilder capacity_checker(this); 1308 IfBuilder capacity_checker(this);
1233 1309
1234 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity, 1310 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
1235 Token::GTE); 1311 Token::GTE);
1236 capacity_checker.Then(); 1312 capacity_checker.Then();
1237 1313
1238 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); 1314 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
1239 HValue* max_capacity = Add<HAdd>(current_capacity, max_gap); 1315 HValue* max_capacity = AddUncasted<HAdd>(current_capacity, max_gap);
1240 IfBuilder key_checker(this); 1316 IfBuilder key_checker(this);
1241 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT); 1317 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT);
1242 key_checker.Then(); 1318 key_checker.Then();
1243 key_checker.ElseDeopt("Key out of capacity range"); 1319 key_checker.ElseDeopt("Key out of capacity range");
1244 key_checker.End(); 1320 key_checker.End();
1245 1321
1246 HValue* new_capacity = BuildNewElementsCapacity(key); 1322 HValue* new_capacity = BuildNewElementsCapacity(key);
1247 HValue* new_elements = BuildGrowElementsCapacity(object, elements, 1323 HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1248 kind, kind, length, 1324 kind, kind, length,
1249 new_capacity); 1325 new_capacity);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1333 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, 1409 BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
1334 array_length, elements_length); 1410 array_length, elements_length);
1335 1411
1336 if_builder.End(); 1412 if_builder.End();
1337 } 1413 }
1338 1414
1339 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); 1415 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
1340 } 1416 }
1341 1417
1342 1418
1419 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoadHelper(
1420 HValue* elements,
1421 HValue* key,
1422 HValue* hash,
1423 HValue* mask,
1424 int current_probe) {
1425 if (current_probe == kNumberDictionaryProbes) {
1426 return NULL;
1427 }
1428
1429 int32_t offset = SeededNumberDictionary::GetProbeOffset(current_probe);
1430 HValue* raw_index = (current_probe == 0)
1431 ? hash
1432 : AddUncasted<HAdd>(hash, Add<HConstant>(offset));
1433 raw_index = AddUncasted<HBitwise>(Token::BIT_AND, raw_index, mask);
1434 int32_t entry_size = SeededNumberDictionary::kEntrySize;
1435 raw_index = AddUncasted<HMul>(raw_index, Add<HConstant>(entry_size));
1436 raw_index->ClearFlag(HValue::kCanOverflow);
1437
1438 int32_t base_offset = SeededNumberDictionary::kElementsStartIndex;
1439 HValue* key_index = AddUncasted<HAdd>(raw_index, Add<HConstant>(base_offset));
1440 key_index->ClearFlag(HValue::kCanOverflow);
1441
1442 HValue* candidate_key = Add<HLoadKeyed>(elements, key_index,
1443 static_cast<HValue*>(NULL),
1444 FAST_SMI_ELEMENTS);
1445
1446 IfBuilder key_compare(this);
1447 key_compare.IfNot<HCompareObjectEqAndBranch>(key, candidate_key);
1448 key_compare.Then();
1449 {
1450 // Key at the current probe doesn't match, try at the next probe.
1451 HValue* result = BuildUncheckedDictionaryElementLoadHelper(
1452 elements, key, hash, mask, current_probe + 1);
1453 if (result == NULL) {
1454 key_compare.Deopt("probes exhausted in keyed load dictionary lookup");
1455 result = graph()->GetConstantUndefined();
1456 } else {
1457 Push(result);
1458 }
1459 }
1460 key_compare.Else();
1461 {
1462 // Key at current probe matches. Details must be zero, otherwise the
1463 // dictionary element requires special handling.
1464 HValue* details_index = AddUncasted<HAdd>(
1465 raw_index, Add<HConstant>(base_offset + 2));
1466 details_index->ClearFlag(HValue::kCanOverflow);
1467
1468 HValue* details = Add<HLoadKeyed>(elements, details_index,
1469 static_cast<HValue*>(NULL),
1470 FAST_SMI_ELEMENTS);
1471 IfBuilder details_compare(this);
1472 details_compare.If<HCompareNumericAndBranch>(details,
1473 graph()->GetConstant0(),
1474 Token::NE);
1475 details_compare.ThenDeopt("keyed load dictionary element not fast case");
1476
1477 details_compare.Else();
1478 {
1479 // Key matches and details are zero --> fast case. Load and return the
1480 // value.
1481 HValue* result_index = AddUncasted<HAdd>(
1482 raw_index, Add<HConstant>(base_offset + 1));
1483 result_index->ClearFlag(HValue::kCanOverflow);
1484
1485 Push(Add<HLoadKeyed>(elements, result_index,
1486 static_cast<HValue*>(NULL),
1487 FAST_ELEMENTS));
1488 }
1489 details_compare.End();
1490 }
1491 key_compare.End();
1492
1493 return Pop();
1494 }
1495
1496
1497 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) {
1498 int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed());
1499 HValue* seed = Add<HConstant>(seed_value);
1500 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed);
1501
1502 // hash = ~hash + (hash << 15);
1503 HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15));
1504 HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash,
1505 graph()->GetConstantMinus1());
1506 hash = AddUncasted<HAdd>(shifted_hash, not_hash);
1507
1508 // hash = hash ^ (hash >> 12);
1509 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(12));
1510 hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1511
1512 // hash = hash + (hash << 2);
1513 shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(2));
1514 hash = AddUncasted<HAdd>(hash, shifted_hash);
1515
1516 // hash = hash ^ (hash >> 4);
1517 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(4));
1518 hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1519
1520 // hash = hash * 2057;
1521 hash = AddUncasted<HMul>(hash, Add<HConstant>(2057));
1522 hash->ClearFlag(HValue::kCanOverflow);
1523
1524 // hash = hash ^ (hash >> 16);
1525 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16));
1526 return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1527 }
1528
1529
1530 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
1531 HValue* key) {
1532 HValue* elements = AddLoadElements(receiver);
1533
1534 HValue* hash = BuildElementIndexHash(key);
1535
1536 HValue* capacity = Add<HLoadKeyed>(
1537 elements,
1538 Add<HConstant>(NameDictionary::kCapacityIndex),
1539 static_cast<HValue*>(NULL),
1540 FAST_SMI_ELEMENTS);
1541
1542 HValue* mask = Add<HSub>(capacity, graph()->GetConstant1());
1543 mask->ChangeRepresentation(Representation::Integer32());
1544 mask->ClearFlag(HValue::kCanOverflow);
1545
1546 return BuildUncheckedDictionaryElementLoadHelper(elements, key,
1547 hash, mask, 0);
1548 }
1549
1550
1343 HValue* HGraphBuilder::BuildNumberToString(HValue* object, 1551 HValue* HGraphBuilder::BuildNumberToString(HValue* object,
1344 Handle<Type> type) { 1552 Handle<Type> type) {
1345 NoObservableSideEffectsScope scope(this); 1553 NoObservableSideEffectsScope scope(this);
1346 1554
1555 // Convert constant numbers at compile time.
1556 if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) {
1557 Handle<Object> number = HConstant::cast(object)->handle(isolate());
1558 Handle<String> result = isolate()->factory()->NumberToString(number);
1559 return Add<HConstant>(result);
1560 }
1561
1347 // Create a joinable continuation. 1562 // Create a joinable continuation.
1348 HIfContinuation found(graph()->CreateBasicBlock(), 1563 HIfContinuation found(graph()->CreateBasicBlock(),
1349 graph()->CreateBasicBlock()); 1564 graph()->CreateBasicBlock());
1350 1565
1351 // Load the number string cache. 1566 // Load the number string cache.
1352 HValue* number_string_cache = 1567 HValue* number_string_cache =
1353 Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex); 1568 Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);
1354 1569
1355 // Make the hash mask from the length of the number string cache. It 1570 // Make the hash mask from the length of the number string cache. It
1356 // contains two elements (number and string) for each cache entry. 1571 // contains two elements (number and string) for each cache entry.
1357 HValue* mask = AddLoadFixedArrayLength(number_string_cache); 1572 HValue* mask = AddLoadFixedArrayLength(number_string_cache);
1358 mask->set_type(HType::Smi()); 1573 mask->set_type(HType::Smi());
1359 mask = Add<HSar>(mask, graph()->GetConstant1()); 1574 mask = Add<HSar>(mask, graph()->GetConstant1());
1360 mask = Add<HSub>(mask, graph()->GetConstant1()); 1575 mask = Add<HSub>(mask, graph()->GetConstant1());
1361 1576
1362 // Check whether object is a smi. 1577 // Check whether object is a smi.
1363 IfBuilder if_objectissmi(this); 1578 IfBuilder if_objectissmi(this);
1364 if_objectissmi.If<HIsSmiAndBranch>(object); 1579 if_objectissmi.If<HIsSmiAndBranch>(object);
1365 if_objectissmi.Then(); 1580 if_objectissmi.Then();
1366 { 1581 {
1367 // Compute hash for smi similar to smi_get_hash(). 1582 // Compute hash for smi similar to smi_get_hash().
1368 HValue* hash = Add<HBitwise>(Token::BIT_AND, object, mask); 1583 HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask);
1369 1584
1370 // Load the key. 1585 // Load the key.
1371 HValue* key_index = Add<HShl>(hash, graph()->GetConstant1()); 1586 HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
1372 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, 1587 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index,
1373 static_cast<HValue*>(NULL), 1588 static_cast<HValue*>(NULL),
1374 FAST_ELEMENTS, ALLOW_RETURN_HOLE); 1589 FAST_ELEMENTS, ALLOW_RETURN_HOLE);
1375 1590
1376 // Check if object == key. 1591 // Check if object == key.
1377 IfBuilder if_objectiskey(this); 1592 IfBuilder if_objectiskey(this);
1378 if_objectiskey.If<HCompareObjectEqAndBranch>(object, key); 1593 if_objectiskey.If<HCompareObjectEqAndBranch>(object, key);
1379 if_objectiskey.Then(); 1594 if_objectiskey.Then();
1380 { 1595 {
1381 // Make the key_index available. 1596 // Make the key_index available.
(...skipping 10 matching lines...) Expand all
1392 IfBuilder if_objectisnumber(this); 1607 IfBuilder if_objectisnumber(this);
1393 if_objectisnumber.If<HCompareMap>( 1608 if_objectisnumber.If<HCompareMap>(
1394 object, isolate()->factory()->heap_number_map()); 1609 object, isolate()->factory()->heap_number_map());
1395 if_objectisnumber.Then(); 1610 if_objectisnumber.Then();
1396 { 1611 {
1397 // Compute hash for heap number similar to double_get_hash(). 1612 // Compute hash for heap number similar to double_get_hash().
1398 HValue* low = Add<HLoadNamedField>( 1613 HValue* low = Add<HLoadNamedField>(
1399 object, HObjectAccess::ForHeapNumberValueLowestBits()); 1614 object, HObjectAccess::ForHeapNumberValueLowestBits());
1400 HValue* high = Add<HLoadNamedField>( 1615 HValue* high = Add<HLoadNamedField>(
1401 object, HObjectAccess::ForHeapNumberValueHighestBits()); 1616 object, HObjectAccess::ForHeapNumberValueHighestBits());
1402 HValue* hash = Add<HBitwise>(Token::BIT_XOR, low, high); 1617 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high);
1403 hash = Add<HBitwise>(Token::BIT_AND, hash, mask); 1618 hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask);
1404 1619
1405 // Load the key. 1620 // Load the key.
1406 HValue* key_index = Add<HShl>(hash, graph()->GetConstant1()); 1621 HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
1407 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, 1622 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index,
1408 static_cast<HValue*>(NULL), 1623 static_cast<HValue*>(NULL),
1409 FAST_ELEMENTS, ALLOW_RETURN_HOLE); 1624 FAST_ELEMENTS, ALLOW_RETURN_HOLE);
1410 1625
1411 // Check if key is a heap number (the number string cache contains only 1626 // Check if key is a heap number (the number string cache contains only
1412 // SMIs and heap number, so it is sufficient to do a SMI check here). 1627 // SMIs and heap number, so it is sufficient to do a SMI check here).
1413 IfBuilder if_keyisnotsmi(this); 1628 IfBuilder if_keyisnotsmi(this);
1414 if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key); 1629 if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key);
1415 if_keyisnotsmi.Then(); 1630 if_keyisnotsmi.Then();
1416 { 1631 {
(...skipping 25 matching lines...) Expand all
1442 1657
1443 // Check for cache hit. 1658 // Check for cache hit.
1444 IfBuilder if_found(this, &found); 1659 IfBuilder if_found(this, &found);
1445 if_found.Then(); 1660 if_found.Then();
1446 { 1661 {
1447 // Count number to string operation in native code. 1662 // Count number to string operation in native code.
1448 AddIncrementCounter(isolate()->counters()->number_to_string_native()); 1663 AddIncrementCounter(isolate()->counters()->number_to_string_native());
1449 1664
1450 // Load the value in case of cache hit. 1665 // Load the value in case of cache hit.
1451 HValue* key_index = Pop(); 1666 HValue* key_index = Pop();
1452 HValue* value_index = Add<HAdd>(key_index, graph()->GetConstant1()); 1667 HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1());
1453 Push(Add<HLoadKeyed>(number_string_cache, value_index, 1668 Push(Add<HLoadKeyed>(number_string_cache, value_index,
1454 static_cast<HValue*>(NULL), 1669 static_cast<HValue*>(NULL),
1455 FAST_ELEMENTS, ALLOW_RETURN_HOLE)); 1670 FAST_ELEMENTS, ALLOW_RETURN_HOLE));
1456 } 1671 }
1457 if_found.Else(); 1672 if_found.Else();
1458 { 1673 {
1459 // Cache miss, fallback to runtime. 1674 // Cache miss, fallback to runtime.
1460 Add<HPushArgument>(object); 1675 Add<HPushArgument>(object);
1461 Push(Add<HCallRuntime>( 1676 Push(Add<HCallRuntime>(
1462 isolate()->factory()->empty_string(), 1677 isolate()->factory()->empty_string(),
1463 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), 1678 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
1464 1)); 1679 1));
1465 } 1680 }
1466 if_found.End(); 1681 if_found.End();
1467 1682
1468 return Pop(); 1683 return Pop();
1469 } 1684 }
1470 1685
1471 1686
1472 HValue* HGraphBuilder::BuildSeqStringSizeFor(HValue* length, 1687 HValue* HGraphBuilder::BuildSeqStringSizeFor(HValue* length,
1473 String::Encoding encoding) { 1688 String::Encoding encoding) {
1474 STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0); 1689 STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
1475 HValue* size = length; 1690 HValue* size = length;
1476 if (encoding == String::TWO_BYTE_ENCODING) { 1691 if (encoding == String::TWO_BYTE_ENCODING) {
1477 size = Add<HShl>(length, graph()->GetConstant1()); 1692 size = AddUncasted<HShl>(length, graph()->GetConstant1());
1478 size->ClearFlag(HValue::kCanOverflow); 1693 size->ClearFlag(HValue::kCanOverflow);
1479 size->SetFlag(HValue::kUint32); 1694 size->SetFlag(HValue::kUint32);
1480 } 1695 }
1481 size = Add<HAdd>(size, Add<HConstant>(static_cast<int32_t>( 1696 size = AddUncasted<HAdd>(size, Add<HConstant>(static_cast<int32_t>(
1482 SeqString::kHeaderSize + kObjectAlignmentMask))); 1697 SeqString::kHeaderSize + kObjectAlignmentMask)));
1483 size->ClearFlag(HValue::kCanOverflow); 1698 size->ClearFlag(HValue::kCanOverflow);
1484 size = Add<HBitwise>( 1699 size = AddUncasted<HBitwise>(
1485 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>( 1700 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
1486 ~kObjectAlignmentMask))); 1701 ~kObjectAlignmentMask)));
1487 return size; 1702 return size;
1488 } 1703 }
1489 1704
1490 1705
1491 void HGraphBuilder::BuildCopySeqStringChars(HValue* src, 1706 void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
1492 HValue* src_offset, 1707 HValue* src_offset,
1493 String::Encoding src_encoding, 1708 String::Encoding src_encoding,
1494 HValue* dst, 1709 HValue* dst,
1495 HValue* dst_offset, 1710 HValue* dst_offset,
1496 String::Encoding dst_encoding, 1711 String::Encoding dst_encoding,
1497 HValue* length) { 1712 HValue* length) {
1498 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING || 1713 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING ||
1499 src_encoding == String::ONE_BYTE_ENCODING); 1714 src_encoding == String::ONE_BYTE_ENCODING);
1500 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); 1715 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
1501 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); 1716 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
1502 { 1717 {
1503 HValue* src_index = Add<HAdd>(src_offset, index); 1718 HValue* src_index = AddUncasted<HAdd>(src_offset, index);
1504 HValue* value = Add<HSeqStringGetChar>(src_encoding, src, src_index); 1719 HValue* value = Add<HSeqStringGetChar>(src_encoding, src, src_index);
1505 HValue* dst_index = Add<HAdd>(dst_offset, index); 1720 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index);
1506 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); 1721 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
1507 } 1722 }
1508 loop.EndBody(); 1723 loop.EndBody();
1509 } 1724 }
1510 1725
1511 1726
1512 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left, 1727 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left,
1513 HValue* right, 1728 HValue* right,
1514 PretenureFlag pretenure_flag) { 1729 PretenureFlag pretenure_flag) {
1515 // Determine the string lengths. 1730 // Determine the string lengths.
1516 HValue* left_length = Add<HLoadNamedField>( 1731 HValue* left_length = Add<HLoadNamedField>(
1517 left, HObjectAccess::ForStringLength()); 1732 left, HObjectAccess::ForStringLength());
1518 HValue* right_length = Add<HLoadNamedField>( 1733 HValue* right_length = Add<HLoadNamedField>(
1519 right, HObjectAccess::ForStringLength()); 1734 right, HObjectAccess::ForStringLength());
1520 1735
1521 // Check if we concatenated the strings here, or if we have to resort to the 1736 // Compute the combined string length. If the result is larger than the max
1522 // runtime function. 1737 // supported string length, we bailout to the runtime. This is done implicitly
1523 HIfContinuation handled(graph()->CreateBasicBlock(), 1738 // when converting the result back to a smi in case the max string length
1524 graph()->CreateBasicBlock()); 1739 // equals the max smi valie. Otherwise, for platforms with 32-bit smis, we do
1525 1740 HValue* length = AddUncasted<HAdd>(left_length, right_length);
1526 // Check if both parameters do not exceed half the max string length, because 1741 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
1527 // exceptionally long strings should be handled in the runtime. Unfortunately 1742 if (String::kMaxLength != Smi::kMaxValue) {
1528 // we cannot actually check whether the combined length of both strings 1743 IfBuilder if_nooverflow(this);
1529 // exceeds String::kMaxLength (because of unclear results from the 1744 if_nooverflow.If<HCompareNumericAndBranch>(
1530 // representation inference phase), so we use a pessimistic approach here 1745 length, Add<HConstant>(String::kMaxLength), Token::LTE);
1531 // instead, checking that the length of either substring does not exceed half 1746 if_nooverflow.Then();
1532 // of String::kMaxLength. 1747 if_nooverflow.ElseDeopt("String length exceeds limit");
1533 HConstant* max_length = Add<HConstant>(String::kMaxLength / 2); 1748 }
1534 IfBuilder if_nooverflow(this); 1749
1535 if_nooverflow.If<HCompareNumericAndBranch>( 1750 // Determine the string instance types.
1536 left_length, max_length, Token::LTE); 1751 HLoadNamedField* left_instance_type = Add<HLoadNamedField>(
1537 if_nooverflow.AndIf<HCompareNumericAndBranch>( 1752 Add<HLoadNamedField>(left, HObjectAccess::ForMap()),
1538 right_length, max_length, Token::LTE); 1753 HObjectAccess::ForMapInstanceType());
1539 if_nooverflow.Then(); 1754 HLoadNamedField* right_instance_type = Add<HLoadNamedField>(
1755 Add<HLoadNamedField>(right, HObjectAccess::ForMap()),
1756 HObjectAccess::ForMapInstanceType());
1757
1758 // Compute difference of instance types.
1759 HValue* xored_instance_types = AddUncasted<HBitwise>(
1760 Token::BIT_XOR, left_instance_type, right_instance_type);
1761
1762 // Check if we should create a cons string.
1763 IfBuilder if_createcons(this);
1764 if_createcons.If<HCompareNumericAndBranch>(
1765 length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
1766 if_createcons.Then();
1540 { 1767 {
1541 // Determine the string instance types. 1768 // Allocate the cons string object. HAllocate does not care whether we
1542 HLoadNamedField* left_instance_type = Add<HLoadNamedField>( 1769 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use
1543 Add<HLoadNamedField>(left, HObjectAccess::ForMap()), 1770 // CONS_STRING_TYPE here. Below we decide whether the cons string is
1544 HObjectAccess::ForMapInstanceType()); 1771 // one-byte or two-byte and set the appropriate map.
1545 HLoadNamedField* right_instance_type = Add<HLoadNamedField>( 1772 HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize),
1546 Add<HLoadNamedField>(right, HObjectAccess::ForMap()), 1773 HType::String(), pretenure_flag,
1547 HObjectAccess::ForMapInstanceType()); 1774 CONS_STRING_TYPE);
1548 1775
1549 // Compute difference of instance types. 1776 // Compute the intersection of instance types.
1550 HValue* xored_instance_types = Add<HBitwise>( 1777 HValue* anded_instance_types = AddUncasted<HBitwise>(
1551 Token::BIT_XOR, left_instance_type, right_instance_type); 1778 Token::BIT_AND, left_instance_type, right_instance_type);
1552 1779
1553 // Compute the length of the resulting string. 1780 // We create a one-byte cons string if
1554 HValue* length = Add<HAdd>(left_length, right_length); 1781 // 1. both strings are one-byte, or
1555 1782 // 2. at least one of the strings is two-byte, but happens to contain only
1556 // Check if we should create a cons string. 1783 // one-byte characters.
1557 IfBuilder if_createcons(this); 1784 // To do this, we check
1558 if_createcons.If<HCompareNumericAndBranch>( 1785 // 1. if both strings are one-byte, or if the one-byte data hint is set in
1559 length, Add<HConstant>(ConsString::kMinLength), Token::GTE); 1786 // both strings, or
1560 if_createcons.Then(); 1787 // 2. if one of the strings has the one-byte data hint set and the other
1561 { 1788 // string is one-byte.
1562 // Allocate the cons string object. HAllocate does not care whether we 1789 IfBuilder if_onebyte(this);
1563 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use 1790 STATIC_ASSERT(kOneByteStringTag != 0);
1564 // CONS_STRING_TYPE here. Below we decide whether the cons string is 1791 STATIC_ASSERT(kOneByteDataHintMask != 0);
1565 // one-byte or two-byte and set the appropriate map. 1792 if_onebyte.If<HCompareNumericAndBranch>(
1566 HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize), 1793 AddUncasted<HBitwise>(
1567 HType::String(), pretenure_flag, 1794 Token::BIT_AND, anded_instance_types,
1568 CONS_STRING_TYPE); 1795 Add<HConstant>(static_cast<int32_t>(
1569 1796 kStringEncodingMask | kOneByteDataHintMask))),
1570 // Compute the intersection of instance types. 1797 graph()->GetConstant0(), Token::NE);
1571 HValue* anded_instance_types = Add<HBitwise>( 1798 if_onebyte.Or();
1572 Token::BIT_AND, left_instance_type, right_instance_type); 1799 STATIC_ASSERT(kOneByteStringTag != 0 &&
1573 1800 kOneByteDataHintTag != 0 &&
1574 // We create a one-byte cons string if 1801 kOneByteDataHintTag != kOneByteStringTag);
1575 // 1. both strings are one-byte, or 1802 if_onebyte.If<HCompareNumericAndBranch>(
1576 // 2. at least one of the strings is two-byte, but happens to contain only 1803 AddUncasted<HBitwise>(
1577 // one-byte characters. 1804 Token::BIT_AND, xored_instance_types,
1578 // To do this, we check 1805 Add<HConstant>(static_cast<int32_t>(
1579 // 1. if both strings are one-byte, or if the one-byte data hint is set in 1806 kOneByteStringTag | kOneByteDataHintTag))),
1580 // both strings, or 1807 Add<HConstant>(static_cast<int32_t>(
1581 // 2. if one of the strings has the one-byte data hint set and the other 1808 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
1582 // string is one-byte. 1809 if_onebyte.Then();
1810 {
1811 // We can safely skip the write barrier for storing the map here.
1812 Handle<Map> map = isolate()->factory()->cons_ascii_string_map();
1813 AddStoreMapConstantNoWriteBarrier(string, map);
1814 }
1815 if_onebyte.Else();
1816 {
1817 // We can safely skip the write barrier for storing the map here.
1818 Handle<Map> map = isolate()->factory()->cons_string_map();
1819 AddStoreMapConstantNoWriteBarrier(string, map);
1820 }
1821 if_onebyte.End();
1822
1823 // Initialize the cons string fields.
1824 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(),
1825 Add<HConstant>(String::kEmptyHashField));
1826 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), length);
1827 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left);
1828 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(),
1829 right);
1830
1831 // Count the native string addition.
1832 AddIncrementCounter(isolate()->counters()->string_add_native());
1833
1834 // Cons string is result.
1835 Push(string);
1836 }
1837 if_createcons.Else();
1838 {
1839 // Compute union of instance types.
1840 HValue* ored_instance_types = AddUncasted<HBitwise>(
1841 Token::BIT_OR, left_instance_type, right_instance_type);
1842
1843 // Check if both strings have the same encoding and both are
1844 // sequential.
1845 IfBuilder if_sameencodingandsequential(this);
1846 if_sameencodingandsequential.If<HCompareNumericAndBranch>(
1847 AddUncasted<HBitwise>(
1848 Token::BIT_AND, xored_instance_types,
1849 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
1850 graph()->GetConstant0(), Token::EQ);
1851 if_sameencodingandsequential.And();
1852 STATIC_ASSERT(kSeqStringTag == 0);
1853 if_sameencodingandsequential.If<HCompareNumericAndBranch>(
1854 AddUncasted<HBitwise>(
1855 Token::BIT_AND, ored_instance_types,
1856 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
1857 graph()->GetConstant0(), Token::EQ);
1858 if_sameencodingandsequential.Then();
1859 {
1860 // Check if the result is a one-byte string.
1583 IfBuilder if_onebyte(this); 1861 IfBuilder if_onebyte(this);
1584 STATIC_ASSERT(kOneByteStringTag != 0); 1862 STATIC_ASSERT(kOneByteStringTag != 0);
1585 STATIC_ASSERT(kOneByteDataHintMask != 0);
1586 if_onebyte.If<HCompareNumericAndBranch>( 1863 if_onebyte.If<HCompareNumericAndBranch>(
1587 Add<HBitwise>( 1864 AddUncasted<HBitwise>(
1588 Token::BIT_AND, anded_instance_types, 1865 Token::BIT_AND, ored_instance_types,
1589 Add<HConstant>(static_cast<int32_t>( 1866 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
1590 kStringEncodingMask | kOneByteDataHintMask))),
1591 graph()->GetConstant0(), Token::NE); 1867 graph()->GetConstant0(), Token::NE);
1592 if_onebyte.Or();
1593 STATIC_ASSERT(kOneByteStringTag != 0 &&
1594 kOneByteDataHintTag != 0 &&
1595 kOneByteDataHintTag != kOneByteStringTag);
1596 if_onebyte.If<HCompareNumericAndBranch>(
1597 Add<HBitwise>(
1598 Token::BIT_AND, xored_instance_types,
1599 Add<HConstant>(static_cast<int32_t>(
1600 kOneByteStringTag | kOneByteDataHintTag))),
1601 Add<HConstant>(static_cast<int32_t>(
1602 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
1603 if_onebyte.Then(); 1868 if_onebyte.Then();
1604 { 1869 {
1605 // We can safely skip the write barrier for storing the map here. 1870 // Calculate the number of bytes needed for the characters in the
1606 Handle<Map> map = isolate()->factory()->cons_ascii_string_map(); 1871 // string while observing object alignment.
1872 HValue* size = BuildSeqStringSizeFor(
1873 length, String::ONE_BYTE_ENCODING);
1874
1875 // Allocate the ASCII string object.
1876 Handle<Map> map = isolate()->factory()->ascii_string_map();
1877 HAllocate* string = Add<HAllocate>(size, HType::String(),
1878 pretenure_flag, ASCII_STRING_TYPE);
1879 string->set_known_initial_map(map);
1880
1881 // We can safely skip the write barrier for storing map here.
1607 AddStoreMapConstantNoWriteBarrier(string, map); 1882 AddStoreMapConstantNoWriteBarrier(string, map);
1883
1884 // Length must be stored into the string before we copy characters to
1885 // make debug verification code happy.
1886 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
1887 length);
1888
1889 // Copy bytes from the left string.
1890 BuildCopySeqStringChars(
1891 left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1892 string, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1893 left_length);
1894
1895 // Copy bytes from the right string.
1896 BuildCopySeqStringChars(
1897 right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1898 string, left_length, String::ONE_BYTE_ENCODING,
1899 right_length);
1900
1901 // Count the native string addition.
1902 AddIncrementCounter(isolate()->counters()->string_add_native());
1903
1904 // Return the string.
1905 Push(string);
1608 } 1906 }
1609 if_onebyte.Else(); 1907 if_onebyte.Else();
1610 { 1908 {
1611 // We can safely skip the write barrier for storing the map here. 1909 // Calculate the number of bytes needed for the characters in the
1612 Handle<Map> map = isolate()->factory()->cons_string_map(); 1910 // string while observing object alignment.
1911 HValue* size = BuildSeqStringSizeFor(
1912 length, String::TWO_BYTE_ENCODING);
1913
1914 // Allocate the two-byte string object.
1915 Handle<Map> map = isolate()->factory()->string_map();
1916 HAllocate* string = Add<HAllocate>(size, HType::String(),
1917 pretenure_flag, STRING_TYPE);
1918 string->set_known_initial_map(map);
1919
1920 // We can safely skip the write barrier for storing map here.
1613 AddStoreMapConstantNoWriteBarrier(string, map); 1921 AddStoreMapConstantNoWriteBarrier(string, map);
1922
1923 // Length must be stored into the string before we copy characters to
1924 // make debug verification code happy.
1925 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
1926 length);
1927
1928 // Copy bytes from the left string.
1929 BuildCopySeqStringChars(
1930 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1931 string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1932 left_length);
1933
1934 // Copy bytes from the right string.
1935 BuildCopySeqStringChars(
1936 right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1937 string, left_length, String::TWO_BYTE_ENCODING,
1938 right_length);
1939
1940 // Return the string.
1941 Push(string);
1614 } 1942 }
1615 if_onebyte.End(); 1943 if_onebyte.End();
1616 1944
1617 // Initialize the cons string fields. 1945 // Initialize the (common) string fields.
1946 HValue* string = Pop();
1618 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(), 1947 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(),
1619 Add<HConstant>(String::kEmptyHashField)); 1948 Add<HConstant>(String::kEmptyHashField));
1620 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), length); 1949
1621 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left); 1950 // Count the native string addition.
1622 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(), 1951 AddIncrementCounter(isolate()->counters()->string_add_native());
1623 right); 1952
1624
1625 // Cons string is result.
1626 Push(string); 1953 Push(string);
1627 } 1954 }
1628 if_createcons.Else(); 1955 if_sameencodingandsequential.Else();
1629 { 1956 {
1630 // Compute union of instance types. 1957 // Fallback to the runtime to add the two strings.
1631 HValue* ored_instance_types = Add<HBitwise>( 1958 Add<HPushArgument>(left);
1632 Token::BIT_OR, left_instance_type, right_instance_type); 1959 Add<HPushArgument>(right);
1633 1960 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
1634 // Check if both strings have the same encoding and both are 1961 Runtime::FunctionForId(Runtime::kStringAdd),
1635 // sequential. 1962 2));
1636 IfBuilder if_sameencodingandsequential(this); 1963 }
1637 if_sameencodingandsequential.If<HCompareNumericAndBranch>( 1964 if_sameencodingandsequential.End();
1638 Add<HBitwise>(
1639 Token::BIT_AND, xored_instance_types,
1640 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
1641 graph()->GetConstant0(), Token::EQ);
1642 if_sameencodingandsequential.And();
1643 STATIC_ASSERT(kSeqStringTag == 0);
1644 if_sameencodingandsequential.If<HCompareNumericAndBranch>(
1645 Add<HBitwise>(
1646 Token::BIT_AND, ored_instance_types,
1647 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
1648 graph()->GetConstant0(), Token::EQ);
1649 if_sameencodingandsequential.Then();
1650 {
1651 // Check if the result is a one-byte string.
1652 IfBuilder if_onebyte(this);
1653 STATIC_ASSERT(kOneByteStringTag != 0);
1654 if_onebyte.If<HCompareNumericAndBranch>(
1655 Add<HBitwise>(
1656 Token::BIT_AND, ored_instance_types,
1657 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
1658 graph()->GetConstant0(), Token::NE);
1659 if_onebyte.Then();
1660 {
1661 // Calculate the number of bytes needed for the characters in the
1662 // string while observing object alignment.
1663 HValue* size = BuildSeqStringSizeFor(
1664 length, String::ONE_BYTE_ENCODING);
1665
1666 // Allocate the ASCII string object.
1667 Handle<Map> map = isolate()->factory()->ascii_string_map();
1668 HAllocate* string = Add<HAllocate>(size, HType::String(),
1669 pretenure_flag, ASCII_STRING_TYPE);
1670 string->set_known_initial_map(map);
1671
1672 // We can safely skip the write barrier for storing map here.
1673 AddStoreMapConstantNoWriteBarrier(string, map);
1674
1675 // Copy bytes from the left string.
1676 BuildCopySeqStringChars(
1677 left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1678 string, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1679 left_length);
1680
1681 // Copy bytes from the right string.
1682 BuildCopySeqStringChars(
1683 right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1684 string, left_length, String::ONE_BYTE_ENCODING,
1685 right_length);
1686
1687 // Return the string.
1688 Push(string);
1689 }
1690 if_onebyte.Else();
1691 {
1692 // Calculate the number of bytes needed for the characters in the
1693 // string while observing object alignment.
1694 HValue* size = BuildSeqStringSizeFor(
1695 length, String::TWO_BYTE_ENCODING);
1696
1697 // Allocate the two-byte string object.
1698 Handle<Map> map = isolate()->factory()->string_map();
1699 HAllocate* string = Add<HAllocate>(size, HType::String(),
1700 pretenure_flag, STRING_TYPE);
1701 string->set_known_initial_map(map);
1702
1703 // We can safely skip the write barrier for storing map here.
1704 AddStoreMapConstantNoWriteBarrier(string, map);
1705
1706 // Copy bytes from the left string.
1707 BuildCopySeqStringChars(
1708 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1709 string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1710 left_length);
1711
1712 // Copy bytes from the right string.
1713 BuildCopySeqStringChars(
1714 right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1715 string, left_length, String::TWO_BYTE_ENCODING,
1716 right_length);
1717
1718 // Return the string.
1719 Push(string);
1720 }
1721 if_onebyte.End();
1722
1723 // Initialize the (common) string fields.
1724 HValue* string = Pop();
1725 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(),
1726 Add<HConstant>(String::kEmptyHashField));
1727 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
1728 length);
1729 Push(string);
1730 }
1731 if_sameencodingandsequential.JoinContinuation(&handled);
1732 }
1733 if_createcons.JoinContinuation(&handled);
1734 } 1965 }
1735 if_nooverflow.JoinContinuation(&handled); 1966 if_createcons.End();
1736
1737 // Check if the strings were concatenated successfully, otherwise fallback to
1738 // add the strings in the runtime.
1739 IfBuilder if_handled(this, &handled);
1740 if_handled.Then();
1741 {
1742 // Count the native string addition.
1743 AddIncrementCounter(isolate()->counters()->string_add_native());
1744 }
1745 if_handled.Else();
1746 {
1747 // Fallback to the runtime to add the two strings.
1748 Add<HPushArgument>(left);
1749 Add<HPushArgument>(right);
1750 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
1751 Runtime::FunctionForId(Runtime::kStringAdd),
1752 2));
1753 }
1754 if_handled.End();
1755 1967
1756 return Pop(); 1968 return Pop();
1757 } 1969 }
1758 1970
1759 1971
1760 HValue* HGraphBuilder::BuildStringAdd(HValue* left, 1972 HValue* HGraphBuilder::BuildStringAdd(HValue* left,
1761 HValue* right, 1973 HValue* right,
1762 PretenureFlag pretenure_flag) { 1974 PretenureFlag pretenure_flag) {
1763 // Determine the string lengths. 1975 // Determine the string lengths.
1764 HValue* left_length = Add<HLoadNamedField>( 1976 HValue* left_length = Add<HLoadNamedField>(
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1852 IfBuilder length_checker(this); 2064 IfBuilder length_checker(this);
1853 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); 2065 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
1854 length_checker.Then(); 2066 length_checker.Then();
1855 IfBuilder negative_checker(this); 2067 IfBuilder negative_checker(this);
1856 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( 2068 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
1857 key, graph()->GetConstant0(), Token::GTE); 2069 key, graph()->GetConstant0(), Token::GTE);
1858 negative_checker.Then(); 2070 negative_checker.Then();
1859 HInstruction* result = AddElementAccess( 2071 HInstruction* result = AddElementAccess(
1860 external_elements, key, val, bounds_check, elements_kind, is_store); 2072 external_elements, key, val, bounds_check, elements_kind, is_store);
1861 negative_checker.ElseDeopt("Negative key encountered"); 2073 negative_checker.ElseDeopt("Negative key encountered");
2074 negative_checker.End();
1862 length_checker.End(); 2075 length_checker.End();
1863 return result; 2076 return result;
1864 } else { 2077 } else {
1865 ASSERT(store_mode == STANDARD_STORE); 2078 ASSERT(store_mode == STANDARD_STORE);
1866 checked_key = Add<HBoundsCheck>(key, length); 2079 checked_key = Add<HBoundsCheck>(key, length);
1867 HLoadExternalArrayPointer* external_elements = 2080 HLoadExternalArrayPointer* external_elements =
1868 Add<HLoadExternalArrayPointer>(elements); 2081 Add<HLoadExternalArrayPointer>(elements);
1869 return AddElementAccess( 2082 return AddElementAccess(
1870 external_elements, checked_key, val, 2083 external_elements, checked_key, val,
1871 checked_object, elements_kind, is_store); 2084 checked_object, elements_kind, is_store);
1872 } 2085 }
1873 } 2086 }
1874 ASSERT(fast_smi_only_elements || 2087 ASSERT(fast_smi_only_elements ||
1875 fast_elements || 2088 fast_elements ||
1876 IsFastDoubleElementsKind(elements_kind)); 2089 IsFastDoubleElementsKind(elements_kind));
1877 2090
1878 // In case val is stored into a fast smi array, assure that the value is a smi 2091 // In case val is stored into a fast smi array, assure that the value is a smi
1879 // before manipulating the backing store. Otherwise the actual store may 2092 // before manipulating the backing store. Otherwise the actual store may
1880 // deopt, leaving the backing store in an invalid state. 2093 // deopt, leaving the backing store in an invalid state.
1881 if (is_store && IsFastSmiElementsKind(elements_kind) && 2094 if (is_store && IsFastSmiElementsKind(elements_kind) &&
1882 !val->type().IsSmi()) { 2095 !val->type().IsSmi()) {
1883 val = Add<HForceRepresentation>(val, Representation::Smi()); 2096 val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
1884 } 2097 }
1885 2098
1886 if (IsGrowStoreMode(store_mode)) { 2099 if (IsGrowStoreMode(store_mode)) {
1887 NoObservableSideEffectsScope no_effects(this); 2100 NoObservableSideEffectsScope no_effects(this);
1888 elements = BuildCheckForCapacityGrow(checked_object, elements, 2101 elements = BuildCheckForCapacityGrow(checked_object, elements,
1889 elements_kind, length, key, 2102 elements_kind, length, key,
1890 is_js_array); 2103 is_js_array);
1891 checked_key = key; 2104 checked_key = key;
1892 } else { 2105 } else {
1893 checked_key = Add<HBoundsCheck>(key, length); 2106 checked_key = Add<HBoundsCheck>(key, length);
1894 2107
1895 if (is_store && (fast_elements || fast_smi_only_elements)) { 2108 if (is_store && (fast_elements || fast_smi_only_elements)) {
1896 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { 2109 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
1897 NoObservableSideEffectsScope no_effects(this); 2110 NoObservableSideEffectsScope no_effects(this);
1898 elements = BuildCopyElementsOnWrite(checked_object, elements, 2111 elements = BuildCopyElementsOnWrite(checked_object, elements,
1899 elements_kind, length); 2112 elements_kind, length);
1900 } else { 2113 } else {
1901 HCheckMaps* check_cow_map = Add<HCheckMaps>( 2114 HCheckMaps* check_cow_map = Add<HCheckMaps>(
1902 elements, isolate()->factory()->fixed_array_map(), top_info()); 2115 elements, isolate()->factory()->fixed_array_map(), top_info());
1903 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 2116 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1904 } 2117 }
1905 } 2118 }
1906 } 2119 }
1907 return AddElementAccess(elements, checked_key, val, checked_object, 2120 return AddElementAccess(elements, checked_key, val, checked_object,
1908 elements_kind, is_store, load_mode); 2121 elements_kind, is_store, load_mode);
1909 } 2122 }
1910 2123
1911 2124
2125
2126 HValue* HGraphBuilder::BuildAllocateArrayFromLength(
2127 JSArrayBuilder* array_builder,
2128 HValue* length_argument) {
2129 if (length_argument->IsConstant() &&
2130 HConstant::cast(length_argument)->HasSmiValue()) {
2131 int array_length = HConstant::cast(length_argument)->Integer32Value();
2132 HValue* new_object = array_length == 0
2133 ? array_builder->AllocateEmptyArray()
2134 : array_builder->AllocateArray(length_argument, length_argument);
2135 return new_object;
2136 }
2137
2138 HValue* constant_zero = graph()->GetConstant0();
2139 HConstant* max_alloc_length =
2140 Add<HConstant>(JSObject::kInitialMaxFastElementArray);
2141 HInstruction* checked_length = Add<HBoundsCheck>(length_argument,
2142 max_alloc_length);
2143 IfBuilder if_builder(this);
2144 if_builder.If<HCompareNumericAndBranch>(checked_length, constant_zero,
2145 Token::EQ);
2146 if_builder.Then();
2147 const int initial_capacity = JSArray::kPreallocatedArrayElements;
2148 HConstant* initial_capacity_node = Add<HConstant>(initial_capacity);
2149 Push(initial_capacity_node); // capacity
2150 Push(constant_zero); // length
2151 if_builder.Else();
2152 if (!(top_info()->IsStub()) &&
2153 IsFastPackedElementsKind(array_builder->kind())) {
2154 // We'll come back later with better (holey) feedback.
2155 if_builder.Deopt("Holey array despite packed elements_kind feedback");
2156 } else {
2157 Push(checked_length); // capacity
2158 Push(checked_length); // length
2159 }
2160 if_builder.End();
2161
2162 // Figure out total size
2163 HValue* length = Pop();
2164 HValue* capacity = Pop();
2165 return array_builder->AllocateArray(capacity, length);
2166 }
2167
1912 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, 2168 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
1913 HValue* capacity) { 2169 HValue* capacity) {
1914 int elements_size; 2170 int elements_size;
1915 InstanceType instance_type; 2171 InstanceType instance_type;
1916 2172
1917 if (IsFastDoubleElementsKind(kind)) { 2173 if (IsFastDoubleElementsKind(kind)) {
1918 elements_size = kDoubleSize; 2174 elements_size = kDoubleSize;
1919 instance_type = FIXED_DOUBLE_ARRAY_TYPE; 2175 instance_type = FIXED_DOUBLE_ARRAY_TYPE;
1920 } else { 2176 } else {
1921 elements_size = kPointerSize; 2177 elements_size = kPointerSize;
1922 instance_type = FIXED_ARRAY_TYPE; 2178 instance_type = FIXED_ARRAY_TYPE;
1923 } 2179 }
1924 2180
1925 HConstant* elements_size_value = Add<HConstant>(elements_size); 2181 HConstant* elements_size_value = Add<HConstant>(elements_size);
1926 HValue* mul = Add<HMul>(capacity, elements_size_value); 2182 HValue* mul = AddUncasted<HMul>(capacity, elements_size_value);
1927 mul->ClearFlag(HValue::kCanOverflow); 2183 mul->ClearFlag(HValue::kCanOverflow);
1928 2184
1929 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize); 2185 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
1930 HValue* total_size = Add<HAdd>(mul, header_size); 2186 HValue* total_size = AddUncasted<HAdd>(mul, header_size);
1931 total_size->ClearFlag(HValue::kCanOverflow); 2187 total_size->ClearFlag(HValue::kCanOverflow);
1932 2188
1933 return Add<HAllocate>(total_size, HType::JSArray(), 2189 return Add<HAllocate>(total_size, HType::JSArray(),
1934 isolate()->heap()->GetPretenureMode(), instance_type); 2190 isolate()->heap()->GetPretenureMode(), instance_type);
1935 } 2191 }
1936 2192
1937 2193
1938 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, 2194 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
1939 ElementsKind kind, 2195 ElementsKind kind,
1940 HValue* capacity) { 2196 HValue* capacity) {
1941 Factory* factory = isolate()->factory(); 2197 Factory* factory = isolate()->factory();
1942 Handle<Map> map = IsFastDoubleElementsKind(kind) 2198 Handle<Map> map = IsFastDoubleElementsKind(kind)
1943 ? factory->fixed_double_array_map() 2199 ? factory->fixed_double_array_map()
1944 : factory->fixed_array_map(); 2200 : factory->fixed_array_map();
1945 2201
1946 AddStoreMapConstant(elements, map); 2202 AddStoreMapConstant(elements, map);
1947 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(), 2203 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
1948 capacity); 2204 capacity);
1949 } 2205 }
1950 2206
1951 2207
1952 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( 2208 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader(
1953 ElementsKind kind, 2209 ElementsKind kind,
1954 HValue* capacity) { 2210 HValue* capacity) {
1955 // The HForceRepresentation is to prevent possible deopt on int-smi 2211 // The HForceRepresentation is to prevent possible deopt on int-smi
1956 // conversion after allocation but before the new object fields are set. 2212 // conversion after allocation but before the new object fields are set.
1957 capacity = Add<HForceRepresentation>(capacity, Representation::Smi()); 2213 capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
1958 HValue* new_elements = BuildAllocateElements(kind, capacity); 2214 HValue* new_elements = BuildAllocateElements(kind, capacity);
1959 BuildInitializeElementsHeader(new_elements, kind, capacity); 2215 BuildInitializeElementsHeader(new_elements, kind, capacity);
1960 return new_elements; 2216 return new_elements;
1961 } 2217 }
1962 2218
1963 2219
1964 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, 2220 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array,
1965 HValue* array_map, 2221 HValue* array_map,
1966 AllocationSiteMode mode, 2222 AllocationSiteMode mode,
1967 ElementsKind elements_kind, 2223 ElementsKind elements_kind,
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
2090 // Fast elements kinds need to be initialized in case statements below cause 2346 // Fast elements kinds need to be initialized in case statements below cause
2091 // a garbage collection. 2347 // a garbage collection.
2092 Factory* factory = isolate()->factory(); 2348 Factory* factory = isolate()->factory();
2093 2349
2094 double nan_double = FixedDoubleArray::hole_nan_as_double(); 2350 double nan_double = FixedDoubleArray::hole_nan_as_double();
2095 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) 2351 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
2096 ? Add<HConstant>(factory->the_hole_value()) 2352 ? Add<HConstant>(factory->the_hole_value())
2097 : Add<HConstant>(nan_double); 2353 : Add<HConstant>(nan_double);
2098 2354
2099 // Special loop unfolding case 2355 // Special loop unfolding case
2100 static const int kLoopUnfoldLimit = 4; 2356 static const int kLoopUnfoldLimit = 8;
2101 bool unfold_loop = false; 2357 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit);
2102 int initial_capacity = JSArray::kPreallocatedArrayElements; 2358 int initial_capacity = -1;
2103 if (from->IsConstant() && to->IsConstant() && 2359 if (from->IsInteger32Constant() && to->IsInteger32Constant()) {
2104 initial_capacity <= kLoopUnfoldLimit) { 2360 int constant_from = from->GetInteger32Constant();
2105 HConstant* constant_from = HConstant::cast(from); 2361 int constant_to = to->GetInteger32Constant();
2106 HConstant* constant_to = HConstant::cast(to);
2107 2362
2108 if (constant_from->HasInteger32Value() && 2363 if (constant_from == 0 && constant_to <= kLoopUnfoldLimit) {
2109 constant_from->Integer32Value() == 0 && 2364 initial_capacity = constant_to;
2110 constant_to->HasInteger32Value() &&
2111 constant_to->Integer32Value() == initial_capacity) {
2112 unfold_loop = true;
2113 } 2365 }
2114 } 2366 }
2115 2367
2116 // Since we're about to store a hole value, the store instruction below must 2368 // Since we're about to store a hole value, the store instruction below must
2117 // assume an elements kind that supports heap object values. 2369 // assume an elements kind that supports heap object values.
2118 if (IsFastSmiOrObjectElementsKind(elements_kind)) { 2370 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
2119 elements_kind = FAST_HOLEY_ELEMENTS; 2371 elements_kind = FAST_HOLEY_ELEMENTS;
2120 } 2372 }
2121 2373
2122 if (unfold_loop) { 2374 if (initial_capacity >= 0) {
2123 for (int i = 0; i < initial_capacity; i++) { 2375 for (int i = 0; i < initial_capacity; i++) {
2124 HInstruction* key = Add<HConstant>(i); 2376 HInstruction* key = Add<HConstant>(i);
2125 Add<HStoreKeyed>(elements, key, hole, elements_kind); 2377 Add<HStoreKeyed>(elements, key, hole, elements_kind);
2126 } 2378 }
2127 } else { 2379 } else {
2128 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); 2380 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
2129 2381
2130 HValue* key = builder.BeginBody(from, to, Token::LT); 2382 HValue* key = builder.BeginBody(from, to, Token::LT);
2131 2383
2132 Add<HStoreKeyed>(elements, key, hole, elements_kind); 2384 Add<HStoreKeyed>(elements, key, hole, elements_kind);
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
2371 HValue* constructor_function) : 2623 HValue* constructor_function) :
2372 builder_(builder), 2624 builder_(builder),
2373 kind_(kind), 2625 kind_(kind),
2374 mode_(DONT_TRACK_ALLOCATION_SITE), 2626 mode_(DONT_TRACK_ALLOCATION_SITE),
2375 allocation_site_payload_(NULL), 2627 allocation_site_payload_(NULL),
2376 constructor_function_(constructor_function) { 2628 constructor_function_(constructor_function) {
2377 } 2629 }
2378 2630
2379 2631
2380 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { 2632 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
2381 if (kind_ == GetInitialFastElementsKind()) { 2633 if (!builder()->top_info()->IsStub()) {
2634 // A constant map is fine.
2635 Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_),
2636 builder()->isolate());
2637 return builder()->Add<HConstant>(map);
2638 }
2639
2640 if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) {
2382 // No need for a context lookup if the kind_ matches the initial 2641 // No need for a context lookup if the kind_ matches the initial
2383 // map, because we can just load the map in that case. 2642 // map, because we can just load the map in that case.
2384 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 2643 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
2385 return builder()->AddLoadNamedField(constructor_function_, access); 2644 return builder()->AddLoadNamedField(constructor_function_, access);
2386 } 2645 }
2387 2646
2388 HInstruction* native_context = builder()->BuildGetNativeContext(); 2647 HInstruction* native_context = builder()->BuildGetNativeContext();
2389 HInstruction* index = builder()->Add<HConstant>( 2648 HInstruction* index = builder()->Add<HConstant>(
2390 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); 2649 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
2391 2650
(...skipping 21 matching lines...) Expand all
2413 int base_size = JSArray::kSize; 2672 int base_size = JSArray::kSize;
2414 if (mode_ == TRACK_ALLOCATION_SITE) { 2673 if (mode_ == TRACK_ALLOCATION_SITE) {
2415 base_size += AllocationMemento::kSize; 2674 base_size += AllocationMemento::kSize;
2416 } 2675 }
2417 2676
2418 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); 2677 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
2419 base_size += FixedArray::kHeaderSize; 2678 base_size += FixedArray::kHeaderSize;
2420 2679
2421 HInstruction* elements_size_value = 2680 HInstruction* elements_size_value =
2422 builder()->Add<HConstant>(elements_size()); 2681 builder()->Add<HConstant>(elements_size());
2423 HInstruction* mul = builder()->Add<HMul>(length_node, elements_size_value); 2682 HInstruction* mul = HMul::NewImul(builder()->zone(), builder()->context(),
2424 mul->ClearFlag(HValue::kCanOverflow); 2683 length_node, elements_size_value);
2425 2684 builder()->AddInstruction(mul);
2426 HInstruction* base = builder()->Add<HConstant>(base_size); 2685 HInstruction* base = builder()->Add<HConstant>(base_size);
2427 HInstruction* total_size = builder()->Add<HAdd>(base, mul); 2686 HInstruction* total_size = HAdd::New(builder()->zone(), builder()->context(),
2687 base, mul);
2428 total_size->ClearFlag(HValue::kCanOverflow); 2688 total_size->ClearFlag(HValue::kCanOverflow);
2689 builder()->AddInstruction(total_size);
2429 return total_size; 2690 return total_size;
2430 } 2691 }
2431 2692
2432 2693
2433 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { 2694 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() {
2434 int base_size = JSArray::kSize; 2695 int base_size = JSArray::kSize;
2435 if (mode_ == TRACK_ALLOCATION_SITE) { 2696 if (mode_ == TRACK_ALLOCATION_SITE) {
2436 base_size += AllocationMemento::kSize; 2697 base_size += AllocationMemento::kSize;
2437 } 2698 }
2438 2699
2439 base_size += IsFastDoubleElementsKind(kind_) 2700 base_size += IsFastDoubleElementsKind(kind_)
2440 ? FixedDoubleArray::SizeFor(initial_capacity()) 2701 ? FixedDoubleArray::SizeFor(initial_capacity())
2441 : FixedArray::SizeFor(initial_capacity()); 2702 : FixedArray::SizeFor(initial_capacity());
2442 2703
2443 return builder()->Add<HConstant>(base_size); 2704 return builder()->Add<HConstant>(base_size);
2444 } 2705 }
2445 2706
2446 2707
2447 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { 2708 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() {
2448 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); 2709 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize();
2449 HConstant* capacity = builder()->Add<HConstant>(initial_capacity()); 2710 HConstant* capacity = builder()->Add<HConstant>(initial_capacity());
2450 return AllocateArray(size_in_bytes, 2711 return AllocateArray(size_in_bytes,
2451 capacity, 2712 capacity,
2452 builder()->graph()->GetConstant0(), 2713 builder()->graph()->GetConstant0());
2453 true);
2454 } 2714 }
2455 2715
2456 2716
2457 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, 2717 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity,
2458 HValue* length_field, 2718 HValue* length_field,
2459 bool fill_with_hole) { 2719 FillMode fill_mode) {
2460 HValue* size_in_bytes = EstablishAllocationSize(capacity); 2720 HValue* size_in_bytes = EstablishAllocationSize(capacity);
2461 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); 2721 return AllocateArray(size_in_bytes, capacity, length_field, fill_mode);
2462 } 2722 }
2463 2723
2464 2724
2465 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, 2725 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
2466 HValue* capacity, 2726 HValue* capacity,
2467 HValue* length_field, 2727 HValue* length_field,
2468 bool fill_with_hole) { 2728 FillMode fill_mode) {
2469 // These HForceRepresentations are because we store these as fields in the 2729 // These HForceRepresentations are because we store these as fields in the
2470 // objects we construct, and an int32-to-smi HChange could deopt. Accept 2730 // objects we construct, and an int32-to-smi HChange could deopt. Accept
2471 // the deopt possibility now, before allocation occurs. 2731 // the deopt possibility now, before allocation occurs.
2472 capacity = builder()->Add<HForceRepresentation>(capacity, 2732 capacity =
2473 Representation::Smi()); 2733 builder()->AddUncasted<HForceRepresentation>(capacity,
2474 length_field = builder()->Add<HForceRepresentation>(length_field, 2734 Representation::Smi());
2475 Representation::Smi()); 2735 length_field =
2736 builder()->AddUncasted<HForceRepresentation>(length_field,
2737 Representation::Smi());
2476 // Allocate (dealing with failure appropriately) 2738 // Allocate (dealing with failure appropriately)
2477 HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes, 2739 HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes,
2478 HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE); 2740 HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE);
2479 2741
2480 // Folded array allocation should be aligned if it has fast double elements. 2742 // Folded array allocation should be aligned if it has fast double elements.
2481 if (IsFastDoubleElementsKind(kind_)) { 2743 if (IsFastDoubleElementsKind(kind_)) {
2482 new_object->MakeDoubleAligned(); 2744 new_object->MakeDoubleAligned();
2483 } 2745 }
2484 2746
2485 // Fill in the fields: map, properties, length 2747 // Fill in the fields: map, properties, length
2486 HValue* map; 2748 HValue* map;
2487 if (allocation_site_payload_ == NULL) { 2749 if (allocation_site_payload_ == NULL) {
2488 map = EmitInternalMapCode(); 2750 map = EmitInternalMapCode();
2489 } else { 2751 } else {
2490 map = EmitMapCode(); 2752 map = EmitMapCode();
2491 } 2753 }
2492 elements_location_ = builder()->BuildJSArrayHeader(new_object, 2754 elements_location_ = builder()->BuildJSArrayHeader(new_object,
2493 map, 2755 map,
2494 mode_, 2756 mode_,
2495 kind_, 2757 kind_,
2496 allocation_site_payload_, 2758 allocation_site_payload_,
2497 length_field); 2759 length_field);
2498 2760
2499 // Initialize the elements 2761 // Initialize the elements
2500 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); 2762 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
2501 2763
2502 if (fill_with_hole) { 2764 if (fill_mode == FILL_WITH_HOLE) {
2503 builder()->BuildFillElementsWithHole(elements_location_, kind_, 2765 builder()->BuildFillElementsWithHole(elements_location_, kind_,
2504 graph()->GetConstant0(), capacity); 2766 graph()->GetConstant0(), capacity);
2505 } 2767 }
2506 2768
2507 return new_object; 2769 return new_object;
2508 } 2770 }
2509 2771
2510 2772
2511 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, 2773 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object,
2512 Handle<Map> map) { 2774 Handle<Map> map) {
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
2652 2914
2653 HBasicBlock* HGraph::CreateBasicBlock() { 2915 HBasicBlock* HGraph::CreateBasicBlock() {
2654 HBasicBlock* result = new(zone()) HBasicBlock(this); 2916 HBasicBlock* result = new(zone()) HBasicBlock(this);
2655 blocks_.Add(result, zone()); 2917 blocks_.Add(result, zone());
2656 return result; 2918 return result;
2657 } 2919 }
2658 2920
2659 2921
2660 void HGraph::FinalizeUniqueness() { 2922 void HGraph::FinalizeUniqueness() {
2661 DisallowHeapAllocation no_gc; 2923 DisallowHeapAllocation no_gc;
2662 ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread()); 2924 ASSERT(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
2663 for (int i = 0; i < blocks()->length(); ++i) { 2925 for (int i = 0; i < blocks()->length(); ++i) {
2664 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) { 2926 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
2665 it.Current()->FinalizeUniqueness(); 2927 it.Current()->FinalizeUniqueness();
2666 } 2928 }
2667 } 2929 }
2668 } 2930 }
2669 2931
2670 2932
2671 // Block ordering was implemented with two mutually recursive methods, 2933 // Block ordering was implemented with two mutually recursive methods,
2672 // HGraph::Postorder and HGraph::PostorderLoopBlocks. 2934 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
(...skipping 1569 matching lines...) Expand 10 before | Expand all | Expand 10 after
4242 BreakAndContinueInfo break_info(stmt, 5); 4504 BreakAndContinueInfo break_info(stmt, 5);
4243 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); 4505 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
4244 4506
4245 HBasicBlock* body_exit = 4507 HBasicBlock* body_exit =
4246 JoinContinue(stmt, current_block(), break_info.continue_block()); 4508 JoinContinue(stmt, current_block(), break_info.continue_block());
4247 4509
4248 if (body_exit != NULL) { 4510 if (body_exit != NULL) {
4249 set_current_block(body_exit); 4511 set_current_block(body_exit);
4250 4512
4251 HValue* current_index = Pop(); 4513 HValue* current_index = Pop();
4252 Push(Add<HAdd>(current_index, graph()->GetConstant1())); 4514 Push(AddUncasted<HAdd>(current_index, graph()->GetConstant1()));
4253 body_exit = current_block(); 4515 body_exit = current_block();
4254 } 4516 }
4255 4517
4256 HBasicBlock* loop_exit = CreateLoop(stmt, 4518 HBasicBlock* loop_exit = CreateLoop(stmt,
4257 loop_entry, 4519 loop_entry,
4258 body_exit, 4520 body_exit,
4259 loop_successor, 4521 loop_successor,
4260 break_info.break_block()); 4522 break_info.break_block());
4261 4523
4262 set_current_block(loop_exit); 4524 set_current_block(loop_exit);
(...skipping 1409 matching lines...) Expand 10 before | Expand all | Expand 10 after
5672 CHECK_ALIVE(VisitForValue(prop->key())); 5934 CHECK_ALIVE(VisitForValue(prop->key()));
5673 key = Top(); 5935 key = Top();
5674 } 5936 }
5675 5937
5676 CHECK_ALIVE(PushLoad(prop, object, key)); 5938 CHECK_ALIVE(PushLoad(prop, object, key));
5677 5939
5678 CHECK_ALIVE(VisitForValue(expr->value())); 5940 CHECK_ALIVE(VisitForValue(expr->value()));
5679 HValue* right = Pop(); 5941 HValue* right = Pop();
5680 HValue* left = Pop(); 5942 HValue* left = Pop();
5681 5943
5682 HInstruction* instr = BuildBinaryOperation(operation, left, right); 5944 Push(BuildBinaryOperation(operation, left, right));
5683 AddInstruction(instr);
5684 Push(instr);
5685 if (instr->HasObservableSideEffects()) {
5686 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
5687 }
5688 BuildStore(expr, prop, expr->id(), 5945 BuildStore(expr, prop, expr->id(),
5689 expr->AssignmentId(), expr->IsUninitialized()); 5946 expr->AssignmentId(), expr->IsUninitialized());
5690 } else { 5947 } else {
5691 return Bailout(kInvalidLhsInCompoundAssignment); 5948 return Bailout(kInvalidLhsInCompoundAssignment);
5692 } 5949 }
5693 } 5950 }
5694 5951
5695 5952
5696 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { 5953 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
5697 ASSERT(!HasStackOverflow()); 5954 ASSERT(!HasStackOverflow());
(...skipping 1513 matching lines...) Expand 10 before | Expand all | Expand 10 after
7211 } 7468 }
7212 } 7469 }
7213 7470
7214 if (result == NULL) { 7471 if (result == NULL) {
7215 result = NewUncasted<HPower>(left, right); 7472 result = NewUncasted<HPower>(left, right);
7216 } 7473 }
7217 ast_context()->ReturnInstruction(result, expr->id()); 7474 ast_context()->ReturnInstruction(result, expr->id());
7218 return true; 7475 return true;
7219 } 7476 }
7220 break; 7477 break;
7221 case kMathRandom:
7222 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) {
7223 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7224 Drop(1); // Receiver.
7225 HGlobalObject* global_object = Add<HGlobalObject>();
7226 HRandom* result = New<HRandom>(global_object);
7227 ast_context()->ReturnInstruction(result, expr->id());
7228 return true;
7229 }
7230 break;
7231 case kMathMax: 7478 case kMathMax:
7232 case kMathMin: 7479 case kMathMin:
7233 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 7480 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
7234 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 7481 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7235 HValue* right = Pop(); 7482 HValue* right = Pop();
7236 HValue* left = Pop(); 7483 HValue* left = Pop();
7237 Drop(1); // Receiver. 7484 Drop(1); // Receiver.
7238 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin 7485 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
7239 : HMathMinMax::kMathMax; 7486 : HMathMinMax::kMathMax;
7240 HInstruction* result = NewUncasted<HMathMinMax>(left, right, op); 7487 HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
7348 ASSERT(current_block() != NULL); 7595 ASSERT(current_block() != NULL);
7349 ASSERT(current_block()->HasPredecessor()); 7596 ASSERT(current_block()->HasPredecessor());
7350 Expression* callee = expr->expression(); 7597 Expression* callee = expr->expression();
7351 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 7598 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
7352 HInstruction* call = NULL; 7599 HInstruction* call = NULL;
7353 7600
7354 Property* prop = callee->AsProperty(); 7601 Property* prop = callee->AsProperty();
7355 if (prop != NULL) { 7602 if (prop != NULL) {
7356 if (!prop->key()->IsPropertyName()) { 7603 if (!prop->key()->IsPropertyName()) {
7357 // Keyed function call. 7604 // Keyed function call.
7358 CHECK_ALIVE(VisitArgument(prop->obj())); 7605 CHECK_ALIVE(VisitForValue(prop->obj()));
7606 CHECK_ALIVE(VisitForValue(prop->key()));
7359 7607
7360 CHECK_ALIVE(VisitForValue(prop->key()));
7361 // 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.
7362 HValue* key = Pop(); 7609 HValue* key = Pop();
7363 HValue* receiver = Pop(); 7610 HValue* receiver = Pop();
7364 Push(key); 7611 Push(key);
7365 Push(receiver); 7612 Push(Add<HPushArgument>(receiver));
7366
7367 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 7613 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7368 7614
7369 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 }
7370 Drop(argument_count + 1); // 1 is the key. 7629 Drop(argument_count + 1); // 1 is the key.
7371 return ast_context()->ReturnInstruction(call, expr->id()); 7630 return ast_context()->ReturnInstruction(call, expr->id());
7372 } 7631 }
7373 7632
7374 // Named function call. 7633 // Named function call.
7375 if (TryCallApply(expr)) return; 7634 if (TryCallApply(expr)) return;
7376 7635
7377 CHECK_ALIVE(VisitForValue(prop->obj())); 7636 CHECK_ALIVE(VisitForValue(prop->obj()));
7378 CHECK_ALIVE(VisitExpressions(expr->arguments())); 7637 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7379 7638
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
7528 7787
7529 call = New<HCallFunction>(function, argument_count); 7788 call = New<HCallFunction>(function, argument_count);
7530 Drop(argument_count + 1); 7789 Drop(argument_count + 1);
7531 } 7790 }
7532 } 7791 }
7533 7792
7534 return ast_context()->ReturnInstruction(call, expr->id()); 7793 return ast_context()->ReturnInstruction(call, expr->id());
7535 } 7794 }
7536 7795
7537 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
7538 // Checks whether allocation using the given constructor can be inlined. 7862 // Checks whether allocation using the given constructor can be inlined.
7539 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { 7863 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
7540 return constructor->has_initial_map() && 7864 return constructor->has_initial_map() &&
7541 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && 7865 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
7542 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && 7866 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize &&
7543 constructor->initial_map()->InitialPropertiesLength() == 0; 7867 constructor->initial_map()->InitialPropertiesLength() == 0;
7544 } 7868 }
7545 7869
7546 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
7547 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { 7915 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
7548 ASSERT(!HasStackOverflow()); 7916 ASSERT(!HasStackOverflow());
7549 ASSERT(current_block() != NULL); 7917 ASSERT(current_block() != NULL);
7550 ASSERT(current_block()->HasPredecessor()); 7918 ASSERT(current_block()->HasPredecessor());
7551 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); 7919 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
7552 int argument_count = expr->arguments()->length() + 1; // Plus constructor. 7920 int argument_count = expr->arguments()->length() + 1; // Plus constructor.
7553 Factory* factory = isolate()->factory(); 7921 Factory* factory = isolate()->factory();
7554 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
7555 if (FLAG_inline_construct && 7929 if (FLAG_inline_construct &&
7556 expr->IsMonomorphic() && 7930 expr->IsMonomorphic() &&
7557 IsAllocationInlineable(expr->target())) { 7931 IsAllocationInlineable(expr->target())) {
7558 // The constructor function is on the stack in the unoptimized code
7559 // during evaluation of the arguments.
7560 CHECK_ALIVE(VisitForValue(expr->expression()));
7561 HValue* function = Top();
7562 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7563 Handle<JSFunction> constructor = expr->target(); 7932 Handle<JSFunction> constructor = expr->target();
7564 HValue* check = Add<HCheckValue>(function, constructor); 7933 HValue* check = Add<HCheckValue>(function, constructor);
7565 7934
7566 // Force completion of inobject slack tracking before generating 7935 // Force completion of inobject slack tracking before generating
7567 // allocation code to finalize instance size. 7936 // allocation code to finalize instance size.
7568 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { 7937 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) {
7569 constructor->shared()->CompleteInobjectSlackTracking(); 7938 constructor->shared()->CompleteInobjectSlackTracking();
7570 } 7939 }
7571 7940
7572 // 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
7639 check->DeleteAndReplaceWith(NULL); 8008 check->DeleteAndReplaceWith(NULL);
7640 environment()->SetExpressionStackAt(receiver_index, function); 8009 environment()->SetExpressionStackAt(receiver_index, function);
7641 HInstruction* call = 8010 HInstruction* call =
7642 PreProcessCall(New<HCallNew>(function, argument_count)); 8011 PreProcessCall(New<HCallNew>(function, argument_count));
7643 return ast_context()->ReturnInstruction(call, expr->id()); 8012 return ast_context()->ReturnInstruction(call, expr->id());
7644 } else { 8013 } else {
7645 // 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
7646 // argument to the construct call. 8015 // argument to the construct call.
7647 Handle<JSFunction> array_function( 8016 Handle<JSFunction> array_function(
7648 isolate()->global_context()->array_function(), isolate()); 8017 isolate()->global_context()->array_function(), isolate());
7649 CHECK_ALIVE(VisitArgument(expr->expression())); 8018 bool use_call_new_array = expr->target().is_identical_to(array_function);
7650 HValue* constructor = HPushArgument::cast(Top())->argument(); 8019 Handle<Cell> cell = expr->allocation_info_cell();
7651 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
7652 HBinaryCall* call; 8027 HBinaryCall* call;
7653 if (expr->target().is_identical_to(array_function)) { 8028 if (use_call_new_array) {
7654 Handle<Cell> cell = expr->allocation_info_cell(); 8029 Add<HCheckValue>(function, array_function);
7655 Add<HCheckValue>(constructor, array_function); 8030 call = New<HCallNewArray>(function, argument_count, cell,
7656 call = New<HCallNewArray>(constructor, argument_count, 8031 expr->elements_kind());
7657 cell, expr->elements_kind());
7658 } else { 8032 } else {
7659 call = New<HCallNew>(constructor, argument_count); 8033 call = New<HCallNew>(function, argument_count);
7660 } 8034 }
7661 Drop(argument_count); 8035 PreProcessCall(call);
7662 return ast_context()->ReturnInstruction(call, expr->id()); 8036 return ast_context()->ReturnInstruction(call, expr->id());
7663 } 8037 }
7664 } 8038 }
7665 8039
7666 8040
7667 // Support for generating inlined runtime functions. 8041 // Support for generating inlined runtime functions.
7668 8042
7669 // Lookup table for generators for runtime calls that are generated inline. 8043 // Lookup table for generators for runtime calls that are generated inline.
7670 // Elements of the table are member pointers to functions of 8044 // Elements of the table are member pointers to functions of
7671 // HOptimizedGraphBuilder. 8045 // HOptimizedGraphBuilder.
7672 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ 8046 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
7673 &HOptimizedGraphBuilder::Generate##Name, 8047 &HOptimizedGraphBuilder::Generate##Name,
7674 8048
7675 const HOptimizedGraphBuilder::InlineFunctionGenerator 8049 const HOptimizedGraphBuilder::InlineFunctionGenerator
7676 HOptimizedGraphBuilder::kInlineFunctionGenerators[] = { 8050 HOptimizedGraphBuilder::kInlineFunctionGenerators[] = {
7677 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 8051 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
7678 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 8052 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
7679 }; 8053 };
7680 #undef INLINE_FUNCTION_GENERATOR_ADDRESS 8054 #undef INLINE_FUNCTION_GENERATOR_ADDRESS
7681 8055
7682 8056
8057 void HOptimizedGraphBuilder::VisitDataViewInitialize(
8058 CallRuntime* expr) {
8059 ZoneList<Expression*>* arguments = expr->arguments();
8060
8061 NoObservableSideEffectsScope scope(this);
8062 ASSERT(arguments->length()== 4);
8063 CHECK_ALIVE(VisitForValue(arguments->at(0)));
8064 HValue* obj = Pop();
8065
8066 CHECK_ALIVE(VisitForValue(arguments->at(1)));
8067 HValue* buffer = Pop();
8068
8069 CHECK_ALIVE(VisitForValue(arguments->at(2)));
8070 HValue* byte_offset = Pop();
8071
8072 CHECK_ALIVE(VisitForValue(arguments->at(3)));
8073 HValue* byte_length = Pop();
8074
8075 for (int offset = JSDataView::kSize;
8076 offset < JSDataView::kSizeWithInternalFields;
8077 offset += kPointerSize) {
8078 Add<HStoreNamedField>(obj,
8079 HObjectAccess::ForJSObjectOffset(offset),
8080 Add<HConstant>(static_cast<int32_t>(0)));
8081 }
8082
8083 Add<HStoreNamedField>(obj,
8084 HObjectAccess::ForJSObjectOffset(JSDataView::kBufferOffset), buffer);
8085 Add<HStoreNamedField>(obj,
8086 HObjectAccess::ForJSObjectOffset(JSDataView::kByteOffsetOffset),
8087 byte_offset);
8088 Add<HStoreNamedField>(obj,
8089 HObjectAccess::ForJSObjectOffset(JSDataView::kByteLengthOffset),
8090 byte_length);
8091
8092 Add<HStoreNamedField>(obj,
8093 HObjectAccess::ForJSObjectOffset(JSDataView::kWeakNextOffset),
8094 Add<HLoadNamedField>(buffer,
8095 HObjectAccess::ForJSObjectOffset(
8096 JSArrayBuffer::kWeakFirstViewOffset)));
8097 Add<HStoreNamedField>(buffer,
8098 HObjectAccess::ForJSObjectOffset(JSArrayBuffer::kWeakFirstViewOffset),
8099 obj);
8100 }
8101
8102
7683 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { 8103 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
7684 ASSERT(!HasStackOverflow()); 8104 ASSERT(!HasStackOverflow());
7685 ASSERT(current_block() != NULL); 8105 ASSERT(current_block() != NULL);
7686 ASSERT(current_block()->HasPredecessor()); 8106 ASSERT(current_block()->HasPredecessor());
7687 if (expr->is_jsruntime()) { 8107 if (expr->is_jsruntime()) {
7688 return Bailout(kCallToAJavaScriptRuntimeFunction); 8108 return Bailout(kCallToAJavaScriptRuntimeFunction);
7689 } 8109 }
7690 8110
7691 const Runtime::Function* function = expr->function(); 8111 const Runtime::Function* function = expr->function();
7692 ASSERT(function != NULL); 8112 ASSERT(function != NULL);
8113
8114 if (function->function_id == Runtime::kDataViewInitialize) {
8115 return VisitDataViewInitialize(expr);
8116 }
8117
7693 if (function->intrinsic_type == Runtime::INLINE) { 8118 if (function->intrinsic_type == Runtime::INLINE) {
7694 ASSERT(expr->name()->length() > 0); 8119 ASSERT(expr->name()->length() > 0);
7695 ASSERT(expr->name()->Get(0) == '_'); 8120 ASSERT(expr->name()->Get(0) == '_');
7696 // Call to an inline function. 8121 // Call to an inline function.
7697 int lookup_index = static_cast<int>(function->function_id) - 8122 int lookup_index = static_cast<int>(function->function_id) -
7698 static_cast<int>(Runtime::kFirstInlineFunction); 8123 static_cast<int>(Runtime::kFirstInlineFunction);
7699 ASSERT(lookup_index >= 0); 8124 ASSERT(lookup_index >= 0);
7700 ASSERT(static_cast<size_t>(lookup_index) < 8125 ASSERT(static_cast<size_t>(lookup_index) <
7701 ARRAY_SIZE(kInlineFunctionGenerators)); 8126 ARRAY_SIZE(kInlineFunctionGenerators));
7702 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; 8127 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
7837 Representation rep = Representation::FromType(info); 8262 Representation rep = Representation::FromType(info);
7838 if (rep.IsNone() || rep.IsTagged()) { 8263 if (rep.IsNone() || rep.IsTagged()) {
7839 rep = Representation::Smi(); 8264 rep = Representation::Smi();
7840 } 8265 }
7841 8266
7842 if (returns_original_input) { 8267 if (returns_original_input) {
7843 // We need an explicit HValue representing ToNumber(input). The 8268 // We need an explicit HValue representing ToNumber(input). The
7844 // actual HChange instruction we need is (sometimes) added in a later 8269 // actual HChange instruction we need is (sometimes) added in a later
7845 // phase, so it is not available now to be used as an input to HAdd and 8270 // phase, so it is not available now to be used as an input to HAdd and
7846 // as the return value. 8271 // as the return value.
7847 HInstruction* number_input = Add<HForceRepresentation>(Pop(), rep); 8272 HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep);
7848 if (!rep.IsDouble()) { 8273 if (!rep.IsDouble()) {
7849 number_input->SetFlag(HInstruction::kFlexibleRepresentation); 8274 number_input->SetFlag(HInstruction::kFlexibleRepresentation);
7850 number_input->SetFlag(HInstruction::kCannotBeTagged); 8275 number_input->SetFlag(HInstruction::kCannotBeTagged);
7851 } 8276 }
7852 Push(number_input); 8277 Push(number_input);
7853 } 8278 }
7854 8279
7855 // The addition has no side effects, so we do not need 8280 // The addition has no side effects, so we do not need
7856 // to simulate the expression stack after this instruction. 8281 // to simulate the expression stack after this instruction.
7857 // Any later failures deopt to the load of the input or earlier. 8282 // Any later failures deopt to the load of the input or earlier.
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
8084 return false; 8509 return false;
8085 } 8510 }
8086 } 8511 }
8087 return true; 8512 return true;
8088 } 8513 }
8089 8514
8090 8515
8091 HValue* HGraphBuilder::EnforceNumberType(HValue* number, 8516 HValue* HGraphBuilder::EnforceNumberType(HValue* number,
8092 Handle<Type> expected) { 8517 Handle<Type> expected) {
8093 if (expected->Is(Type::Smi())) { 8518 if (expected->Is(Type::Smi())) {
8094 return Add<HForceRepresentation>(number, Representation::Smi()); 8519 return AddUncasted<HForceRepresentation>(number, Representation::Smi());
8095 } 8520 }
8096 if (expected->Is(Type::Signed32())) { 8521 if (expected->Is(Type::Signed32())) {
8097 return Add<HForceRepresentation>(number, Representation::Integer32()); 8522 return AddUncasted<HForceRepresentation>(number,
8523 Representation::Integer32());
8098 } 8524 }
8099 return number; 8525 return number;
8100 } 8526 }
8101 8527
8102 8528
8103 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { 8529 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) {
8104 if (value->IsConstant()) { 8530 if (value->IsConstant()) {
8105 HConstant* constant = HConstant::cast(value); 8531 HConstant* constant = HConstant::cast(value);
8106 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); 8532 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone());
8107 if (number.has_value) { 8533 if (number.has_value) {
(...skipping 26 matching lines...) Expand all
8134 // This is already done by HChange. 8560 // This is already done by HChange.
8135 *expected = handle(Type::Union( 8561 *expected = handle(Type::Union(
8136 expected_number, handle(Type::Double(), isolate())), isolate()); 8562 expected_number, handle(Type::Double(), isolate())), isolate());
8137 return value; 8563 return value;
8138 } 8564 }
8139 8565
8140 return value; 8566 return value;
8141 } 8567 }
8142 8568
8143 8569
8144 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( 8570 HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
8145 BinaryOperation* expr, 8571 BinaryOperation* expr,
8146 HValue* left, 8572 HValue* left,
8147 HValue* right) { 8573 HValue* right) {
8148 Handle<Type> left_type = expr->left()->bounds().lower; 8574 Handle<Type> left_type = expr->left()->bounds().lower;
8149 Handle<Type> right_type = expr->right()->bounds().lower; 8575 Handle<Type> right_type = expr->right()->bounds().lower;
8150 Handle<Type> result_type = expr->bounds().lower; 8576 Handle<Type> result_type = expr->bounds().lower;
8151 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); 8577 Maybe<int> fixed_right_arg = expr->fixed_right_arg();
8152 8578
8153 return HGraphBuilder::BuildBinaryOperation(expr->op(), left, right, 8579 HValue* result = HGraphBuilder::BuildBinaryOperation(
8154 left_type, right_type, result_type, fixed_right_arg); 8580 expr->op(), left, right, left_type, right_type,
8581 result_type, fixed_right_arg);
8582 // Add a simulate after instructions with observable side effects, and
8583 // after phis, which are the result of BuildBinaryOperation when we
8584 // inlined some complex subgraph.
8585 if (result->HasObservableSideEffects() || result->IsPhi()) {
8586 Push(result);
8587 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8588 Drop(1);
8589 }
8590 return result;
8155 } 8591 }
8156 8592
8157 8593
8158 HInstruction* HGraphBuilder::BuildBinaryOperation( 8594 HValue* HGraphBuilder::BuildBinaryOperation(
8159 Token::Value op, 8595 Token::Value op,
8160 HValue* left, 8596 HValue* left,
8161 HValue* right, 8597 HValue* right,
8162 Handle<Type> left_type, 8598 Handle<Type> left_type,
8163 Handle<Type> right_type, 8599 Handle<Type> right_type,
8164 Handle<Type> result_type, 8600 Handle<Type> result_type,
8165 Maybe<int> fixed_right_arg, 8601 Maybe<int> fixed_right_arg) {
8166 bool binop_stub) {
8167 8602
8168 Representation left_rep = Representation::FromType(left_type); 8603 Representation left_rep = Representation::FromType(left_type);
8169 Representation right_rep = Representation::FromType(right_type); 8604 Representation right_rep = Representation::FromType(right_type);
8170 8605
8171 bool maybe_string_add = op == Token::ADD && 8606 bool maybe_string_add = op == Token::ADD &&
8172 (left_type->Maybe(Type::String()) || 8607 (left_type->Maybe(Type::String()) ||
8173 right_type->Maybe(Type::String())); 8608 right_type->Maybe(Type::String()));
8174 8609
8175 if (left_type->Is(Type::None())) { 8610 if (left_type->Is(Type::None())) {
8176 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", 8611 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation",
(...skipping 11 matching lines...) Expand all
8188 Deoptimizer::SOFT); 8623 Deoptimizer::SOFT);
8189 right_type = handle(Type::Any(), isolate()); 8624 right_type = handle(Type::Any(), isolate());
8190 } else { 8625 } else {
8191 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); 8626 if (!maybe_string_add) right = TruncateToNumber(right, &right_type);
8192 right_rep = Representation::FromType(right_type); 8627 right_rep = Representation::FromType(right_type);
8193 } 8628 }
8194 8629
8195 // Special case for string addition here. 8630 // Special case for string addition here.
8196 if (op == Token::ADD && 8631 if (op == Token::ADD &&
8197 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { 8632 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
8633 // Validate type feedback for left argument.
8198 if (left_type->Is(Type::String())) { 8634 if (left_type->Is(Type::String())) {
8199 IfBuilder if_isstring(this); 8635 left = BuildCheckString(left);
8200 if_isstring.If<HIsStringAndBranch>(left); 8636 }
8201 if_isstring.Then(); 8637
8202 if_isstring.ElseDeopt("Expected string for LHS of binary operation"); 8638 // Validate type feedback for right argument.
8203 } else if (left_type->Is(Type::Number())) { 8639 if (right_type->Is(Type::String())) {
8640 right = BuildCheckString(right);
8641 }
8642
8643 // Convert left argument as necessary.
8644 if (left_type->Is(Type::Number())) {
8645 ASSERT(right_type->Is(Type::String()));
8204 left = BuildNumberToString(left, left_type); 8646 left = BuildNumberToString(left, left_type);
8205 } else { 8647 } else if (!left_type->Is(Type::String())) {
8206 ASSERT(right_type->Is(Type::String())); 8648 ASSERT(right_type->Is(Type::String()));
8207 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT); 8649 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT);
8208 Add<HPushArgument>(left); 8650 Add<HPushArgument>(left);
8209 Add<HPushArgument>(right); 8651 Add<HPushArgument>(right);
8210 return NewUncasted<HInvokeFunction>(function, 2); 8652 return AddUncasted<HInvokeFunction>(function, 2);
8211 } 8653 }
8212 8654
8213 if (right_type->Is(Type::String())) { 8655 // Convert right argument as necessary.
8214 IfBuilder if_isstring(this); 8656 if (right_type->Is(Type::Number())) {
8215 if_isstring.If<HIsStringAndBranch>(right); 8657 ASSERT(left_type->Is(Type::String()));
8216 if_isstring.Then();
8217 if_isstring.ElseDeopt("Expected string for RHS of binary operation");
8218 } else if (right_type->Is(Type::Number())) {
8219 right = BuildNumberToString(right, right_type); 8658 right = BuildNumberToString(right, right_type);
8220 } else { 8659 } else if (!right_type->Is(Type::String())) {
8221 ASSERT(left_type->Is(Type::String())); 8660 ASSERT(left_type->Is(Type::String()));
8222 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); 8661 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT);
8223 Add<HPushArgument>(left); 8662 Add<HPushArgument>(left);
8224 Add<HPushArgument>(right); 8663 Add<HPushArgument>(right);
8225 return NewUncasted<HInvokeFunction>(function, 2); 8664 return AddUncasted<HInvokeFunction>(function, 2);
8226 } 8665 }
8227 8666
8228 return NewUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_NONE); 8667 return AddUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_NONE);
8229 } 8668 }
8230 8669
8231 if (binop_stub) { 8670 if (graph()->info()->IsStub()) {
8232 left = EnforceNumberType(left, left_type); 8671 left = EnforceNumberType(left, left_type);
8233 right = EnforceNumberType(right, right_type); 8672 right = EnforceNumberType(right, right_type);
8234 } 8673 }
8235 8674
8236 Representation result_rep = Representation::FromType(result_type); 8675 Representation result_rep = Representation::FromType(result_type);
8237 8676
8238 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || 8677 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
8239 (right_rep.IsTagged() && !right_rep.IsSmi()); 8678 (right_rep.IsTagged() && !right_rep.IsSmi());
8240 8679
8241 HInstruction* instr = NULL; 8680 HInstruction* instr = NULL;
8242 // Only the stub is allowed to call into the runtime, since otherwise we would 8681 // Only the stub is allowed to call into the runtime, since otherwise we would
8243 // inline several instructions (including the two pushes) for every tagged 8682 // inline several instructions (including the two pushes) for every tagged
8244 // operation in optimized code, which is more expensive, than a stub call. 8683 // operation in optimized code, which is more expensive, than a stub call.
8245 if (binop_stub && is_non_primitive) { 8684 if (graph()->info()->IsStub() && is_non_primitive) {
8246 HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op)); 8685 HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op));
8247 Add<HPushArgument>(left); 8686 Add<HPushArgument>(left);
8248 Add<HPushArgument>(right); 8687 Add<HPushArgument>(right);
8249 instr = NewUncasted<HInvokeFunction>(function, 2); 8688 instr = AddUncasted<HInvokeFunction>(function, 2);
8250 } else { 8689 } else {
8251 switch (op) { 8690 switch (op) {
8252 case Token::ADD: 8691 case Token::ADD:
8253 instr = NewUncasted<HAdd>(left, right); 8692 instr = AddUncasted<HAdd>(left, right);
8254 break; 8693 break;
8255 case Token::SUB: 8694 case Token::SUB:
8256 instr = NewUncasted<HSub>(left, right); 8695 instr = AddUncasted<HSub>(left, right);
8257 break; 8696 break;
8258 case Token::MUL: 8697 case Token::MUL:
8259 instr = NewUncasted<HMul>(left, right); 8698 instr = AddUncasted<HMul>(left, right);
8260 break; 8699 break;
8261 case Token::MOD: 8700 case Token::MOD: {
8262 instr = NewUncasted<HMod>(left, right, fixed_right_arg); 8701 if (fixed_right_arg.has_value) {
8702 if (right->IsConstant()) {
8703 ASSERT_EQ(fixed_right_arg.value,
8704 HConstant::cast(right)->Integer32Value());
8705 } else {
8706 HConstant* fixed_right = Add<HConstant>(
8707 static_cast<int>(fixed_right_arg.value));
8708 IfBuilder if_same(this);
8709 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ);
8710 if_same.Then();
8711 if_same.ElseDeopt("Unexpected RHS of binary operation");
8712 right = fixed_right;
8713 }
8714 }
8715 instr = AddUncasted<HMod>(left, right);
8263 break; 8716 break;
8717 }
8264 case Token::DIV: 8718 case Token::DIV:
8265 instr = NewUncasted<HDiv>(left, right); 8719 instr = AddUncasted<HDiv>(left, right);
8266 break; 8720 break;
8267 case Token::BIT_XOR: 8721 case Token::BIT_XOR:
8268 case Token::BIT_AND: 8722 case Token::BIT_AND:
8269 instr = NewUncasted<HBitwise>(op, left, right); 8723 instr = AddUncasted<HBitwise>(op, left, right);
8270 break; 8724 break;
8271 case Token::BIT_OR: { 8725 case Token::BIT_OR: {
8272 HValue* operand, *shift_amount; 8726 HValue* operand, *shift_amount;
8273 if (left_type->Is(Type::Signed32()) && 8727 if (left_type->Is(Type::Signed32()) &&
8274 right_type->Is(Type::Signed32()) && 8728 right_type->Is(Type::Signed32()) &&
8275 MatchRotateRight(left, right, &operand, &shift_amount)) { 8729 MatchRotateRight(left, right, &operand, &shift_amount)) {
8276 instr = NewUncasted<HRor>(operand, shift_amount); 8730 instr = AddUncasted<HRor>(operand, shift_amount);
8277 } else { 8731 } else {
8278 instr = NewUncasted<HBitwise>(op, left, right); 8732 instr = AddUncasted<HBitwise>(op, left, right);
8279 } 8733 }
8280 break; 8734 break;
8281 } 8735 }
8282 case Token::SAR: 8736 case Token::SAR:
8283 instr = NewUncasted<HSar>(left, right); 8737 instr = AddUncasted<HSar>(left, right);
8284 break; 8738 break;
8285 case Token::SHR: 8739 case Token::SHR:
8286 instr = NewUncasted<HShr>(left, right); 8740 instr = AddUncasted<HShr>(left, right);
8287 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && 8741 if (FLAG_opt_safe_uint32_operations && instr->IsShr() &&
8288 CanBeZero(right)) { 8742 CanBeZero(right)) {
8289 graph()->RecordUint32Instruction(instr); 8743 graph()->RecordUint32Instruction(instr);
8290 } 8744 }
8291 break; 8745 break;
8292 case Token::SHL: 8746 case Token::SHL:
8293 instr = NewUncasted<HShl>(left, right); 8747 instr = AddUncasted<HShl>(left, right);
8294 break; 8748 break;
8295 default: 8749 default:
8296 UNREACHABLE(); 8750 UNREACHABLE();
8297 } 8751 }
8298 } 8752 }
8299 8753
8300 if (instr->IsBinaryOperation()) { 8754 if (instr->IsBinaryOperation()) {
8301 HBinaryOperation* binop = HBinaryOperation::cast(instr); 8755 HBinaryOperation* binop = HBinaryOperation::cast(instr);
8302 binop->set_observed_input_representation(1, left_rep); 8756 binop->set_observed_input_representation(1, left_rep);
8303 binop->set_observed_input_representation(2, right_rep); 8757 binop->set_observed_input_representation(2, right_rep);
8304 binop->initialize_output_representation(result_rep); 8758 binop->initialize_output_representation(result_rep);
8305 if (binop_stub) { 8759 if (graph()->info()->IsStub()) {
8306 // Stub should not call into stub. 8760 // Stub should not call into stub.
8307 instr->SetFlag(HValue::kCannotBeTagged); 8761 instr->SetFlag(HValue::kCannotBeTagged);
8308 // And should truncate on HForceRepresentation already. 8762 // And should truncate on HForceRepresentation already.
8309 if (left->IsForceRepresentation()) { 8763 if (left->IsForceRepresentation()) {
8310 left->CopyFlag(HValue::kTruncatingToSmi, instr); 8764 left->CopyFlag(HValue::kTruncatingToSmi, instr);
8311 left->CopyFlag(HValue::kTruncatingToInt32, instr); 8765 left->CopyFlag(HValue::kTruncatingToInt32, instr);
8312 } 8766 }
8313 if (right->IsForceRepresentation()) { 8767 if (right->IsForceRepresentation()) {
8314 right->CopyFlag(HValue::kTruncatingToSmi, instr); 8768 right->CopyFlag(HValue::kTruncatingToSmi, instr);
8315 right->CopyFlag(HValue::kTruncatingToInt32, instr); 8769 right->CopyFlag(HValue::kTruncatingToInt32, instr);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
8456 set_current_block(join_block); 8910 set_current_block(join_block);
8457 // We did not materialize any value in the predecessor environments, 8911 // We did not materialize any value in the predecessor environments,
8458 // so there is no need to handle it here. 8912 // so there is no need to handle it here.
8459 } 8913 }
8460 } 8914 }
8461 8915
8462 8916
8463 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { 8917 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
8464 CHECK_ALIVE(VisitForValue(expr->left())); 8918 CHECK_ALIVE(VisitForValue(expr->left()));
8465 CHECK_ALIVE(VisitForValue(expr->right())); 8919 CHECK_ALIVE(VisitForValue(expr->right()));
8466 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); 8920 SetSourcePosition(expr->position());
8467 HValue* right = Pop(); 8921 HValue* right = Pop();
8468 HValue* left = Pop(); 8922 HValue* left = Pop();
8469 HInstruction* instr = BuildBinaryOperation(expr, left, right); 8923 HValue* result = BuildBinaryOperation(expr, left, right);
8470 return ast_context()->ReturnInstruction(instr, expr->id()); 8924 if (FLAG_emit_opt_code_positions && result->IsBinaryOperation()) {
8925 HBinaryOperation::cast(result)->SetOperandPositions(
8926 zone(), expr->left()->position(), expr->right()->position());
8927 }
8928 return ast_context()->ReturnValue(result);
8471 } 8929 }
8472 8930
8473 8931
8474 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, 8932 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
8475 Expression* sub_expr, 8933 Expression* sub_expr,
8476 Handle<String> check) { 8934 Handle<String> check) {
8477 CHECK_ALIVE(VisitForTypeOf(sub_expr)); 8935 CHECK_ALIVE(VisitForTypeOf(sub_expr));
8478 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); 8936 SetSourcePosition(expr->position());
8479 HValue* value = Pop(); 8937 HValue* value = Pop();
8480 HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check); 8938 HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
8481 return ast_context()->ReturnControl(instr, expr->id()); 8939 return ast_context()->ReturnControl(instr, expr->id());
8482 } 8940 }
8483 8941
8484 8942
8485 static bool IsLiteralCompareBool(Isolate* isolate, 8943 static bool IsLiteralCompareBool(Isolate* isolate,
8486 HValue* left, 8944 HValue* left,
8487 Token::Value op, 8945 Token::Value op,
8488 HValue* right) { 8946 HValue* right) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
8530 Handle<Type> left_type = expr->left()->bounds().lower; 8988 Handle<Type> left_type = expr->left()->bounds().lower;
8531 Handle<Type> right_type = expr->right()->bounds().lower; 8989 Handle<Type> right_type = expr->right()->bounds().lower;
8532 Handle<Type> combined_type = expr->combined_type(); 8990 Handle<Type> combined_type = expr->combined_type();
8533 Representation combined_rep = Representation::FromType(combined_type); 8991 Representation combined_rep = Representation::FromType(combined_type);
8534 Representation left_rep = Representation::FromType(left_type); 8992 Representation left_rep = Representation::FromType(left_type);
8535 Representation right_rep = Representation::FromType(right_type); 8993 Representation right_rep = Representation::FromType(right_type);
8536 8994
8537 CHECK_ALIVE(VisitForValue(expr->left())); 8995 CHECK_ALIVE(VisitForValue(expr->left()));
8538 CHECK_ALIVE(VisitForValue(expr->right())); 8996 CHECK_ALIVE(VisitForValue(expr->right()));
8539 8997
8998 if (FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
8999
8540 HValue* right = Pop(); 9000 HValue* right = Pop();
8541 HValue* left = Pop(); 9001 HValue* left = Pop();
8542 Token::Value op = expr->op(); 9002 Token::Value op = expr->op();
8543 9003
8544 if (IsLiteralCompareBool(isolate(), left, op, right)) { 9004 if (IsLiteralCompareBool(isolate(), left, op, right)) {
8545 HCompareObjectEqAndBranch* result = 9005 HCompareObjectEqAndBranch* result =
8546 New<HCompareObjectEqAndBranch>(left, right); 9006 New<HCompareObjectEqAndBranch>(left, right);
8547 return ast_context()->ReturnControl(result, expr->id()); 9007 return ast_context()->ReturnControl(result, expr->id());
8548 } 9008 }
8549 9009
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
8608 switch (op) { 9068 switch (op) {
8609 case Token::EQ: 9069 case Token::EQ:
8610 case Token::EQ_STRICT: { 9070 case Token::EQ_STRICT: {
8611 // Can we get away with map check and not instance type check? 9071 // Can we get away with map check and not instance type check?
8612 if (combined_type->IsClass()) { 9072 if (combined_type->IsClass()) {
8613 Handle<Map> map = combined_type->AsClass(); 9073 Handle<Map> map = combined_type->AsClass();
8614 AddCheckMap(left, map); 9074 AddCheckMap(left, map);
8615 AddCheckMap(right, map); 9075 AddCheckMap(right, map);
8616 HCompareObjectEqAndBranch* result = 9076 HCompareObjectEqAndBranch* result =
8617 New<HCompareObjectEqAndBranch>(left, right); 9077 New<HCompareObjectEqAndBranch>(left, right);
9078 if (FLAG_emit_opt_code_positions) {
9079 result->set_operand_position(zone(), 0, expr->left()->position());
9080 result->set_operand_position(zone(), 1, expr->right()->position());
9081 }
8618 return ast_context()->ReturnControl(result, expr->id()); 9082 return ast_context()->ReturnControl(result, expr->id());
8619 } else { 9083 } else {
8620 BuildCheckHeapObject(left); 9084 BuildCheckHeapObject(left);
8621 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_SPEC_OBJECT); 9085 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_SPEC_OBJECT);
8622 BuildCheckHeapObject(right); 9086 BuildCheckHeapObject(right);
8623 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_SPEC_OBJECT); 9087 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_SPEC_OBJECT);
8624 HCompareObjectEqAndBranch* result = 9088 HCompareObjectEqAndBranch* result =
8625 New<HCompareObjectEqAndBranch>(left, right); 9089 New<HCompareObjectEqAndBranch>(left, right);
8626 return ast_context()->ReturnControl(result, expr->id()); 9090 return ast_context()->ReturnControl(result, expr->id());
8627 } 9091 }
(...skipping 21 matching lines...) Expand all
8649 } else { 9113 } else {
8650 if (combined_rep.IsTagged() || combined_rep.IsNone()) { 9114 if (combined_rep.IsTagged() || combined_rep.IsNone()) {
8651 HCompareGeneric* result = New<HCompareGeneric>(left, right, op); 9115 HCompareGeneric* result = New<HCompareGeneric>(left, right, op);
8652 result->set_observed_input_representation(1, left_rep); 9116 result->set_observed_input_representation(1, left_rep);
8653 result->set_observed_input_representation(2, right_rep); 9117 result->set_observed_input_representation(2, right_rep);
8654 return ast_context()->ReturnInstruction(result, expr->id()); 9118 return ast_context()->ReturnInstruction(result, expr->id());
8655 } else { 9119 } else {
8656 HCompareNumericAndBranch* result = 9120 HCompareNumericAndBranch* result =
8657 New<HCompareNumericAndBranch>(left, right, op); 9121 New<HCompareNumericAndBranch>(left, right, op);
8658 result->set_observed_input_representation(left_rep, right_rep); 9122 result->set_observed_input_representation(left_rep, right_rep);
9123 if (FLAG_emit_opt_code_positions) {
9124 result->SetOperandPositions(zone(),
9125 expr->left()->position(),
9126 expr->right()->position());
9127 }
8659 return ast_context()->ReturnControl(result, expr->id()); 9128 return ast_context()->ReturnControl(result, expr->id());
8660 } 9129 }
8661 } 9130 }
8662 } 9131 }
8663 9132
8664 9133
8665 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, 9134 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
8666 Expression* sub_expr, 9135 Expression* sub_expr,
8667 NilValue nil) { 9136 NilValue nil) {
8668 ASSERT(!HasStackOverflow()); 9137 ASSERT(!HasStackOverflow());
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
9257 9726
9258 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar( 9727 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
9259 CallRuntime* call) { 9728 CallRuntime* call) {
9260 ASSERT(call->arguments()->length() == 3); 9729 ASSERT(call->arguments()->length() == 3);
9261 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9730 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9262 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 9731 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9263 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); 9732 CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
9264 HValue* value = Pop(); 9733 HValue* value = Pop();
9265 HValue* index = Pop(); 9734 HValue* index = Pop();
9266 HValue* string = Pop(); 9735 HValue* string = Pop();
9267 HSeqStringSetChar* result = New<HSeqStringSetChar>( 9736 Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string,
9268 String::ONE_BYTE_ENCODING, string, index, value); 9737 index, value);
9269 return ast_context()->ReturnInstruction(result, call->id()); 9738 Add<HSimulate>(call->id(), FIXED_SIMULATE);
9739 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
9270 } 9740 }
9271 9741
9272 9742
9273 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar( 9743 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
9274 CallRuntime* call) { 9744 CallRuntime* call) {
9275 ASSERT(call->arguments()->length() == 3); 9745 ASSERT(call->arguments()->length() == 3);
9276 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9746 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9277 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 9747 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9278 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); 9748 CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
9279 HValue* value = Pop(); 9749 HValue* value = Pop();
9280 HValue* index = Pop(); 9750 HValue* index = Pop();
9281 HValue* string = Pop(); 9751 HValue* string = Pop();
9282 HSeqStringSetChar* result = New<HSeqStringSetChar>( 9752 Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string,
9283 String::TWO_BYTE_ENCODING, string, index, value); 9753 index, value);
9284 return ast_context()->ReturnInstruction(result, call->id()); 9754 Add<HSimulate>(call->id(), FIXED_SIMULATE);
9755 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
9285 } 9756 }
9286 9757
9287 9758
9288 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { 9759 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
9289 ASSERT(call->arguments()->length() == 2); 9760 ASSERT(call->arguments()->length() == 2);
9290 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9761 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9291 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 9762 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9292 HValue* value = Pop(); 9763 HValue* value = Pop();
9293 HValue* object = Pop(); 9764 HValue* object = Pop();
9294 // Check if object is a not a smi. 9765 // Check if object is a not a smi.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
9368 return ast_context()->ReturnControl(result, call->id()); 9839 return ast_context()->ReturnControl(result, call->id());
9369 } 9840 }
9370 9841
9371 9842
9372 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { 9843 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) {
9373 // %_Log is ignored in optimized code. 9844 // %_Log is ignored in optimized code.
9374 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 9845 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
9375 } 9846 }
9376 9847
9377 9848
9378 // Fast support for Math.random().
9379 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
9380 HGlobalObject* global_object = Add<HGlobalObject>();
9381 HRandom* result = New<HRandom>(global_object);
9382 return ast_context()->ReturnInstruction(result, call->id());
9383 }
9384
9385
9386 // Fast support for StringAdd. 9849 // Fast support for StringAdd.
9387 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { 9850 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
9388 ASSERT_EQ(2, call->arguments()->length()); 9851 ASSERT_EQ(2, call->arguments()->length());
9389 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9852 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9390 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 9853 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9391 HValue* right = Pop(); 9854 HValue* right = Pop();
9392 HValue* left = Pop(); 9855 HValue* left = Pop();
9393 HInstruction* result = New<HStringAdd>(left, right, STRING_ADD_CHECK_BOTH); 9856 HInstruction* result = New<HStringAdd>(left, right, STRING_ADD_CHECK_BOTH);
9394 return ast_context()->ReturnInstruction(result, call->id()); 9857 return ast_context()->ReturnInstruction(result, call->id());
9395 } 9858 }
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
9873 } else { 10336 } else {
9874 CodeStub::Major major_key = info->code_stub()->MajorKey(); 10337 CodeStub::Major major_key = info->code_stub()->MajorKey();
9875 PrintStringProperty("name", CodeStub::MajorName(major_key, false)); 10338 PrintStringProperty("name", CodeStub::MajorName(major_key, false));
9876 PrintStringProperty("method", "stub"); 10339 PrintStringProperty("method", "stub");
9877 } 10340 }
9878 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); 10341 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis()));
9879 } 10342 }
9880 10343
9881 10344
9882 void HTracer::TraceLithium(const char* name, LChunk* chunk) { 10345 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
9883 ASSERT(!FLAG_concurrent_recompilation); 10346 ASSERT(!chunk->isolate()->concurrent_recompilation_enabled());
9884 AllowHandleDereference allow_deref; 10347 AllowHandleDereference allow_deref;
9885 AllowDeferredHandleDereference allow_deferred_deref; 10348 AllowDeferredHandleDereference allow_deferred_deref;
9886 Trace(name, chunk->graph(), chunk); 10349 Trace(name, chunk->graph(), chunk);
9887 } 10350 }
9888 10351
9889 10352
9890 void HTracer::TraceHydrogen(const char* name, HGraph* graph) { 10353 void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
9891 ASSERT(!FLAG_concurrent_recompilation); 10354 ASSERT(!graph->isolate()->concurrent_recompilation_enabled());
9892 AllowHandleDereference allow_deref; 10355 AllowHandleDereference allow_deref;
9893 AllowDeferredHandleDereference allow_deferred_deref; 10356 AllowDeferredHandleDereference allow_deferred_deref;
9894 Trace(name, graph, NULL); 10357 Trace(name, graph, NULL);
9895 } 10358 }
9896 10359
9897 10360
9898 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) { 10361 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
9899 Tag tag(this, "cfg"); 10362 Tag tag(this, "cfg");
9900 PrintStringProperty("name", name); 10363 PrintStringProperty("name", name);
9901 const ZoneList<HBasicBlock*>* blocks = graph->blocks(); 10364 const ZoneList<HBasicBlock*>* blocks = graph->blocks();
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
9965 trace_.Add(" "); 10428 trace_.Add(" ");
9966 phi->PrintTo(&trace_); 10429 phi->PrintTo(&trace_);
9967 trace_.Add("\n"); 10430 trace_.Add("\n");
9968 } 10431 }
9969 } 10432 }
9970 10433
9971 { 10434 {
9972 Tag HIR_tag(this, "HIR"); 10435 Tag HIR_tag(this, "HIR");
9973 for (HInstructionIterator it(current); !it.Done(); it.Advance()) { 10436 for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
9974 HInstruction* instruction = it.Current(); 10437 HInstruction* instruction = it.Current();
9975 int bci = 0; 10438 int bci = FLAG_emit_opt_code_positions && instruction->has_position() ?
10439 instruction->position() : 0;
9976 int uses = instruction->UseCount(); 10440 int uses = instruction->UseCount();
9977 PrintIndent(); 10441 PrintIndent();
9978 trace_.Add("%d %d ", bci, uses); 10442 trace_.Add("%d %d ", bci, uses);
9979 instruction->PrintNameTo(&trace_); 10443 instruction->PrintNameTo(&trace_);
9980 trace_.Add(" "); 10444 trace_.Add(" ");
9981 instruction->PrintTo(&trace_); 10445 instruction->PrintTo(&trace_);
9982 trace_.Add(" <|@\n"); 10446 trace_.Add(" <|@\n");
9983 } 10447 }
9984 } 10448 }
9985 10449
9986 10450
9987 if (chunk != NULL) { 10451 if (chunk != NULL) {
9988 Tag LIR_tag(this, "LIR"); 10452 Tag LIR_tag(this, "LIR");
9989 int first_index = current->first_instruction_index(); 10453 int first_index = current->first_instruction_index();
9990 int last_index = current->last_instruction_index(); 10454 int last_index = current->last_instruction_index();
9991 if (first_index != -1 && last_index != -1) { 10455 if (first_index != -1 && last_index != -1) {
9992 const ZoneList<LInstruction*>* instructions = chunk->instructions(); 10456 const ZoneList<LInstruction*>* instructions = chunk->instructions();
9993 for (int i = first_index; i <= last_index; ++i) { 10457 for (int i = first_index; i <= last_index; ++i) {
9994 LInstruction* linstr = instructions->at(i); 10458 LInstruction* linstr = instructions->at(i);
9995 if (linstr != NULL) { 10459 if (linstr != NULL) {
9996 PrintIndent(); 10460 PrintIndent();
9997 trace_.Add("%d ", 10461 trace_.Add("%d ",
9998 LifetimePosition::FromInstructionIndex(i).Value()); 10462 LifetimePosition::FromInstructionIndex(i).Value());
9999 linstr->PrintTo(&trace_); 10463 linstr->PrintTo(&trace_);
10464 trace_.Add(" [hir:");
10465 linstr->hydrogen_value()->PrintNameTo(&trace_);
10466 trace_.Add("]");
10000 trace_.Add(" <|@\n"); 10467 trace_.Add(" <|@\n");
10001 } 10468 }
10002 } 10469 }
10003 } 10470 }
10004 } 10471 }
10005 } 10472 }
10006 } 10473 }
10007 10474
10008 10475
10009 void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) { 10476 void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
10168 if (ShouldProduceTraceOutput()) { 10635 if (ShouldProduceTraceOutput()) {
10169 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 10636 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
10170 } 10637 }
10171 10638
10172 #ifdef DEBUG 10639 #ifdef DEBUG
10173 graph_->Verify(false); // No full verify. 10640 graph_->Verify(false); // No full verify.
10174 #endif 10641 #endif
10175 } 10642 }
10176 10643
10177 } } // namespace v8::internal 10644 } } // namespace v8::internal
OLDNEW
« include/v8-platform.h ('K') | « src/hydrogen.h ('k') | src/hydrogen-dehoist.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698